func cliTunnelUDP(uconn *net.UDPConn, sconn net.Conn) { var raddr *net.UDPAddr go func() { b := lpool.Take() defer lpool.put(b) for { n, addr, err := uconn.ReadFromUDP(b) if err != nil { log.Println(err) return } raddr = addr r := bytes.NewBuffer(b[:n]) udp, err := gosocks5.ReadUDPDatagram(r) if err != nil { return } udp.Header.Rsv = uint16(len(udp.Data)) //log.Println("r", raddr.String(), udp.Header) if err := udp.Write(sconn); err != nil { log.Println(err) return } } }() for { b := lpool.Take() defer lpool.put(b) udp, err := gosocks5.ReadUDPDatagram(sconn) if err != nil { log.Println(err) return } //log.Println("w", udp.Header) udp.Header.Rsv = 0 buf := bytes.NewBuffer(b[0:0]) udp.Write(buf) if _, err := uconn.WriteTo(buf.Bytes(), raddr); err != nil { log.Println(err) return } } }
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 createClientConn(conn net.Conn, uconn *net.UDPConn) (c *UDPConn, dgram *gosocks5.UDPDatagram, err error) { var raddr *net.UDPAddr dgramChan := make(chan *gosocks5.UDPDatagram, 1) errChan := make(chan error, 1) go func() { b := make([]byte, 64*1024+262) n, addr, err := uconn.ReadFromUDP(b) if err != nil { errChan <- err return } raddr = addr dgram, err := gosocks5.ReadUDPDatagram(bytes.NewReader(b[:n])) if err != nil { errChan <- err return } dgramChan <- dgram }() go func() { dgram, err := gosocks5.ReadUDPDatagram(conn) if err != nil { errChan <- err return } dgramChan <- dgram }() select { case dgram = <-dgramChan: if raddr != nil { glog.V(LINFO).Infoln("[udp] client", raddr) c = Client(uconn, raddr) } else { glog.V(LINFO).Infoln("[udp] tunnel") c = Client(conn, nil) } case err = <-errChan: } return }
func (c *UDPConn) readUDPServer() (*gosocks5.UDPDatagram, error) { if c.udp != nil { b := make([]byte, 65535) n, addr, err := c.udp.ReadFrom(b) if err != nil { return nil, err } dgram := gosocks5.NewUDPDatagram( gosocks5.NewUDPHeader(0, 0, ToSocksAddr(addr)), b[:n]) return dgram, nil } return gosocks5.ReadUDPDatagram(c.tcp) }
func srvTunnelUDP(conn net.Conn, uconn *net.UDPConn) { go func() { b := make([]byte, 16*1024) for { n, addr, err := uconn.ReadFromUDP(b) if err != nil { if glog.V(LWARNING) { glog.Warningln(err) } return } udp := gosocks5.NewUDPDatagram( gosocks5.NewUDPHeader(uint16(n), 0, ToSocksAddr(addr)), b[:n]) //log.Println("r", udp.Header) if err := udp.Write(conn); err != nil { if glog.V(LWARNING) { glog.Warningln(err) } return } } }() for { udp, err := gosocks5.ReadUDPDatagram(conn) if err != nil { if glog.V(LWARNING) { glog.Warningln(err) } return } //log.Println("w", udp.Header) addr, err := net.ResolveUDPAddr("udp", udp.Header.Addr.String()) if err != nil { if glog.V(LWARNING) { glog.Warningln(err) } continue // drop silently } if _, err := uconn.WriteToUDP(udp.Data, addr); err != nil { if glog.V(LWARNING) { glog.Warningln(err) } return } } }
func srvTunnelUDP(conn net.Conn, uconn *net.UDPConn) { go func() { b := lpool.Take() defer lpool.put(b) for { n, addr, err := uconn.ReadFromUDP(b) if err != nil { log.Println(err) return } udp := gosocks5.NewUDPDatagram( gosocks5.NewUDPHeader(uint16(n), 0, ToSocksAddr(addr)), b[:n]) //log.Println("r", udp.Header) if err := udp.Write(conn); err != nil { log.Println(err) return } } }() for { udp, err := gosocks5.ReadUDPDatagram(conn) if err != nil { log.Println(err) return } //log.Println("w", udp.Header) addr, err := net.ResolveUDPAddr("udp", udp.Header.Addr.String()) if err != nil { log.Println(err) continue // drop silently } if _, err := uconn.WriteToUDP(udp.Data, addr); err != nil { log.Println(err) return } } }
func (s *Socks5Server) tunnelUDP(uc *net.UDPConn, cc net.Conn, client bool) (err error) { errc := make(chan error, 2) var clientAddr *net.UDPAddr go func() { b := make([]byte, LargeBufferSize) for { n, addr, err := uc.ReadFromUDP(b) if err != nil { errc <- err return } var dgram *gosocks5.UDPDatagram if client { // pipe from relay to tunnel dgram, err = gosocks5.ReadUDPDatagram(bytes.NewReader(b[:n])) if err != nil { errc <- err return } if clientAddr == nil { clientAddr = addr } dgram.Header.Rsv = uint16(len(dgram.Data)) if err := dgram.Write(cc); err != nil { errc <- err return } glog.V(LDEBUG).Infof("[udp-tun] %s >>> %s length: %d", uc.LocalAddr(), dgram.Header.Addr, len(dgram.Data)) } else { // pipe from peer to tunnel dgram = gosocks5.NewUDPDatagram( gosocks5.NewUDPHeader(uint16(n), 0, ToSocksAddr(addr)), b[:n]) if err := dgram.Write(cc); err != nil { errc <- err return } glog.V(LDEBUG).Infof("[udp-tun] %s <<< %s length: %d", cc.RemoteAddr(), dgram.Header.Addr, len(dgram.Data)) } } }() go func() { for { dgram, err := gosocks5.ReadUDPDatagram(cc) if err != nil { errc <- err return } if client { // pipe from tunnel to relay if clientAddr == nil { continue } dgram.Header.Rsv = 0 buf := bytes.Buffer{} dgram.Write(&buf) if _, err := uc.WriteToUDP(buf.Bytes(), clientAddr); err != nil { errc <- err return } glog.V(LDEBUG).Infof("[udp-tun] %s <<< %s length: %d", uc.LocalAddr(), dgram.Header.Addr, len(dgram.Data)) } else { // pipe from tunnel to peer addr, err := net.ResolveUDPAddr("udp", dgram.Header.Addr.String()) if err != nil { continue // drop silently } if _, err := uc.WriteToUDP(dgram.Data, addr); err != nil { errc <- err return } glog.V(LDEBUG).Infof("[udp-tun] %s >>> %s length: %d", cc.RemoteAddr(), addr, len(dgram.Data)) } } }() select { case err = <-errc: } return }
func (s *Socks5Server) transportUDP(relay, peer *net.UDPConn) (err error) { errc := make(chan error, 2) var clientAddr *net.UDPAddr go func() { b := make([]byte, LargeBufferSize) for { n, laddr, err := relay.ReadFromUDP(b) if err != nil { errc <- err return } if clientAddr == nil { clientAddr = laddr } dgram, err := gosocks5.ReadUDPDatagram(bytes.NewReader(b[:n])) if err != nil { errc <- err return } raddr, err := net.ResolveUDPAddr("udp", dgram.Header.Addr.String()) if err != nil { continue // drop silently } if _, err := peer.WriteToUDP(dgram.Data, raddr); err != nil { errc <- err return } glog.V(LDEBUG).Infof("[socks5-udp] %s >>> %s length: %d", relay.LocalAddr(), raddr, len(dgram.Data)) } }() go func() { b := make([]byte, LargeBufferSize) for { n, raddr, err := peer.ReadFromUDP(b) if err != nil { errc <- err return } if clientAddr == nil { continue } buf := bytes.Buffer{} dgram := gosocks5.NewUDPDatagram(gosocks5.NewUDPHeader(0, 0, ToSocksAddr(raddr)), b[:n]) dgram.Write(&buf) if _, err := relay.WriteToUDP(buf.Bytes(), clientAddr); err != nil { errc <- err return } glog.V(LDEBUG).Infof("[socks5-udp] %s <<< %s length: %d", relay.LocalAddr(), raddr, len(dgram.Data)) } }() select { case err = <-errc: //log.Println("w exit", err) } return }
func (c *UDPConn) readUDPClient() (*gosocks5.UDPDatagram, error) { if c.udp != nil { return gosocks5.ReadUDPDatagram(c.udp) } return gosocks5.ReadUDPDatagram(c.tcp) }
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 (s *RUdpForwardServer) connectRUdpForward(conn net.Conn, laddr, raddr *net.UDPAddr) error { glog.V(LINFO).Infof("[rudp] %s - %s", laddr, raddr) req := gosocks5.NewRequest(CmdUdpTun, ToSocksAddr(laddr)) conn.SetWriteDeadline(time.Now().Add(WriteTimeout)) if err := req.Write(conn); err != nil { glog.V(LWARNING).Infof("[rudp] %s -> %s : %s", laddr, raddr, err) return err } conn.SetWriteDeadline(time.Time{}) conn.SetReadDeadline(time.Now().Add(ReadTimeout)) rep, err := gosocks5.ReadReply(conn) if err != nil { glog.V(LWARNING).Infof("[rudp] %s <- %s : %s", laddr, raddr, err) return err } conn.SetReadDeadline(time.Time{}) if rep.Rep != gosocks5.Succeeded { glog.V(LWARNING).Infof("[rudp] %s <- %s : bind on %s failure", laddr, raddr, laddr) return errors.New(fmt.Sprintf("bind on %s failure", laddr)) } glog.V(LINFO).Infof("[rudp] %s - %s BIND ON %s OK", laddr, raddr, rep.Addr) for { dgram, err := gosocks5.ReadUDPDatagram(conn) if err != nil { glog.V(LWARNING).Infof("[rudp] %s <- %s : %s", laddr, raddr, err) return err } go func() { b := make([]byte, MediumBufferSize) relay, err := net.DialUDP("udp", nil, raddr) if err != nil { glog.V(LWARNING).Infof("[rudp] %s -> %s : %s", laddr, raddr, err) return } defer relay.Close() if _, err := relay.Write(dgram.Data); err != nil { glog.V(LWARNING).Infof("[rudp] %s -> %s : %s", laddr, raddr, err) return } glog.V(LDEBUG).Infof("[rudp] %s >>> %s length: %d", laddr, raddr, len(dgram.Data)) relay.SetReadDeadline(time.Now().Add(ReadTimeout)) n, err := relay.Read(b) if err != nil { glog.V(LWARNING).Infof("[rudp] %s <- %s : %s", laddr, raddr, err) return } relay.SetReadDeadline(time.Time{}) glog.V(LDEBUG).Infof("[rudp] %s <<< %s length: %d", laddr, raddr, n) conn.SetWriteDeadline(time.Now().Add(WriteTimeout)) if err := gosocks5.NewUDPDatagram(gosocks5.NewUDPHeader(uint16(n), 0, dgram.Header.Addr), b[:n]).Write(conn); err != nil { glog.V(LWARNING).Infof("[rudp] %s <- %s : %s", laddr, raddr, err) return } conn.SetWriteDeadline(time.Time{}) }() } }
func (s *UdpForwardServer) handleUdpForwardTunnel(laddr, raddr *net.UDPAddr, rChan, wChan chan *gosocks5.UDPDatagram) { var cc net.Conn var err error retry := 0 for { cc, err = s.prepareUdpConnectTunnel(raddr) if err != nil { glog.V(LWARNING).Infof("[udp] %s -> %s : %s", laddr, raddr, err) time.Sleep((1 << uint(retry)) * time.Second) if retry < 5 { retry++ } continue } break } defer cc.Close() glog.V(LINFO).Infof("[udp] %s <-> %s", laddr, raddr) rExit := make(chan interface{}) errc := make(chan error, 2) go func() { for { select { case dgram := <-rChan: if err := dgram.Write(cc); err != nil { glog.V(LWARNING).Infof("[udp] %s -> %s : %s", laddr, raddr, err) errc <- err return } glog.V(LDEBUG).Infof("[udp-tun] %s >>> %s length: %d", laddr, raddr, len(dgram.Data)) case <-rExit: // glog.V(LDEBUG).Infof("[udp-connect] %s -> %s : exited", laddr, raddr) return } } }() go func() { for { dgram, err := gosocks5.ReadUDPDatagram(cc) if err != nil { glog.V(LWARNING).Infof("[udp] %s <- %s : %s", laddr, raddr, err) close(rExit) errc <- err return } select { case wChan <- dgram: glog.V(LDEBUG).Infof("[udp-tun] %s <<< %s length: %d", laddr, raddr, len(dgram.Data)) default: } } }() select { case <-errc: //log.Println("w exit", err) } glog.V(LINFO).Infof("[udp] %s >-< %s", laddr, raddr) }