func (s *Socks5Server) handleUDPConnect(req *gosocks5.Request) { cc, err := s.Base.Chain.GetConn() // connection error if err != nil && err != ErrEmptyChain { glog.V(LWARNING).Infof("[udp] %s <- %s : %s", s.conn.RemoteAddr(), req.Addr, err) reply := gosocks5.NewReply(gosocks5.Failure, nil) reply.Write(s.conn) glog.V(LDEBUG).Infof("[udp] %s <- %s\n%s", s.conn.RemoteAddr(), req.Addr, reply) return } // serve udp connect if err == ErrEmptyChain { s.udpConnect(req.Addr.String()) return } defer cc.Close() // forward request if err := req.Write(cc); err != nil { glog.V(LINFO).Infof("[udp] %s -> %s : %s", s.conn.RemoteAddr(), req.Addr, err) gosocks5.NewReply(gosocks5.Failure, nil).Write(s.conn) return } glog.V(LINFO).Infof("[udp] %s <-> %s", s.conn.RemoteAddr(), req.Addr) s.Base.transport(s.conn, cc) glog.V(LINFO).Infof("[udp] %s >-< %s", s.conn.RemoteAddr(), req.Addr) }
func handleSocks5(conn net.Conn, methods []uint8) { if err := selectMethod(conn, methods...); err != nil { log.Println(err) return } req, err := gosocks5.ReadRequest(conn) if err != nil { return } //log.Println(req) sconn, err := makeTunnel() if err != nil { gosocks5.NewReply(gosocks5.Failure, nil).Write(conn) log.Println(err) return } defer sconn.Close() switch req.Cmd { case gosocks5.CmdConnect, gosocks5.CmdBind: if err := req.Write(sconn); err != nil { return } Transport(conn, sconn) case gosocks5.CmdUdp: if err := req.Write(sconn); err != nil { return } rep, err := gosocks5.ReadReply(sconn) if err != nil || rep.Rep != gosocks5.Succeeded { return } uconn, err := net.ListenUDP("udp", nil) if err != nil { log.Println(err) gosocks5.NewReply(gosocks5.Failure, nil).Write(conn) return } defer uconn.Close() addr := ToSocksAddr(uconn.LocalAddr()) addr.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String()) log.Println("udp:", addr) rep = gosocks5.NewReply(gosocks5.Succeeded, addr) if err := rep.Write(conn); err != nil { log.Println(err) return } go cliTunnelUDP(uconn, sconn) // block, waiting for client exit ioutil.ReadAll(conn) } }
func (s *Socks5Server) udpConnect(addr string) { raddr, err := net.ResolveUDPAddr("udp", addr) if err != nil { glog.V(LINFO).Infof("[udp] %s -> %s : %s", s.conn.RemoteAddr(), addr, err) gosocks5.NewReply(gosocks5.Failure, nil).Write(s.conn) return } if err := gosocks5.NewReply(gosocks5.Succeeded, nil).Write(s.conn); err != nil { glog.V(LINFO).Infof("[udp] %s <- %s : %s", s.conn.RemoteAddr(), addr, err) return } glog.V(LINFO).Infof("[udp] %s <-> %s", s.conn.RemoteAddr(), raddr) defer glog.V(LINFO).Infof("[udp] %s >-< %s", s.conn.RemoteAddr(), raddr) for { dgram, err := gosocks5.ReadUDPDatagram(s.conn) if err != nil { glog.V(LWARNING).Infof("[udp] %s -> %s : %s", s.conn.RemoteAddr(), addr, err) return } go func() { b := make([]byte, LargeBufferSize) relay, err := net.DialUDP("udp", nil, raddr) if err != nil { glog.V(LWARNING).Infof("[udp] %s -> %s : %s", s.conn.RemoteAddr(), raddr, err) return } defer relay.Close() if _, err := relay.Write(dgram.Data); err != nil { glog.V(LWARNING).Infof("[udp] %s -> %s : %s", s.conn.RemoteAddr(), raddr, err) return } glog.V(LDEBUG).Infof("[udp-tun] %s >>> %s length: %d", s.conn.RemoteAddr(), raddr, len(dgram.Data)) relay.SetReadDeadline(time.Now().Add(time.Second * 60)) n, err := relay.Read(b) if err != nil { glog.V(LWARNING).Infof("[udp] %s <- %s : %s", s.conn.RemoteAddr(), raddr, err) return } relay.SetReadDeadline(time.Time{}) glog.V(LDEBUG).Infof("[udp-tun] %s <<< %s length: %d", s.conn.RemoteAddr(), raddr, n) s.conn.SetWriteDeadline(time.Now().Add(time.Second * 90)) if err := gosocks5.NewUDPDatagram(gosocks5.NewUDPHeader(uint16(n), 0, dgram.Header.Addr), b[:n]).Write(s.conn); err != nil { glog.V(LWARNING).Infof("[udp] %s <- %s : %s", s.conn.RemoteAddr(), raddr, err) return } s.conn.SetWriteDeadline(time.Time{}) }() } }
func serveBind(conn net.Conn) error { l, err := net.ListenTCP("tcp", nil) if err != nil { glog.V(LWARNING).Infoln("socks5 bind listen:", err) rep := gosocks5.NewReply(gosocks5.Failure, nil) if err := rep.Write(conn); err != nil { glog.V(LWARNING).Infoln("socks5 bind listen:", err) } else { glog.V(LDEBUG).Infoln(rep) } return err } addr := ToSocksAddr(l.Addr()) // Issue: may not reachable when host has two interfaces addr.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String()) rep := gosocks5.NewReply(gosocks5.Succeeded, addr) if err := rep.Write(conn); err != nil { glog.V(LWARNING).Infoln("socks5 bind:", err) l.Close() return err } glog.V(LDEBUG).Infoln(rep) glog.V(LINFO).Infoln("[socks5] BIND on", addr, "OK") l.SetDeadline(time.Now().Add(time.Minute * 30)) // wait 30 minutes at most tconn, err := l.AcceptTCP() l.Close() // only accept one peer if err != nil { glog.V(LWARNING).Infoln("socks5 bind accept:", err) rep = gosocks5.NewReply(gosocks5.Failure, nil) if err := rep.Write(conn); err != nil { glog.V(LWARNING).Infoln("socks5 bind accept:", err) } else { glog.V(LDEBUG).Infoln(rep) } return err } defer tconn.Close() addr = ToSocksAddr(tconn.RemoteAddr()) glog.V(LINFO).Infoln("[socks5] BIND accept", addr) rep = gosocks5.NewReply(gosocks5.Succeeded, addr) if err := rep.Write(conn); err != nil { glog.V(LWARNING).Infoln("socks5 bind accept:", err) return err } glog.V(LDEBUG).Infoln(rep) return Transport(conn, tconn) }
func handle(conn net.Conn, method uint8) error { defer conn.Close() req, err := gosocks5.ReadRequest(conn) if err != nil { log.Println(err) return err } tconn, err := Connect(req.Addr.String()) if err != nil { log.Println(err) return err } defer tconn.Close() rep := gosocks5.NewReply(gosocks5.Succeeded, nil) if err := rep.Write(conn); err != nil { return err } if err := Transport(conn, tconn); err != nil { log.Println(err) } return nil }
func (s *Socks5Server) handleUDPTunnel(req *gosocks5.Request) { cc, err := s.Base.Chain.GetConn() // connection error if err != nil && err != ErrEmptyChain { glog.V(LWARNING).Infof("[socks5-udp] %s -> %s : %s", s.conn.RemoteAddr(), req.Addr, err) reply := gosocks5.NewReply(gosocks5.Failure, nil) reply.Write(s.conn) glog.V(LDEBUG).Infof("[socks5-udp] %s -> %s\n%s", s.conn.RemoteAddr(), req.Addr, reply) return } // serve tunnel udp, tunnel <-> remote, handle tunnel udp request if err == ErrEmptyChain { bindAddr, _ := net.ResolveUDPAddr("udp", req.Addr.String()) uc, err := net.ListenUDP("udp", bindAddr) if err != nil { glog.V(LWARNING).Infof("[socks5-udp] %s -> %s : %s", s.conn.RemoteAddr(), req.Addr, err) return } defer uc.Close() socksAddr := ToSocksAddr(uc.LocalAddr()) socksAddr.Host, _, _ = net.SplitHostPort(s.conn.LocalAddr().String()) reply := gosocks5.NewReply(gosocks5.Succeeded, socksAddr) if err := reply.Write(s.conn); err != nil { glog.V(LWARNING).Infof("[socks5-udp] %s <- %s : %s", s.conn.RemoteAddr(), socksAddr, err) return } glog.V(LDEBUG).Infof("[socks5-udp] %s <- %s\n%s", s.conn.RemoteAddr(), socksAddr, reply) glog.V(LINFO).Infof("[socks5-udp] %s <-> %s", s.conn.RemoteAddr(), socksAddr) s.tunnelUDP(uc, s.conn, false) glog.V(LINFO).Infof("[socks5-udp] %s >-< %s", s.conn.RemoteAddr(), socksAddr) return } defer cc.Close() // tunnel <-> tunnel, direct forwarding req.Write(cc) glog.V(LINFO).Infof("[socks5-udp] %s <-> %s [tun]", s.conn.RemoteAddr(), cc.RemoteAddr()) s.Base.transport(s.conn, cc) glog.V(LINFO).Infof("[socks5-udp] %s >-< %s [tun]", s.conn.RemoteAddr(), cc.RemoteAddr()) }
func forwardBind(req *gosocks5.Request, conn net.Conn) error { fconn, _, err := forwardChain(forwardArgs...) if err != nil { glog.V(LWARNING).Infoln("[socks5] BIND(forward)", req.Addr, err) if fconn != nil { fconn.Close() } rep := gosocks5.NewReply(gosocks5.Failure, nil) if err := rep.Write(conn); err != nil { glog.V(LWARNING).Infoln("socks5 bind forward:", err) } else { glog.V(LDEBUG).Infoln(rep) } return err } defer fconn.Close() if err := req.Write(fconn); err != nil { glog.V(LWARNING).Infoln("[socks5] BIND(forward)", err) gosocks5.NewReply(gosocks5.Failure, nil).Write(conn) return err } glog.V(LDEBUG).Infoln(req) // first reply rep, err := peekReply(conn, fconn) if err != nil { glog.V(LWARNING).Infoln("[socks5] BIND(forward)", err) return err } glog.V(LINFO).Infoln("[socks5] BIND(forward) on", rep.Addr, "OK") // second reply rep, err = peekReply(conn, fconn) if err != nil { glog.V(LWARNING).Infoln("[socks5] BIND(forward) accept", err) return err } glog.V(LINFO).Infoln("[socks5] BIND(forward) accept", rep.Addr) return Transport(conn, fconn) }
func (s *Socks5Server) handleConnect(req *gosocks5.Request) { cc, err := s.Base.Chain.Dial(req.Addr.String()) if err != nil { glog.V(LWARNING).Infof("[socks5-connect] %s -> %s : %s", s.conn.RemoteAddr(), req.Addr, err) rep := gosocks5.NewReply(gosocks5.HostUnreachable, nil) rep.Write(s.conn) glog.V(LDEBUG).Infof("[socks5-connect] %s <- %s\n%s", s.conn.RemoteAddr(), req.Addr, rep) return } defer cc.Close() rep := gosocks5.NewReply(gosocks5.Succeeded, nil) if err := rep.Write(s.conn); err != nil { glog.V(LWARNING).Infof("[socks5-connect] %s <- %s : %s", s.conn.RemoteAddr(), req.Addr, err) return } glog.V(LDEBUG).Infof("[socks5-connect] %s <- %s\n%s", s.conn.RemoteAddr(), req.Addr, rep) glog.V(LINFO).Infof("[socks5-connect] %s <-> %s", s.conn.RemoteAddr(), req.Addr) //Transport(conn, cc) s.Base.transport(s.conn, cc) glog.V(LINFO).Infof("[socks5-connect] %s >-< %s", s.conn.RemoteAddr(), req.Addr) }
func peekReply(dst io.Writer, src io.Reader) (rep *gosocks5.Reply, err error) { rep, err = gosocks5.ReadReply(src) if err != nil { glog.V(LWARNING).Infoln(err) rep = gosocks5.NewReply(gosocks5.Failure, nil) } if err = rep.Write(dst); err != nil { return } glog.V(LDEBUG).Infoln(rep) if rep.Rep != gosocks5.Succeeded { err = errors.New("Failure") } return }
func socks5Handle(conn net.Conn) { defer conn.Close() req, err := gosocks5.ReadRequest(conn) if err != nil { log.Println(err) return } switch req.Cmd { case gosocks5.CmdConnect: //log.Println("connect", req.Addr.String()) tconn, err := Connect(req.Addr.String(), Proxy) if err != nil { gosocks5.NewReply(gosocks5.HostUnreachable, nil).Write(conn) return } defer tconn.Close() rep := gosocks5.NewReply(gosocks5.Succeeded, nil) if err := rep.Write(conn); err != nil { return } if err := Transport(conn, tconn); err != nil { //log.Println(err) } case gosocks5.CmdBind: l, err := net.ListenTCP("tcp", nil) if err != nil { gosocks5.NewReply(gosocks5.Failure, nil).Write(conn) return } addr := ToSocksAddr(l.Addr()) addr.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String()) log.Println("bind:", addr) rep := gosocks5.NewReply(gosocks5.Succeeded, addr) if err := rep.Write(conn); err != nil { return } tconn, err := l.AcceptTCP() if err != nil { log.Println("accept:", err) gosocks5.NewReply(gosocks5.Failure, nil).Write(conn) return } defer tconn.Close() l.Close() addr = ToSocksAddr(tconn.RemoteAddr()) log.Println("accept peer:", addr.String()) rep = gosocks5.NewReply(gosocks5.Succeeded, addr) if err := rep.Write(conn); err != nil { log.Println(err) return } if err := Transport(conn, tconn); err != nil { //log.Println(err) } case gosocks5.CmdUdp: uconn, err := net.ListenUDP("udp", nil) if err != nil { log.Println(err) gosocks5.NewReply(gosocks5.Failure, nil).Write(conn) return } defer uconn.Close() addr := ToSocksAddr(uconn.LocalAddr()) addr.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String()) log.Println("udp:", addr) rep := gosocks5.NewReply(gosocks5.Succeeded, addr) if err := rep.Write(conn); err != nil { log.Println(err) return } srvTunnelUDP(conn, uconn) } }
func handleSocks5Request(req *gosocks5.Request, conn net.Conn) { glog.V(LDEBUG).Infoln(req) switch req.Cmd { case gosocks5.CmdConnect: glog.V(LINFO).Infoln("[socks5] CONNECT", req.Addr) tconn, err := Connect(req.Addr.String()) if err != nil { glog.V(LWARNING).Infoln("[socks5] CONNECT", req.Addr, err) rep := gosocks5.NewReply(gosocks5.HostUnreachable, nil) if err := rep.Write(conn); err != nil { glog.V(LWARNING).Infoln("socks5 connect:", err) } else { glog.V(LDEBUG).Infoln(rep) } return } defer tconn.Close() rep := gosocks5.NewReply(gosocks5.Succeeded, nil) if err := rep.Write(conn); err != nil { glog.V(LWARNING).Infoln("socks5 connect:", err) return } glog.V(LDEBUG).Infoln(rep) glog.V(LINFO).Infoln("[socks5] CONNECT", req.Addr, "OK") Transport(conn, tconn) case gosocks5.CmdBind: glog.V(LINFO).Infoln("[socks5] BIND", req.Addr) if len(forwardArgs) > 0 { forwardBind(req, conn) } else { serveBind(conn) } case gosocks5.CmdUdp: glog.V(LINFO).Infoln("[socks5] UDP ASSOCIATE", req.Addr) uconn, err := net.ListenUDP("udp", nil) if err != nil { glog.V(LWARNING).Infoln("socks5 udp listen:", err) rep := gosocks5.NewReply(gosocks5.Failure, nil) if err := rep.Write(conn); err != nil { glog.V(LWARNING).Infoln("socks5 udp listen:", err) } else { glog.V(LDEBUG).Infoln(rep) } return } defer uconn.Close() addr := ToSocksAddr(uconn.LocalAddr()) addr.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String()) glog.V(LINFO).Infoln("[socks5] UDP listen on", addr) rep := gosocks5.NewReply(gosocks5.Succeeded, addr) if err := rep.Write(conn); err != nil { glog.V(LWARNING).Infoln("socks5 udp:", err) return } else { glog.V(LDEBUG).Infoln(rep) } cc, dgram, err := createClientConn(conn, uconn) if err != nil { glog.V(LWARNING).Infoln("socks5 udp:", err) return } glog.V(LINFO).Infof("[udp] to %s, length %d", dgram.Header.Addr, len(dgram.Data)) raddr, err := net.ResolveUDPAddr("udp", dgram.Header.Addr.String()) if err != nil { glog.V(LWARNING).Infoln("socks5 udp:", err) return } sc, err := createServerConn(uconn, raddr) if err != nil { glog.V(LWARNING).Infoln("socks5 udp:", err) return } if err = sc.WriteUDPTimeout(dgram, time.Second*30); err != nil { glog.V(LWARNING).Infoln("socks5 udp:", err) return } dgram, err = sc.ReadUDPTimeout(time.Second * 30) if err != nil { glog.V(LWARNING).Infoln("socks5 udp:", err) return } glog.V(LINFO).Infof("[udp] from %s, length %d", dgram.Header.Addr, len(dgram.Data)) if err = cc.WriteUDPTimeout(dgram, time.Second*30); err != nil { glog.V(LWARNING).Infoln("socks5 udp:", err) return } TransportUDP(cc, sc) default: glog.V(LWARNING).Infoln("Unrecognized request: ", req) } }
func (s *Socks5Server) bindOn(addr string) { bindAddr, _ := net.ResolveTCPAddr("tcp", addr) ln, err := net.ListenTCP("tcp", bindAddr) // strict mode: if the port already in use, it will return error if err != nil { glog.V(LWARNING).Infof("[socks5-bind] %s -> %s : %s", s.conn.RemoteAddr(), addr, err) gosocks5.NewReply(gosocks5.Failure, nil).Write(s.conn) return } socksAddr := ToSocksAddr(ln.Addr()) // Issue: may not reachable when host has multi-interface socksAddr.Host, _, _ = net.SplitHostPort(s.conn.LocalAddr().String()) reply := gosocks5.NewReply(gosocks5.Succeeded, socksAddr) if err := reply.Write(s.conn); err != nil { glog.V(LWARNING).Infof("[socks5-bind] %s <- %s : %s", s.conn.RemoteAddr(), addr, err) ln.Close() return } glog.V(LDEBUG).Infof("[socks5-bind] %s <- %s\n%s", s.conn.RemoteAddr(), addr, reply) glog.V(LINFO).Infof("[socks5-bind] %s - %s BIND ON %s OK", s.conn.RemoteAddr(), addr, socksAddr) var pconn net.Conn accept := func() <-chan error { errc := make(chan error, 1) go func() { defer close(errc) defer ln.Close() c, err := ln.AcceptTCP() if err != nil { errc <- err return } pconn = c }() return errc } pc1, pc2 := net.Pipe() pipe := func() <-chan error { errc := make(chan error, 1) go func() { defer close(errc) defer pc1.Close() errc <- s.Base.transport(s.conn, pc1) }() return errc } defer pc2.Close() for { select { case err := <-accept(): if err != nil || pconn == nil { glog.V(LWARNING).Infof("[socks5-bind] %s <- %s : %s", s.conn.RemoteAddr(), addr, err) return } defer pconn.Close() reply := gosocks5.NewReply(gosocks5.Succeeded, ToSocksAddr(pconn.RemoteAddr())) if err := reply.Write(pc2); err != nil { glog.V(LWARNING).Infof("[socks5-bind] %s <- %s : %s", s.conn.RemoteAddr(), addr, err) } glog.V(LDEBUG).Infof("[socks5-bind] %s <- %s\n%s", s.conn.RemoteAddr(), addr, reply) glog.V(LINFO).Infof("[socks5-bind] %s <- %s PEER %s ACCEPTED", s.conn.RemoteAddr(), socksAddr, pconn.RemoteAddr()) glog.V(LINFO).Infof("[socks5-bind] %s <-> %s", s.conn.RemoteAddr(), pconn.RemoteAddr()) if err = s.Base.transport(pc2, pconn); err != nil { glog.V(LWARNING).Infoln(err) } glog.V(LINFO).Infof("[socks5-bind] %s >-< %s", s.conn.RemoteAddr(), pconn.RemoteAddr()) return case err := <-pipe(): glog.V(LWARNING).Infof("[socks5-bind] %s -> %s : %v", s.conn.RemoteAddr(), addr, err) ln.Close() return } } }
func (s *Socks5Server) handleUDPRelay(req *gosocks5.Request) { bindAddr, _ := net.ResolveUDPAddr("udp", req.Addr.String()) relay, err := net.ListenUDP("udp", bindAddr) // udp associate, strict mode: if the port already in use, it will return error if err != nil { glog.V(LWARNING).Infof("[socks5-udp] %s -> %s : %s", s.conn.RemoteAddr(), req.Addr, err) reply := gosocks5.NewReply(gosocks5.Failure, nil) reply.Write(s.conn) glog.V(LDEBUG).Infof("[socks5-udp] %s <- %s\n%s", s.conn.RemoteAddr(), req.Addr, reply) return } defer relay.Close() socksAddr := ToSocksAddr(relay.LocalAddr()) socksAddr.Host, _, _ = net.SplitHostPort(s.conn.LocalAddr().String()) reply := gosocks5.NewReply(gosocks5.Succeeded, socksAddr) if err := reply.Write(s.conn); err != nil { glog.V(LWARNING).Infof("[socks5-udp] %s <- %s : %s", s.conn.RemoteAddr(), req.Addr, err) return } glog.V(LDEBUG).Infof("[socks5-udp] %s <- %s\n%s", s.conn.RemoteAddr(), reply.Addr, reply) glog.V(LINFO).Infof("[socks5-udp] %s - %s BIND ON %s OK", s.conn.RemoteAddr(), req.Addr, socksAddr) cc, err := s.Base.Chain.GetConn() // connection error if err != nil && err != ErrEmptyChain { glog.V(LWARNING).Infof("[socks5-udp] %s -> %s : %s", s.conn.RemoteAddr(), socksAddr, err) return } // serve as standard socks5 udp relay local <-> remote if err == ErrEmptyChain { peer, er := net.ListenUDP("udp", nil) if er != nil { glog.V(LWARNING).Infof("[socks5-udp] %s -> %s : %s", s.conn.RemoteAddr(), socksAddr, er) return } defer peer.Close() go s.transportUDP(relay, peer) } // forward udp local <-> tunnel if err == nil { defer cc.Close() cc.SetWriteDeadline(time.Now().Add(WriteTimeout)) req := gosocks5.NewRequest(CmdUdpTun, nil) if err := req.Write(cc); err != nil { glog.V(LWARNING).Infoln("[socks5-udp] %s -> %s : %s", s.conn.RemoteAddr(), cc.RemoteAddr(), err) return } cc.SetWriteDeadline(time.Time{}) glog.V(LDEBUG).Infof("[socks5-udp] %s -> %s\n%s", s.conn.RemoteAddr(), cc.RemoteAddr(), req) cc.SetReadDeadline(time.Now().Add(ReadTimeout)) reply, err = gosocks5.ReadReply(cc) if err != nil { glog.V(LWARNING).Infoln("[socks5-udp] %s -> %s : %s", s.conn.RemoteAddr(), cc.RemoteAddr(), err) return } glog.V(LDEBUG).Infof("[socks5-udp] %s <- %s\n%s", s.conn.RemoteAddr(), cc.RemoteAddr(), reply) if reply.Rep != gosocks5.Succeeded { glog.V(LWARNING).Infoln("[socks5-udp] %s <- %s : udp associate failed", s.conn.RemoteAddr(), cc.RemoteAddr()) return } cc.SetReadDeadline(time.Time{}) glog.V(LINFO).Infof("[socks5-udp] %s <-> %s [tun: %s]", s.conn.RemoteAddr(), socksAddr, reply.Addr) go s.tunnelUDP(relay, cc, true) } glog.V(LINFO).Infof("[socks5-udp] %s <-> %s", s.conn.RemoteAddr(), socksAddr) b := make([]byte, SmallBufferSize) for { _, err := s.conn.Read(b) // discard any data from tcp connection if err != nil { glog.V(LWARNING).Infof("[socks5-udp] %s - %s : %s", s.conn.RemoteAddr(), socksAddr, err) break // client disconnected } } glog.V(LINFO).Infof("[socks5-udp] %s >-< %s", s.conn.RemoteAddr(), socksAddr) }
func handleSocks5Request(req *gosocks5.Request, conn net.Conn) { glog.V(LDEBUG).Infoln(req) switch req.Cmd { case gosocks5.CmdConnect: glog.V(LINFO).Infoln("[socks5] CONNECT", req.Addr) tconn, err := Connect(req.Addr.String()) if err != nil { glog.V(LWARNING).Infoln("[socks5] CONNECT", req.Addr, err) rep := gosocks5.NewReply(gosocks5.HostUnreachable, nil) if err := rep.Write(conn); err != nil { glog.V(LWARNING).Infoln("socks5 connect:", err) } else { glog.V(LDEBUG).Infoln(rep) } return } defer tconn.Close() rep := gosocks5.NewReply(gosocks5.Succeeded, nil) if err := rep.Write(conn); err != nil { glog.V(LWARNING).Infoln("socks5 connect:", err) return } glog.V(LDEBUG).Infoln(rep) glog.V(LINFO).Infoln("[socks5] CONNECT", req.Addr, "OK") Transport(conn, tconn) case gosocks5.CmdBind: glog.V(LINFO).Infoln("[socks5] BIND", req.Addr) if len(forwardArgs) > 0 { forwardBind(req, conn) } else { serveBind(conn) } case gosocks5.CmdUdp, CmdUdpTun: glog.V(LINFO).Infoln("[socks5] UDP ASSOCIATE", req.Addr) uconn, err := net.ListenUDP("udp", nil) if err != nil { glog.V(LWARNING).Infoln("socks5 udp listen:", err) rep := gosocks5.NewReply(gosocks5.Failure, nil) if err := rep.Write(conn); err != nil { glog.V(LWARNING).Infoln("socks5 udp listen:", err) } else { glog.V(LDEBUG).Infoln(rep) } return } defer uconn.Close() addr := ToSocksAddr(uconn.LocalAddr()) addr.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String()) rep := gosocks5.NewReply(gosocks5.Succeeded, addr) if err := rep.Write(conn); err != nil { glog.V(LWARNING).Infoln("socks5 udp:", err) return } else { glog.V(LDEBUG).Infoln(rep) glog.V(LINFO).Infoln("[socks5] UDP listen on", addr) } var cc *UDPConn var dgram *gosocks5.UDPDatagram if req.Cmd == CmdUdpTun { dgram, err = gosocks5.ReadUDPDatagram(conn) if err != nil { glog.V(LWARNING).Infoln("socks5 udp:", err) return } cc = Client(conn, nil) glog.V(LINFO).Infof("[udp] -> %s, length %d", dgram.Header.Addr, len(dgram.Data)) } else { b := udpPool.Get().([]byte) defer udpPool.Put(b) n, raddr, err := uconn.ReadFromUDP(b) if err != nil { glog.V(LWARNING).Infoln("socks5 udp:", err) return } dgram, err = gosocks5.ReadUDPDatagram(bytes.NewReader(b[:n])) if err != nil { glog.V(LWARNING).Infoln("socks5 udp:", err) return } cc = Client(uconn, raddr) glog.V(LINFO).Infof("[udp] %s -> %s, length %d", raddr, dgram.Header.Addr, len(dgram.Data)) } sc, err := createServerConn(uconn) if err != nil { glog.V(LWARNING).Infoln("socks5 udp:", err) return } defer sc.Close() if err = sc.WriteUDPTimeout(dgram, time.Second*90); err != nil { glog.V(LWARNING).Infoln("socks5 udp:", err) return } dgram, err = sc.ReadUDPTimeout(time.Second * 90) if err != nil { glog.V(LWARNING).Infoln("socks5 udp:", err) return } glog.V(LINFO).Infof("[udp] <- %s, length %d", dgram.Header.Addr, len(dgram.Data)) if err = cc.WriteUDPTimeout(dgram, time.Second*90); err != nil { glog.V(LWARNING).Infoln("socks5 udp:", err) return } if req.Cmd == gosocks5.CmdUdp { go TransportUDP(cc, sc) ioutil.ReadAll(conn) // wait for client exit glog.V(LINFO).Infoln("[udp] transfer done") } else { TransportUDP(cc, sc) } default: glog.V(LWARNING).Infoln("Unrecognized request: ", req) } }
func handleSocks5Request(req *gosocks5.Request, conn net.Conn, arg Args) { if glog.V(LDEBUG) { glog.Infoln(req) } switch req.Cmd { case gosocks5.CmdConnect: if glog.V(LINFO) { glog.Infoln("socks5 connect:", req.Addr.String()) } tconn, err := connect(req.Addr.String()) if err != nil { if glog.V(LWARNING) { glog.Warningln("socks5 connect:", err) } rep := gosocks5.NewReply(gosocks5.HostUnreachable, nil) if err := rep.Write(conn); err != nil { if glog.V(LWARNING) { glog.Warningln("socks5 connect:", err) } } else { if glog.V(LDEBUG) { glog.Infoln(rep) } } return } defer tconn.Close() rep := gosocks5.NewReply(gosocks5.Succeeded, nil) if err := rep.Write(conn); err != nil { if glog.V(LWARNING) { glog.Warningln("socks5 connect:", err) } return } if glog.V(LDEBUG) { glog.Infoln(rep) } Transport(conn, tconn) case gosocks5.CmdBind: l, err := net.ListenTCP("tcp", nil) if err != nil { if glog.V(LWARNING) { glog.Warningln("socks5 bind listen:", err) } rep := gosocks5.NewReply(gosocks5.Failure, nil) if err := rep.Write(conn); err != nil { if glog.V(LWARNING) { glog.Warningln("socks5 bind listen:", err) } } else { if glog.V(LDEBUG) { glog.Infoln(rep) } } return } addr := ToSocksAddr(l.Addr()) addr.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String()) if glog.V(LINFO) { glog.Infoln("socks5 bind:", addr) } rep := gosocks5.NewReply(gosocks5.Succeeded, addr) if err := rep.Write(conn); err != nil { if glog.V(LWARNING) { glog.Warningln("socks5 bind:", err) } l.Close() return } if glog.V(LDEBUG) { glog.Infoln(rep) } tconn, err := l.AcceptTCP() l.Close() // only accept one peer if err != nil { if glog.V(LWARNING) { glog.Warningln("socks5 bind accept:", err) } rep = gosocks5.NewReply(gosocks5.Failure, nil) if err := rep.Write(conn); err != nil { if glog.V(LWARNING) { glog.Warningln("socks5 bind accept:", err) } } else { if glog.V(LDEBUG) { glog.Infoln(rep) } } return } defer tconn.Close() addr = ToSocksAddr(tconn.RemoteAddr()) if glog.V(LINFO) { glog.Infoln("socks5 bind accept:", addr.String()) } rep = gosocks5.NewReply(gosocks5.Succeeded, addr) if err := rep.Write(conn); err != nil { if glog.V(LWARNING) { glog.Warningln("socks5 bind accept:", err) } return } if glog.V(LDEBUG) { glog.Infoln(rep) } if err := Transport(conn, tconn); err != nil { //log.Println(err) } case gosocks5.CmdUdp: uconn, err := net.ListenUDP("udp", nil) if err != nil { if glog.V(LWARNING) { glog.Warningln("socks5 udp listen:", err) } rep := gosocks5.NewReply(gosocks5.Failure, nil) if err := rep.Write(conn); err != nil { if glog.V(LWARNING) { glog.Warningln("socks5 udp listen:", err) } } else { if glog.V(LDEBUG) { glog.Infoln(rep) } } return } defer uconn.Close() addr := ToSocksAddr(uconn.LocalAddr()) addr.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String()) if glog.V(LINFO) { glog.Infoln("socks5 udp:", addr) } rep := gosocks5.NewReply(gosocks5.Succeeded, addr) if err := rep.Write(conn); err != nil { if glog.V(LWARNING) { glog.Warningln("socks5 udp:", err) } return } else { if glog.V(LDEBUG) { glog.Infoln(rep) } } srvTunnelUDP(conn, uconn) } }