Source File
tcpip.go
Belonging Package
golang.org/x/crypto/ssh
package ssh
import (
)
const openSSHPrefix = "OpenSSH_"
var portRandomizer = rand.New(rand.NewSource(time.Now().UnixNano()))
func ( *Client) ( *net.TCPAddr) (net.Listener, error) {
var net.Listener
var error
const = 10
for := 0; < ; ++ {
:= *
.Port = 1024 + portRandomizer.Intn(60000)
, = .ListenTCP(&)
if == nil {
.Port = .Port
return ,
}
}
return nil, fmt.Errorf("ssh: listen on random port failed after %d tries: %v", , )
}
type channelForwardMsg struct {
addr string
rport uint32
}
func ( *Client) () {
go .forwards.handleChannels(.HandleChannelOpen("forwarded-tcpip"))
go .forwards.handleChannels(.HandleChannelOpen("forwarded-streamlocal@openssh.com"))
}
func ( *Client) ( *net.TCPAddr) (net.Listener, error) {
.handleForwardsOnce.Do(.handleForwards)
if .Port == 0 && isBrokenOpenSSHVersion(string(.ServerVersion())) {
return .autoPortListenWorkaround()
}
:= channelForwardMsg{
.IP.String(),
uint32(.Port),
:= .forwards.add()
return &tcpListener{, , }, nil
}
type forwardList struct {
sync.Mutex
entries []forwardEntry
}
type forward struct {
newCh NewChannel // the ssh client channel underlying this forward
raddr net.Addr // the raddr of the incoming connection
}
func ( *forwardList) ( net.Addr) chan forward {
.Lock()
defer .Unlock()
:= forwardEntry{
laddr: ,
c: make(chan forward, 1),
}
.entries = append(.entries, )
return .c
}
type forwardedTCPPayload struct {
Addr string
Port uint32
OriginAddr string
OriginPort uint32
}
func ( string, uint32) (*net.TCPAddr, error) {
if == 0 || > 65535 {
return nil, fmt.Errorf("ssh: port number out of range: %d", )
}
:= net.ParseIP(string())
if == nil {
return nil, fmt.Errorf("ssh: cannot parse IP address %q", )
}
return &net.TCPAddr{IP: , Port: int()}, nil
}
func ( *forwardList) ( <-chan NewChannel) {
for := range {
var (
net.Addr
net.Addr
error
)
switch := .ChannelType(); {
case "forwarded-tcpip":
var forwardedTCPPayload
if = Unmarshal(.ExtraData(), &); != nil {
.Reject(ConnectionFailed, "could not parse forwarded-tcpip payload: "+.Error())
continue
}
, = parseTCPAddr(.Addr, .Port)
if != nil {
.Reject(ConnectionFailed, .Error())
continue
}
, = parseTCPAddr(.OriginAddr, .OriginPort)
if != nil {
.Reject(ConnectionFailed, .Error())
continue
}
case "forwarded-streamlocal@openssh.com":
var forwardedStreamLocalPayload
if = Unmarshal(.ExtraData(), &); != nil {
.Reject(ConnectionFailed, "could not parse forwarded-streamlocal@openssh.com payload: "+.Error())
continue
}
= &net.UnixAddr{
Name: .SocketPath,
Net: "unix",
}
= &net.UnixAddr{
Name: "@",
Net: "unix",
}
default:
panic(fmt.Errorf("ssh: unknown channel type %s", ))
}
.Reject(Prohibited, "no forward for address")
continue
}
}
}
func ( *forwardList) () {
.Lock()
defer .Unlock()
for , := range .entries {
close(.c)
}
.entries = nil
}
func ( *forwardList) (, net.Addr, NewChannel) bool {
.Lock()
defer .Unlock()
for , := range .entries {
if .Network() == .laddr.Network() && .String() == .laddr.String() {
.c <- forward{newCh: , raddr: }
return true
}
}
return false
}
type tcpListener struct {
laddr *net.TCPAddr
conn *Client
in <-chan forward
}
func ( *tcpListener) () error {
:= channelForwardMsg{
.laddr.IP.String(),
uint32(.laddr.Port),
}
func ( *tcpListener) () net.Addr {
return .laddr
}
:= &net.TCPAddr{
IP: net.IPv4zero,
Port: 0,
}
return &chanConn{
Channel: ,
laddr: ,
raddr: ,
}, nil
case "unix":
var error
, = .dialStreamLocal()
if != nil {
return nil,
}
return &chanConn{
Channel: ,
laddr: &net.UnixAddr{
Name: "@",
Net: "unix",
},
raddr: &net.UnixAddr{
Name: ,
Net: "unix",
},
}, nil
default:
return nil, fmt.Errorf("ssh: unsupported protocol: %s", )
}
}
type channelOpenDirectMsg struct {
raddr string
rport uint32
laddr string
lport uint32
}
func ( *Client) ( string, int, string, int) (Channel, error) {
:= channelOpenDirectMsg{
raddr: ,
rport: uint32(),
laddr: ,
lport: uint32(),
}
, , := .OpenChannel("direct-tcpip", Marshal(&))
if != nil {
return nil,
}
go DiscardRequests()
return ,
}
type tcpChan struct {
Channel // the backing channel
}
func ( *chanConn) ( time.Time) error {
if := .SetReadDeadline(); != nil {
return
}
return .SetWriteDeadline()
}
![]() |
The pages are generated with Golds v0.3.2-preview. (GOOS=darwin GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |