1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
|
package forwarder
import (
"context"
"fmt"
"net"
"sync"
"github.com/containers/gvisor-tap-vsock/pkg/tcpproxy"
log "github.com/sirupsen/logrus"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/adapters/gonet"
"gvisor.dev/gvisor/pkg/tcpip/stack"
"gvisor.dev/gvisor/pkg/tcpip/transport/tcp"
"gvisor.dev/gvisor/pkg/waiter"
)
const linkLocalSubnet = "169.254.0.0/16"
func TCP(s *stack.Stack, nat map[tcpip.Address]tcpip.Address, natLock *sync.Mutex) *tcp.Forwarder {
return tcp.NewForwarder(s, 0, 10, func(r *tcp.ForwarderRequest) {
localAddress := r.ID().LocalAddress
if linkLocal().Contains(localAddress) {
r.Complete(true)
return
}
natLock.Lock()
if replaced, ok := nat[localAddress]; ok {
localAddress = replaced
}
natLock.Unlock()
outbound, err := net.Dial("tcp", fmt.Sprintf("%s:%d", localAddress, r.ID().LocalPort))
if err != nil {
log.Tracef("net.Dial() = %v", err)
r.Complete(true)
return
}
var wq waiter.Queue
ep, tcpErr := r.CreateEndpoint(&wq)
r.Complete(false)
if tcpErr != nil {
if _, ok := tcpErr.(*tcpip.ErrConnectionRefused); ok {
// transient error
log.Debugf("r.CreateEndpoint() = %v", tcpErr)
} else {
log.Errorf("r.CreateEndpoint() = %v", tcpErr)
}
return
}
remote := tcpproxy.DialProxy{
DialContext: func(_ context.Context, _, _ string) (net.Conn, error) {
return outbound, nil
},
}
remote.HandleConn(gonet.NewTCPConn(&wq, ep))
})
}
func linkLocal() *tcpip.Subnet {
_, parsedSubnet, _ := net.ParseCIDR(linkLocalSubnet) // CoreOS VM tries to connect to Amazon EC2 metadata service
subnet, _ := tcpip.NewSubnet(tcpip.AddrFromSlice(parsedSubnet.IP), tcpip.MaskFromBytes(parsedSubnet.Mask))
return &subnet
}
|