--- cryptolib/ssh/tcpip.go 2023-11-18 22:20:50.609146922 +0300 +++ pkg/proto/ssh/tcpip.go 2023-11-18 22:19:08.891684669 +0300 @@ -101,14 +101,18 @@ // ListenTCP requests the remote peer open a listening socket // on laddr. Incoming connections will be available by calling // Accept on the returned net.Listener. -func (c *Client) ListenTCP(laddr *net.TCPAddr) (net.Listener, error) { +func (c *Client) ListenTCP(laddr *net.TCPAddr, fakeHost ...string) (net.Listener, error) { c.handleForwardsOnce.Do(c.handleForwards) if laddr.Port == 0 && isBrokenOpenSSHVersion(string(c.ServerVersion())) { return c.autoPortListenWorkaround(laddr) } + host := laddr.IP.String() + if len(fakeHost) > 0 { + host = fakeHost[0] + } m := channelForwardMsg{ - laddr.IP.String(), + host, uint32(laddr.Port), } // send message @@ -133,7 +137,12 @@ } // Register this forward, using the port number we obtained. - ch := c.forwards.add(laddr) + var ch chan forward + if len(fakeHost) > 0 { + ch = c.forwards.add(laddr, fakeHost[0]) + } else { + ch = c.forwards.add(laddr) + } return &tcpListener{laddr, c, ch}, nil } @@ -142,7 +151,9 @@ // forward requests and the tcpListeners. type forwardList struct { sync.Mutex - entries []forwardEntry + fdm sync.RWMutex + fakeDomainsMap map[string]string + entries []forwardEntry } // forwardEntry represents an established mapping of a laddr on a @@ -160,17 +171,30 @@ raddr net.Addr // the raddr of the incoming connection } -func (l *forwardList) add(addr net.Addr) chan forward { +func (l *forwardList) add(addr net.Addr, fakeHost ...string) chan forward { l.Lock() defer l.Unlock() f := forwardEntry{ laddr: addr, c: make(chan forward, 1), } + if len(fakeHost) > 0 { + if l.fakeDomainsMap == nil { + l.fakeDomainsMap = make(map[string]string) + } + defer l.fdm.Unlock() + l.fdm.Lock() + l.fakeDomainsMap[fakeHost[0]] = l.ipFromAddr(addr) + } l.entries = append(l.entries, f) return f.c } +func (l *forwardList) ipFromAddr(addr net.Addr) string { + host, _, _ := net.SplitHostPort(addr.String()) + return host +} + // See RFC 4254, section 7.2 type forwardedTCPPayload struct { Addr string @@ -206,6 +230,15 @@ continue } + l.fdm.RLock() + if addr, ok := l.fakeDomainsMap[payload.Addr]; ok { + payload.Addr = addr + } + if addr, ok := l.fakeDomainsMap[payload.OriginAddr]; ok { + payload.OriginAddr = addr + } + l.fdm.RUnlock() + // RFC 4254 section 7.2 specifies that incoming // addresses should list the address, in string // format. It is implied that this should be an IP