Commit aef1c86b authored by rui.zheng's avatar rui.zheng

#62 fix UDP port forwarding

parent 62d92d95
This diff is collapsed.
...@@ -28,6 +28,8 @@ var ( ...@@ -28,6 +28,8 @@ var (
DialTimeout = 30 * time.Second DialTimeout = 30 * time.Second
ReadTimeout = 90 * time.Second ReadTimeout = 90 * time.Second
WriteTimeout = 90 * time.Second WriteTimeout = 90 * time.Second
DefaultTTL = 60 // default udp node TTL in second for udp port forwarding
) )
var ( var (
......
...@@ -9,6 +9,7 @@ import ( ...@@ -9,6 +9,7 @@ import (
"io" "io"
"net" "net"
"net/http" "net/http"
"strconv"
) )
type ProxyServer struct { type ProxyServer struct {
...@@ -75,7 +76,11 @@ func (s *ProxyServer) Serve() error { ...@@ -75,7 +76,11 @@ func (s *ProxyServer) Serve() error {
case "tcp": // Local TCP port forwarding case "tcp": // Local TCP port forwarding
return NewTcpForwardServer(s).ListenAndServe() return NewTcpForwardServer(s).ListenAndServe()
case "udp": // Local UDP port forwarding case "udp": // Local UDP port forwarding
return NewUdpForwardServer(s).ListenAndServe() ttl, _ := strconv.Atoi(s.Node.Get("ttl"))
if ttl <= 0 {
ttl = DefaultTTL
}
return NewUdpForwardServer(s, ttl).ListenAndServe()
case "rtcp": // Remote TCP port forwarding case "rtcp": // Remote TCP port forwarding
return NewRTcpForwardServer(s).Serve() return NewRTcpForwardServer(s).Serve()
case "rudp": // Remote UDP port forwarding case "rudp": // Remote UDP port forwarding
......
...@@ -21,8 +21,7 @@ const ( ...@@ -21,8 +21,7 @@ const (
) )
const ( const (
CmdUdpConnect uint8 = 0xF1 // extended method for udp local port forwarding CmdUdpTun uint8 = 0xF3 // extended method for udp over tcp
CmdUdpTun uint8 = 0xF3 // extended method for udp over tcp
) )
type clientSelector struct { type clientSelector struct {
...@@ -190,10 +189,6 @@ func (s *Socks5Server) HandleRequest(req *gosocks5.Request) { ...@@ -190,10 +189,6 @@ func (s *Socks5Server) HandleRequest(req *gosocks5.Request) {
glog.V(LINFO).Infof("[socks5-bind] %s - %s", s.conn.RemoteAddr(), req.Addr) glog.V(LINFO).Infof("[socks5-bind] %s - %s", s.conn.RemoteAddr(), req.Addr)
s.handleBind(req) s.handleBind(req)
case CmdUdpConnect:
glog.V(LINFO).Infof("[udp] %s - %s", s.conn.RemoteAddr(), req.Addr)
s.handleUDPConnect(req)
case gosocks5.CmdUdp: case gosocks5.CmdUdp:
glog.V(LINFO).Infof("[socks5-udp] %s - %s", s.conn.RemoteAddr(), req.Addr) glog.V(LINFO).Infof("[socks5-udp] %s - %s", s.conn.RemoteAddr(), req.Addr)
s.handleUDPRelay(req) s.handleUDPRelay(req)
...@@ -257,38 +252,6 @@ func (s *Socks5Server) handleBind(req *gosocks5.Request) { ...@@ -257,38 +252,6 @@ func (s *Socks5Server) handleBind(req *gosocks5.Request) {
glog.V(LINFO).Infof("[socks5-bind] %s >-< %s", s.conn.RemoteAddr(), cc.RemoteAddr()) glog.V(LINFO).Infof("[socks5-bind] %s >-< %s", s.conn.RemoteAddr(), cc.RemoteAddr())
} }
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 (s *Socks5Server) handleUDPRelay(req *gosocks5.Request) { func (s *Socks5Server) handleUDPRelay(req *gosocks5.Request) {
bindAddr, _ := net.ResolveUDPAddr("udp", req.Addr.String()) 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 relay, err := net.ListenUDP("udp", bindAddr) // udp associate, strict mode: if the port already in use, it will return error
...@@ -506,65 +469,6 @@ func (s *Socks5Server) bindOn(addr string) { ...@@ -506,65 +469,6 @@ func (s *Socks5Server) bindOn(addr string) {
} }
} }
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 (s *Socks5Server) transportUDP(relay, peer *net.UDPConn) (err error) { func (s *Socks5Server) transportUDP(relay, peer *net.UDPConn) (err error) {
errc := make(chan error, 2) errc := make(chan error, 2)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment