Ejemplo n.º 1
0
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)
}
Ejemplo n.º 2
0
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)
	}
}
Ejemplo n.º 3
0
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{})
		}()
	}
}
Ejemplo n.º 4
0
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)
}
Ejemplo n.º 5
0
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
}
Ejemplo n.º 6
0
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())
}
Ejemplo n.º 7
0
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)
}
Ejemplo n.º 8
0
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)
}
Ejemplo n.º 9
0
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
}
Ejemplo n.º 10
0
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)
	}
}
Ejemplo n.º 11
0
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)
	}
}
Ejemplo n.º 12
0
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
		}
	}
}
Ejemplo n.º 13
0
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)
}
Ejemplo n.º 14
0
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)
	}
}
Ejemplo n.º 15
0
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)
	}
}