Example #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)
}
Example #2
0
func requestSocks5(conn net.Conn, req *gosocks5.Request) (*gosocks5.Reply, error) {
	if err := req.Write(conn); err != nil {
		return nil, err
	}
	if glog.V(LDEBUG) {
		glog.Infoln(req.String())
	}
	rep, err := gosocks5.ReadReply(conn)
	if err != nil {
		return nil, err
	}
	if glog.V(LDEBUG) {
		glog.Infoln(rep.String())
	}
	return rep, nil
}
Example #3
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())
}
Example #4
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)
}
Example #5
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)
}