|
|
|
|
@ -468,19 +468,37 @@ func (ns *Impl) injectInbound(p *packet.Parsed, t *tstun.Wrapper) filter.Respons |
|
|
|
|
return filter.DropSilently |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func netaddrIPFromNetstackIP(s tcpip.Address) netaddr.IP { |
|
|
|
|
switch len(s) { |
|
|
|
|
case 4: |
|
|
|
|
return netaddr.IPv4(s[0], s[1], s[2], s[3]) |
|
|
|
|
case 16: |
|
|
|
|
var a [16]byte |
|
|
|
|
copy(a[:], s) |
|
|
|
|
return netaddr.IPFrom16(a) |
|
|
|
|
} |
|
|
|
|
return netaddr.IP{} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (ns *Impl) acceptTCP(r *tcp.ForwarderRequest) { |
|
|
|
|
reqDetails := r.ID() |
|
|
|
|
if debugNetstack { |
|
|
|
|
ns.logf("[v2] TCP ForwarderRequest: %s", stringifyTEI(reqDetails)) |
|
|
|
|
} |
|
|
|
|
dialAddr := reqDetails.LocalAddress |
|
|
|
|
dialNetAddr, _ := netaddr.FromStdIP(net.IP(dialAddr)) |
|
|
|
|
isTailscaleIP := tsaddr.IsTailscaleIP(dialNetAddr) |
|
|
|
|
clientRemoteIP := netaddrIPFromNetstackIP(reqDetails.RemoteAddress) |
|
|
|
|
if !clientRemoteIP.IsValid() { |
|
|
|
|
ns.logf("invalid RemoteAddress in TCP ForwarderRequest: %s", stringifyTEI(reqDetails)) |
|
|
|
|
r.Complete(true) |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
dialIP := netaddrIPFromNetstackIP(reqDetails.LocalAddress) |
|
|
|
|
isTailscaleIP := tsaddr.IsTailscaleIP(dialIP) |
|
|
|
|
defer func() { |
|
|
|
|
if !isTailscaleIP { |
|
|
|
|
// if this is a subnet IP, we added this in before the TCP handshake
|
|
|
|
|
// so netstack is happy TCP-handshaking as a subnet IP
|
|
|
|
|
ns.removeSubnetAddress(dialNetAddr) |
|
|
|
|
ns.removeSubnetAddress(dialIP) |
|
|
|
|
} |
|
|
|
|
}() |
|
|
|
|
var wq waiter.Queue |
|
|
|
|
@ -490,21 +508,31 @@ func (ns *Impl) acceptTCP(r *tcp.ForwarderRequest) { |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
r.Complete(false) |
|
|
|
|
|
|
|
|
|
// Asynchronously start the TCP handshake. Note that the
|
|
|
|
|
// gonet.TCPConn methods c.RemoteAddr() and c.LocalAddr() will
|
|
|
|
|
// return nil until the handshake actually completes. But we
|
|
|
|
|
// have the remote address in reqDetails instead, so we don't
|
|
|
|
|
// use RemoteAddr. The byte copies in both directions in
|
|
|
|
|
// forwardTCP will block until the TCP handshake is complete.
|
|
|
|
|
c := gonet.NewTCPConn(&wq, ep) |
|
|
|
|
|
|
|
|
|
if ns.ForwardTCPIn != nil { |
|
|
|
|
ns.ForwardTCPIn(c, reqDetails.LocalPort) |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
if isTailscaleIP { |
|
|
|
|
dialAddr = tcpip.Address(net.ParseIP("127.0.0.1")).To4() |
|
|
|
|
dialIP = netaddr.IPv4(127, 0, 0, 1) |
|
|
|
|
} |
|
|
|
|
ns.forwardTCP(c, &wq, dialAddr, reqDetails.LocalPort) |
|
|
|
|
dialAddr := netaddr.IPPortFrom(dialIP, uint16(reqDetails.LocalPort)) |
|
|
|
|
ns.forwardTCP(c, clientRemoteIP, &wq, dialAddr) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (ns *Impl) forwardTCP(client *gonet.TCPConn, wq *waiter.Queue, dialAddr tcpip.Address, dialPort uint16) { |
|
|
|
|
func (ns *Impl) forwardTCP(client *gonet.TCPConn, clientRemoteIP netaddr.IP, wq *waiter.Queue, dialAddr netaddr.IPPort) { |
|
|
|
|
defer client.Close() |
|
|
|
|
dialAddrStr := net.JoinHostPort(dialAddr.String(), strconv.Itoa(int(dialPort))) |
|
|
|
|
dialAddrStr := dialAddr.String() |
|
|
|
|
ns.logf("[v2] netstack: forwarding incoming connection to %s", dialAddrStr) |
|
|
|
|
|
|
|
|
|
ctx, cancel := context.WithCancel(context.Background()) |
|
|
|
|
defer cancel() |
|
|
|
|
waitEntry, notifyCh := waiter.NewChannelEntry(nil) |
|
|
|
|
@ -530,7 +558,6 @@ func (ns *Impl) forwardTCP(client *gonet.TCPConn, wq *waiter.Queue, dialAddr tcp |
|
|
|
|
defer server.Close() |
|
|
|
|
backendLocalAddr := server.LocalAddr().(*net.TCPAddr) |
|
|
|
|
backendLocalIPPort, _ := netaddr.FromStdAddr(backendLocalAddr.IP, backendLocalAddr.Port, backendLocalAddr.Zone) |
|
|
|
|
clientRemoteIP, _ := netaddr.FromStdIP(client.RemoteAddr().(*net.TCPAddr).IP) |
|
|
|
|
ns.e.RegisterIPPortIdentity(backendLocalIPPort, clientRemoteIP) |
|
|
|
|
defer ns.e.UnregisterIPPortIdentity(backendLocalIPPort) |
|
|
|
|
connClosed := make(chan error, 2) |
|
|
|
|
|