diff --git a/core/chain.go b/core/chain.go index 57d4ba70..70810587 100644 --- a/core/chain.go +++ b/core/chain.go @@ -65,17 +65,12 @@ func (c *Chain) DialContext(ctx context.Context, network, address string) (conn } func (c *Chain) dial(ctx context.Context, network, address string) (net.Conn, error) { - route, err := c.selectRoute() - if err != nil { - return nil, err - } - ipAddr := address if address != "" { ipAddr = c.resolve(address) } - if route.IsEmpty() { + if c.IsEmpty() { switch network { case "udp", "udp4", "udp6": if address == "" { @@ -90,12 +85,12 @@ func (c *Chain) dial(ctx context.Context, network, address string) (net.Conn, er return d.DialContext(ctx, network, ipAddr) } - conn, err := route.getConn(ctx) + conn, err := c.getConn(ctx) if err != nil { return nil, err } - cc, err := route.Node().Client.ConnectContext(ctx, conn, network, ipAddr) + cc, err := c.Node().Client.ConnectContext(ctx, conn, network, ipAddr) if err != nil { conn.Close() return nil, err @@ -122,12 +117,7 @@ func (c *Chain) Conn() (conn net.Conn, err error) { } for i := 0; i < retries; i++ { - var route *Chain - route, err = c.selectRoute() - if err != nil { - continue - } - conn, err = route.getConn(ctx) + conn, err = c.getConn(ctx) if err == nil { break } @@ -150,15 +140,3 @@ func (c *Chain) getConn(_ context.Context) (conn net.Conn, err error) { conn = cc return } - -func (c *Chain) selectRoute() (route *Chain, err error) { - if c.IsEmpty() { - return newRoute(), nil - } - if c.isRoute { - return c, nil - } - route = newRoute() - route.SetNode(c.node) - return -} diff --git a/core/socks.go b/core/socks.go index 022bb7a0..f3560448 100644 --- a/core/socks.go +++ b/core/socks.go @@ -3,7 +3,6 @@ package core import ( "bytes" "context" - "errors" "fmt" "github.com/wencaiwulue/kubevpn/util" "net" @@ -14,136 +13,50 @@ import ( log "github.com/sirupsen/logrus" ) -type clientSelector struct { - methods []uint8 -} - -func (selector *clientSelector) Methods() []uint8 { - if util.Debug { - log.Debug("[socks5] methods:", selector.methods) - } - return selector.methods -} - -func (selector *clientSelector) AddMethod(methods ...uint8) { - selector.methods = append(selector.methods, methods...) -} - -func (selector *clientSelector) Select(methods ...uint8) (method uint8) { - return -} - -func (selector *clientSelector) OnSelected(method uint8, conn net.Conn) (net.Conn, error) { - if util.Debug { - log.Debug("[socks5] method selected:", method) - } - switch method { - case gosocks5.MethodNoAuth: - log.Debug("[socks5] client", "no auth") - return conn, nil - } - - return conn, nil -} - -type serverSelector struct { - methods []uint8 -} - -func (selector *serverSelector) Methods() []uint8 { - return selector.methods -} - -func (selector *serverSelector) AddMethod(methods ...uint8) { - selector.methods = append(selector.methods, methods...) -} - -func (selector *serverSelector) Select(methods ...uint8) (method uint8) { - if util.Debug { - log.Debugf("[socks5] %d %d %v", gosocks5.Ver5, len(methods), methods) - } - method = gosocks5.MethodNoAuth - return -} - -func (selector *serverSelector) OnSelected(method uint8, conn net.Conn) (net.Conn, error) { - if util.Debug { - log.Debugf("[socks5] %d %d", gosocks5.Ver5, method) - } - switch method { - case gosocks5.MethodNoAuth: - log.Debugf("[socks5] server, no auth") - return conn, nil - case gosocks5.MethodNoAcceptable: - return nil, gosocks5.ErrBadMethod - } - - return conn, nil -} - -type socks5UDPTunConnector struct { +type fakeUDPTunConnector struct { } // SOCKS5UDPTunConnector creates a connector for SOCKS5 UDP-over-TCP relay. // It accepts an optional auth info for SOCKS5 Username/Password Authentication. func SOCKS5UDPTunConnector() Connector { - return &socks5UDPTunConnector{} + return &fakeUDPTunConnector{} } -func (c *socks5UDPTunConnector) ConnectContext(ctx context.Context, conn net.Conn, network, address string) (net.Conn, error) { +func (c *fakeUDPTunConnector) ConnectContext(_ context.Context, conn net.Conn, network, address string) (net.Conn, error) { switch network { case "tcp", "tcp4", "tcp6": return nil, fmt.Errorf("%s unsupported", network) } - conn.SetDeadline(time.Now().Add(util.ConnectTimeout)) + _ = conn.SetDeadline(time.Now().Add(util.ConnectTimeout)) defer conn.SetDeadline(time.Time{}) targetAddr, _ := net.ResolveUDPAddr("udp", address) - return newSocks5UDPTunnelConn(conn, nil, targetAddr) + return newFakeUDPTunnelConnOverTcp(conn, targetAddr) } -type socks5Handler struct { - selector *serverSelector +type fakeUdpHandler struct { } // SOCKS5Handler creates a server Handler for SOCKS5 proxy server. func SOCKS5Handler() Handler { - h := &socks5Handler{} + h := &fakeUdpHandler{} h.Init() return h } -func (h *socks5Handler) Init(...HandlerOption) { - h.selector = &serverSelector{} - h.selector.AddMethod( - gosocks5.MethodNoAuth, - ) +func (h *fakeUdpHandler) Init(...HandlerOption) { } -func (h *socks5Handler) Handle(conn net.Conn) { +func (h *fakeUdpHandler) Handle(conn net.Conn) { defer conn.Close() - - conn = gosocks5.ServerConn(conn, h.selector) - req, err := gosocks5.ReadRequest(conn) - if err != nil { - log.Debugf("[socks5] %s -> %s : %s", conn.RemoteAddr(), conn.LocalAddr(), err) - return - } - if util.Debug { - log.Debugf("[socks5] %s -> %s\n%s", conn.RemoteAddr(), conn.LocalAddr(), req) - } - switch req.Cmd { - case gosocks5.CmdUdp: - h.handleUDPTunnel(conn, req) - - default: - log.Debugf("[socks5] %s - %s : Unrecognized request: %d", conn.RemoteAddr(), conn.LocalAddr(), req.Cmd) + log.Debugf("[socks5] %s -> %s\n", conn.RemoteAddr(), conn.LocalAddr()) } + h.handleUDPTunnel(conn) } -func (h *socks5Handler) transportUDP(relay, peer net.PacketConn) (err error) { +func (h *fakeUdpHandler) transportUDP(relay, peer net.PacketConn) (err error) { errc := make(chan error, 2) var clientAddr net.Addr @@ -196,7 +109,7 @@ func (h *socks5Handler) transportUDP(relay, peer net.PacketConn) (err error) { } buf := bytes.Buffer{} dgram := gosocks5.NewUDPDatagram(gosocks5.NewUDPHeader(0, 0, toSocksAddr(raddr)), b[:n]) - dgram.Write(&buf) + _ = dgram.Write(&buf) if _, err := relay.WriteTo(buf.Bytes(), clientAddr); err != nil { errc <- err return @@ -207,15 +120,10 @@ func (h *socks5Handler) transportUDP(relay, peer net.PacketConn) (err error) { } }() - select { - case err = <-errc: - //log.Println("w exit", err) - } - - return + return <-errc } -func (h *socks5Handler) tunnelClientUDP(uc *net.UDPConn, cc net.Conn) (err error) { +func (h *fakeUdpHandler) tunnelClientUDP(uc *net.UDPConn, cc net.Conn) (err error) { errc := make(chan error, 2) var clientAddr *net.UDPAddr @@ -271,7 +179,7 @@ func (h *socks5Handler) tunnelClientUDP(uc *net.UDPConn, cc net.Conn) (err error dgram.Header.Rsv = 0 buf := bytes.Buffer{} - dgram.Write(&buf) + _ = dgram.Write(&buf) if _, err := uc.WriteToUDP(buf.Bytes(), clientAddr); err != nil { errc <- err return @@ -282,42 +190,28 @@ func (h *socks5Handler) tunnelClientUDP(uc *net.UDPConn, cc net.Conn) (err error } }() - select { - case err = <-errc: - } - - return + return <-errc } -func (h *socks5Handler) handleUDPTunnel(conn net.Conn, req *gosocks5.Request) { +func (h *fakeUdpHandler) handleUDPTunnel(conn net.Conn) { // serve tunnel udp, tunnel <-> remote, handle tunnel udp request - addr := req.Addr.String() - - bindAddr, _ := net.ResolveUDPAddr("udp", addr) + bindAddr, _ := net.ResolveUDPAddr("udp", ":0") uc, err := net.ListenUDP("udp", bindAddr) if err != nil { - log.Debugf("[socks5] udp-tun %s -> %s : %s", conn.RemoteAddr(), req.Addr, err) + log.Debugf("[socks5] udp-tun %s -> %s : %s", conn.RemoteAddr(), bindAddr, err) return } defer uc.Close() - - socksAddr := toSocksAddr(uc.LocalAddr()) - socksAddr.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String()) - reply := gosocks5.NewReply(gosocks5.Succeeded, socksAddr) - if err := reply.Write(conn); err != nil { - log.Debugf("[socks5] udp-tun %s <- %s : %s", conn.RemoteAddr(), socksAddr, err) - return - } if util.Debug { - log.Debugf("[socks5] udp-tun %s <- %s\n%s", conn.RemoteAddr(), socksAddr, reply) + log.Debugf("[socks5] udp-tun %s <- %s\n", conn.RemoteAddr(), uc.LocalAddr()) } - log.Debugf("[socks5] udp-tun %s <-> %s", conn.RemoteAddr(), socksAddr) - h.tunnelServerUDP(conn, uc) - log.Debugf("[socks5] udp-tun %s >-< %s", conn.RemoteAddr(), socksAddr) + log.Debugf("[socks5] udp-tun %s <-> %s", conn.RemoteAddr(), uc.LocalAddr()) + _ = h.tunnelServerUDP(conn, uc) + log.Debugf("[socks5] udp-tun %s >-< %s", conn.RemoteAddr(), uc.LocalAddr()) return } -func (h *socks5Handler) tunnelServerUDP(cc net.Conn, pc net.PacketConn) (err error) { +func (h *fakeUdpHandler) tunnelServerUDP(cc net.Conn, pc net.PacketConn) (err error) { errc := make(chan error, 2) go func() { @@ -333,8 +227,7 @@ func (h *socks5Handler) tunnelServerUDP(cc net.Conn, pc net.PacketConn) (err err } // pipe from peer to tunnel - dgram := gosocks5.NewUDPDatagram( - gosocks5.NewUDPHeader(uint16(n), 0, toSocksAddr(addr)), b[:n]) + dgram := gosocks5.NewUDPDatagram(gosocks5.NewUDPHeader(uint16(n), 0, toSocksAddr(addr)), b[:n]) if err := dgram.Write(cc); err != nil { log.Debugf("[socks5] udp-tun %s <- %s : %s", cc.RemoteAddr(), dgram.Header.Addr, err) errc <- err @@ -371,14 +264,9 @@ func (h *socks5Handler) tunnelServerUDP(cc net.Conn, pc net.PacketConn) (err err } }() - select { - case err = <-errc: - } - - return + return <-errc } -// TODO: support ipv6 and domain func toSocksAddr(addr net.Addr) *gosocks5.Addr { host := "0.0.0.0" port := 0 @@ -394,71 +282,26 @@ func toSocksAddr(addr net.Addr) *gosocks5.Addr { } } -func socks5Handshake(conn net.Conn) (net.Conn, error) { - cs := &clientSelector{} - cs.AddMethod( - gosocks5.MethodNoAuth, - ) - - cc := gosocks5.ClientConn(conn, cs) - if err := cc.Handleshake(); err != nil { - return nil, err - } - return cc, nil -} - // fake upd connect over tcp -type socks5UDPTunnelConn struct { +type fakeUDPTunnelConn struct { // tcp connection net.Conn targetAddr net.Addr } -func newSocks5UDPTunnelConn(conn net.Conn, serverAddr, targetAddr net.Addr) (net.Conn, error) { - cc, err := socks5Handshake(conn) - if err != nil { - return nil, err - } - - req := gosocks5.NewRequest(gosocks5.CmdUdp, toSocksAddr(serverAddr)) - if err := req.Write(cc); err != nil { - return nil, err - } - if util.Debug { - log.Debug("[socks5] udp-tun", req) - } - - reply, err := gosocks5.ReadReply(cc) - if err != nil { - return nil, err - } - - if util.Debug { - log.Debug("[socks5] udp-tun", reply) - } - - if reply.Rep != gosocks5.Succeeded { - return nil, errors.New("socks5 UDP tunnel failure") - } - - bindAddr, err := net.ResolveUDPAddr("udp", reply.Addr.String()) - if err != nil { - return nil, err - } - log.Debugf("[socks5] udp-tun associate on %s OK", bindAddr) - - return &socks5UDPTunnelConn{ - Conn: cc, +func newFakeUDPTunnelConnOverTcp(conn net.Conn, targetAddr net.Addr) (net.Conn, error) { + return &fakeUDPTunnelConn{ + Conn: conn, targetAddr: targetAddr, }, nil } -func (c *socks5UDPTunnelConn) Read(b []byte) (n int, err error) { +func (c *fakeUDPTunnelConn) Read(b []byte) (n int, err error) { n, _, err = c.ReadFrom(b) return } -func (c *socks5UDPTunnelConn) ReadFrom(b []byte) (n int, addr net.Addr, err error) { +func (c *fakeUDPTunnelConn) ReadFrom(b []byte) (n int, addr net.Addr, err error) { dgram, err := gosocks5.ReadUDPDatagram(c.Conn) if err != nil { return @@ -468,11 +311,11 @@ func (c *socks5UDPTunnelConn) ReadFrom(b []byte) (n int, addr net.Addr, err erro return } -func (c *socks5UDPTunnelConn) Write(b []byte) (n int, err error) { +func (c *fakeUDPTunnelConn) Write(b []byte) (n int, err error) { return c.WriteTo(b, c.targetAddr) } -func (c *socks5UDPTunnelConn) WriteTo(b []byte, addr net.Addr) (n int, err error) { +func (c *fakeUDPTunnelConn) WriteTo(b []byte, addr net.Addr) (n int, err error) { dgram := gosocks5.NewUDPDatagram(gosocks5.NewUDPHeader(uint16(len(b)), 0, toSocksAddr(addr)), b) if err = dgram.Write(c.Conn); err != nil { return diff --git a/remote/remote_test.go b/remote/remote_test.go index a0d901e6..91001e09 100644 --- a/remote/remote_test.go +++ b/remote/remote_test.go @@ -17,10 +17,8 @@ import ( "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" - "k8s.io/client-go/util/homedir" cmdutil "k8s.io/kubectl/pkg/cmd/util" "net" - "path/filepath" "strings" "testing" "time" @@ -28,10 +26,7 @@ import ( func TestCreateServer(t *testing.T) { clientConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig( - &clientcmd.ClientConfigLoadingRules{ - ExplicitPath: clientcmd.RecommendedHomeFile, - }, - nil, + &clientcmd.ClientConfigLoadingRules{ExplicitPath: clientcmd.RecommendedHomeFile}, nil, ) config, err := clientConfig.ClientConfig() if err != nil { @@ -66,10 +61,7 @@ func TestGetIp(t *testing.T) { func TestGetIPFromDHCP(t *testing.T) { clientConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig( - &clientcmd.ClientConfigLoadingRules{ - ExplicitPath: filepath.Join(homedir.HomeDir(), clientcmd.RecommendedHomeDir, clientcmd.RecommendedFileName), - }, - nil, + &clientcmd.ClientConfigLoadingRules{ExplicitPath: clientcmd.RecommendedHomeFile}, nil, ) config, err := clientConfig.ClientConfig() if err != nil { @@ -80,13 +72,10 @@ func TestGetIPFromDHCP(t *testing.T) { log.Fatal(err) } - err = InitDHCP(clientset, "test", nil) - if err != nil { - fmt.Println(err) - } + manager := NewDHCPManager(clientset, "test", nil) for i := 0; i < 10; i++ { - ipNet, err := GetIpFromDHCP(clientset, "test") - ipNet2, err := GetIpFromDHCP(clientset, "test") + ipNet, err := manager.RentIPRandom() + ipNet2, err := manager.RentIPRandom() if err != nil { fmt.Println(err) continue @@ -94,8 +83,8 @@ func TestGetIPFromDHCP(t *testing.T) { fmt.Printf("%s->%s\n", ipNet.String(), ipNet2.String()) } time.Sleep(time.Millisecond * 10) - err = ReleaseIpToDHCP(clientset, "test", ipNet) - err = ReleaseIpToDHCP(clientset, "test", ipNet2) + err = manager.ReleaseIpToDHCP(ipNet) + err = manager.ReleaseIpToDHCP(ipNet2) if err != nil { fmt.Println(err) }