2015-05-30 15:19:10 +00:00
package easyssh
import (
"net"
"golang.org/x/crypto/ssh"
)
// Client wraps an SSH Client
type Client struct {
* ssh . Client
}
// Dial starts an ssh connection to the provided server
func Dial ( network , addr string , config * ssh . ClientConfig ) ( * Client , error ) {
c , err := ssh . Dial ( network , addr , config )
return & Client { c } , err
}
// NewClient returns a new SSH Client.
func NewClient ( c ssh . Conn , chans <- chan ssh . NewChannel , reqs <- chan * ssh . Request ) * Client {
client := ssh . NewClient ( c , chans , reqs )
return & Client { client }
}
// LocalForward performs a port forwarding over the ssh connection - ssh -L. Client will bind to the local address, and will tunnel those requests to host addr
func ( c * Client ) LocalForward ( laddr , raddr * net . TCPAddr ) error {
ln , err := net . ListenTCP ( "tcp" , laddr ) //tie to the client connection
if err != nil {
println ( err . Error ( ) )
return err
}
2016-07-30 12:35:10 +00:00
logger . Println ( "Listening on address: " , ln . Addr ( ) . String ( ) )
2015-05-30 15:19:10 +00:00
quit := make ( chan bool )
go func ( ) { // Handle incoming connections on this new listener
for {
select {
case <- quit :
return
default :
conn , err := ln . Accept ( )
if err != nil { // Unable to accept new connection - listener likely closed
continue
}
go func ( conn net . Conn ) {
conn2 , err := c . DialTCP ( "tcp" , laddr , raddr )
if err != nil {
return
}
go func ( conn , conn2 net . Conn ) {
close := func ( ) {
conn . Close ( )
conn2 . Close ( )
}
go CopyReadWriters ( conn , conn2 , close )
} ( conn , conn2 )
} ( conn )
}
}
} ( )
c . Wait ( )
ln . Close ( )
quit <- true
return nil
}
// RemoteForward forwards a remote port - ssh -R
func ( c * Client ) RemoteForward ( remote , local string ) error {
ln , err := c . Listen ( "tcp" , remote )
if err != nil {
return err
}
quit := make ( chan bool )
go func ( ) { // Handle incoming connections on this new listener
for {
select {
case <- quit :
return
default :
conn , err := ln . Accept ( )
if err != nil { // Unable to accept new connection - listener likely closed
continue
}
conn2 , err := net . Dial ( "tcp" , local )
if err != nil {
continue
}
close := func ( ) {
conn . Close ( )
conn2 . Close ( )
}
go CopyReadWriters ( conn , conn2 , close )
}
}
} ( )
c . Wait ( )
ln . Close ( )
quit <- true
return nil
}
// HandleOpenChannel requests that the remote end accept a channel request and if accepted,
// passes the newly opened channel and requests to the provided handler
func ( c * Client ) HandleOpenChannel ( channelName string , handler ChannelMultipleRequestsHandler , data ... byte ) error {
ch , reqs , err := c . OpenChannel ( channelName , data )
if err != nil {
return err
}
handler . HandleMultipleRequests ( reqs , c . Conn , channelName , ch )
return nil
}
// HandleOpenChannelFunc requests that the remote end accept a channel request and if accepted,
// passes the newly opened channel and requests to the provided handler function
func ( c * Client ) HandleOpenChannelFunc ( channelName string , handler ChannelMultipleRequestsHandlerFunc , data ... byte ) error {
return c . HandleOpenChannel ( channelName , ChannelMultipleRequestsHandlerFunc ( handler ) , data ... )
}