add udp port forwarding
This commit is contained in:
parent
1814806ecf
commit
3c79cf44b7
31
conn.go
31
conn.go
@ -55,8 +55,7 @@ func listenAndServe(arg Args) error {
|
||||
case "tcp": // TCP port forwarding
|
||||
return listenAndServeTcpForward(arg)
|
||||
case "udp": // UDP port forwarding
|
||||
//return listenAndServeUdpForward(arg)
|
||||
return nil
|
||||
return listenAndServeUdpForward(arg)
|
||||
default:
|
||||
ln, err = net.Listen("tcp", arg.Addr)
|
||||
}
|
||||
@ -82,6 +81,8 @@ func listenAndServeTcpForward(arg Args) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer ln.Close()
|
||||
|
||||
for {
|
||||
conn, err := ln.Accept()
|
||||
if err != nil {
|
||||
@ -93,29 +94,32 @@ func listenAndServeTcpForward(arg Args) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
/*
|
||||
func listenAndServeUdpForward(arg Args) error {
|
||||
addr, err := net.ResolveUDPAddr("udp", arg.Addr)
|
||||
laddr, err := net.ResolveUDPAddr("udp", arg.Addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ln, err := net.ListenUDP("udp", addr)
|
||||
ln, err := net.ListenUDP("udp", laddr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer ln.Close()
|
||||
|
||||
for {
|
||||
b := udpPool.Get().([]byte)
|
||||
defer udpPool.Put(b)
|
||||
|
||||
_, c, err := ln.ReadFromUDP(b)
|
||||
n, raddr, err := ln.ReadFromUDP(b)
|
||||
if err != nil {
|
||||
glog.V(LWARNING).Infoln(err)
|
||||
continue
|
||||
}
|
||||
handleUdpForward(c, arg)
|
||||
go func(data []byte, length int) {
|
||||
handleUdpForward(ln, raddr, data[:length], arg)
|
||||
udpPool.Put(data)
|
||||
}(b, n)
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
func handleConn(conn net.Conn, arg Args) {
|
||||
atomic.AddInt32(&connCounter, 1)
|
||||
glog.V(LINFO).Infof("%s connected, connections: %d",
|
||||
@ -261,6 +265,7 @@ func Connect(addr string) (conn net.Conn, err error) {
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
// establish connection throughout the forward chain
|
||||
func forwardChain(chain ...Args) (conn net.Conn, end Args, err error) {
|
||||
end = chain[0]
|
||||
if conn, err = net.DialTimeout("tcp", end.Addr, time.Second*90); err != nil {
|
||||
@ -294,10 +299,14 @@ func forward(conn net.Conn, arg Args) (net.Conn, error) {
|
||||
var err error
|
||||
if glog.V(LINFO) {
|
||||
proto := arg.Protocol
|
||||
if proto == "default" {
|
||||
trans := arg.Transport
|
||||
if proto == "" {
|
||||
proto = "http" // default is http
|
||||
}
|
||||
glog.Infof("forward: %s/%s %s", proto, arg.Transport, arg.Addr)
|
||||
if trans == "" { // default is tcp
|
||||
trans = "tcp"
|
||||
}
|
||||
glog.Infof("forward: %s/%s %s", proto, trans, arg.Addr)
|
||||
}
|
||||
|
||||
var tlsUsed bool
|
||||
|
69
forward.go
69
forward.go
@ -1,23 +1,84 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/ginuerzh/gosocks5"
|
||||
"github.com/golang/glog"
|
||||
"net"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func handleTcpForward(conn net.Conn, arg Args) {
|
||||
glog.V(LINFO).Infoln("[tcp-forward] CONNECT", arg.Forward)
|
||||
defer conn.Close()
|
||||
glog.V(LINFO).Infof("[tcp-forward] %s -> %s", conn.RemoteAddr(), arg.Forward)
|
||||
c, err := Connect(arg.Forward)
|
||||
if err != nil {
|
||||
glog.V(LWARNING).Infoln("[tcp-forward] CONNECT", arg.Forward, err)
|
||||
glog.V(LWARNING).Infof("[tcp-forward] %s -> %s : %s", conn.RemoteAddr(), arg.Forward, err)
|
||||
return
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
glog.V(LINFO).Infoln("[tcp-forward] CONNECT", arg.Forward, "OK")
|
||||
glog.V(LINFO).Infof("[tcp-forward] %s <-> %s OK", conn.RemoteAddr(), arg.Forward)
|
||||
Transport(conn, c)
|
||||
glog.V(LINFO).Infof("[tcp-forward] %s >-< %s DISCONNECTED", conn.RemoteAddr(), arg.Forward)
|
||||
}
|
||||
|
||||
func handleUdpForward(conn *net.UDPConn, arg Args) {
|
||||
func handleUdpForward(conn *net.UDPConn, raddr *net.UDPAddr, data []byte, arg Args) {
|
||||
if !strings.Contains(arg.Forward, ":") {
|
||||
arg.Forward += ":53"
|
||||
}
|
||||
glog.V(LINFO).Infof("[udp-forward] %s -> %s", raddr, arg.Forward)
|
||||
fconn, _, err := forwardChain(forwardArgs...)
|
||||
if err != nil {
|
||||
glog.V(LWARNING).Infof("[udp-forward] %s -> %s : %s", raddr, arg.Forward, err)
|
||||
if fconn != nil {
|
||||
fconn.Close()
|
||||
}
|
||||
return
|
||||
}
|
||||
defer fconn.Close()
|
||||
|
||||
glog.V(LINFO).Infof("[udp-forward] %s -> %s ASSOCIATE", raddr, arg.Forward)
|
||||
|
||||
req := gosocks5.NewRequest(CmdUdpTun, nil)
|
||||
if err = req.Write(fconn); err != nil {
|
||||
glog.V(LWARNING).Infof("[udp-forward] %s -> %s ASSOCIATE : %s", raddr, arg.Forward, err)
|
||||
return
|
||||
}
|
||||
glog.V(LDEBUG).Infof("[udp-forward] %s -> %s\n%s", raddr, arg.Forward, req)
|
||||
|
||||
rep, err := gosocks5.ReadReply(fconn)
|
||||
if err != nil {
|
||||
glog.V(LWARNING).Infof("[udp-forward] %s <- %s ASSOCIATE : %s", raddr, arg.Forward, err)
|
||||
return
|
||||
}
|
||||
glog.V(LDEBUG).Infof("[udp-forward] %s <- %s\n%s", raddr, arg.Forward, rep)
|
||||
if rep.Rep != gosocks5.Succeeded {
|
||||
glog.V(LWARNING).Infof("[udp-forward] %s <- %s ASSOCIATE failured", raddr, arg.Forward)
|
||||
return
|
||||
}
|
||||
glog.V(LINFO).Infof("[udp-forward] %s <-> %s ASSOCIATE ON %s OK", raddr, arg.Forward, rep.Addr)
|
||||
|
||||
addr, err := net.ResolveUDPAddr("udp", arg.Forward)
|
||||
if err != nil {
|
||||
glog.V(LWARNING).Infof("[udp-forward] %s -> %s : %s", raddr, arg.Forward, err)
|
||||
return
|
||||
}
|
||||
dgram := gosocks5.NewUDPDatagram(
|
||||
gosocks5.NewUDPHeader(uint16(len(data)), 0, ToSocksAddr(addr)), data)
|
||||
if err = dgram.Write(fconn); err != nil {
|
||||
glog.V(LWARNING).Infof("[udp-forward] %s -> %s : %s", raddr, arg.Forward, err)
|
||||
return
|
||||
}
|
||||
glog.V(LINFO).Infof("[udp-forward] %s >>> %s length %d", raddr, arg.Forward, len(data))
|
||||
|
||||
dgram, err = gosocks5.ReadUDPDatagram(fconn)
|
||||
if err != nil {
|
||||
glog.V(LWARNING).Infof("[udp-forward] %s <- %s : %s", raddr, arg.Forward, err)
|
||||
return
|
||||
}
|
||||
glog.V(LINFO).Infof("[udp-forward] %s <<< %s length %d", raddr, arg.Forward, len(dgram.Data))
|
||||
|
||||
if _, err = conn.WriteToUDP(dgram.Data, raddr); err != nil {
|
||||
glog.V(LWARNING).Infof("[udp-forward] %s <- %s : %s", raddr, arg.Forward, err)
|
||||
}
|
||||
}
|
||||
|
21
http.go
21
http.go
@ -18,7 +18,7 @@ func handleHttpRequest(req *http.Request, conn net.Conn, arg Args) {
|
||||
glog.Infoln(string(dump))
|
||||
}
|
||||
}
|
||||
glog.V(LINFO).Infoln("[http] CONNECT", req.Host)
|
||||
glog.V(LINFO).Infof("[http] %s -> %s", conn.RemoteAddr(), req.Host)
|
||||
|
||||
var username, password string
|
||||
if arg.User != nil {
|
||||
@ -34,21 +34,21 @@ func handleHttpRequest(req *http.Request, conn net.Conn, arg Args) {
|
||||
"Proxy-Agent: gost/" + Version + "\r\n\r\n"
|
||||
|
||||
if _, err := conn.Write([]byte(resp)); err != nil {
|
||||
glog.V(LWARNING).Infoln(err)
|
||||
glog.V(LWARNING).Infof("[http] %s <- %s : %s", conn.RemoteAddr(), req.Host, err)
|
||||
}
|
||||
glog.V(LDEBUG).Infoln(resp)
|
||||
glog.V(LDEBUG).Infof("[http] %s <- %s\n%s", conn.RemoteAddr(), req.Host, resp)
|
||||
|
||||
glog.V(LWARNING).Infoln("http: proxy authentication required")
|
||||
glog.V(LWARNING).Infof("[http] %s <- %s : proxy authentication required", conn.RemoteAddr(), req.Host)
|
||||
return
|
||||
}
|
||||
|
||||
c, err := Connect(req.Host)
|
||||
if err != nil {
|
||||
glog.V(LWARNING).Infoln("[http] CONNECT", req.Host, err)
|
||||
glog.V(LWARNING).Infof("[http] %s -> %s : %s", conn.RemoteAddr(), req.Host, err)
|
||||
|
||||
b := []byte("HTTP/1.1 503 Service unavailable\r\n" +
|
||||
"Proxy-Agent: gost/" + Version + "\r\n\r\n")
|
||||
glog.V(LDEBUG).Infoln(string(b))
|
||||
glog.V(LDEBUG).Infof("[http] %s <- %s\n%s", conn.RemoteAddr(), req.Host, string(b))
|
||||
conn.Write(b)
|
||||
return
|
||||
}
|
||||
@ -57,10 +57,10 @@ func handleHttpRequest(req *http.Request, conn net.Conn, arg Args) {
|
||||
if req.Method == "CONNECT" {
|
||||
b := []byte("HTTP/1.1 200 Connection established\r\n" +
|
||||
"Proxy-Agent: gost/" + Version + "\r\n\r\n")
|
||||
glog.V(LDEBUG).Infoln(string(b))
|
||||
glog.V(LDEBUG).Infof("[http] %s <- %s\n%s", conn.RemoteAddr(), req.Host, string(b))
|
||||
|
||||
if _, err := conn.Write(b); err != nil {
|
||||
glog.V(LWARNING).Infoln(err)
|
||||
glog.V(LWARNING).Infof("[http] %s <- %s : %s", conn.RemoteAddr(), req.Host, err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
@ -68,13 +68,14 @@ func handleHttpRequest(req *http.Request, conn net.Conn, arg Args) {
|
||||
req.Header.Set("Connection", "Keep-Alive")
|
||||
|
||||
if err = req.Write(c); err != nil {
|
||||
glog.V(LWARNING).Infoln(err)
|
||||
glog.V(LWARNING).Infof("[http] %s -> %s : %s", conn.RemoteAddr(), req.Host, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
glog.V(LINFO).Infoln("[http] CONNECT", req.Host, "OK")
|
||||
glog.V(LINFO).Infof("[http] %s <-> %s OK", conn.RemoteAddr(), req.Host)
|
||||
Transport(conn, c)
|
||||
glog.V(LINFO).Infof("[http] %s >-< %s DISCONNECTED", conn.RemoteAddr(), req.Host)
|
||||
}
|
||||
|
||||
func basicAuth(authInfo string) (username, password string, ok bool) {
|
||||
|
51
socks.go
51
socks.go
@ -162,20 +162,20 @@ func (selector *serverSelector) OnSelected(method uint8, conn net.Conn) (net.Con
|
||||
}
|
||||
|
||||
func handleSocks5Request(req *gosocks5.Request, conn net.Conn) {
|
||||
glog.V(LDEBUG).Infoln(req)
|
||||
glog.V(LDEBUG).Infof("[socks5-connect] %s -> %s\n%s", conn.RemoteAddr(), req.Addr, req)
|
||||
|
||||
switch req.Cmd {
|
||||
case gosocks5.CmdConnect:
|
||||
glog.V(LINFO).Infoln("[socks5] CONNECT", req.Addr)
|
||||
glog.V(LINFO).Infof("[socks5-connect] %s -> %s", conn.RemoteAddr(), req.Addr)
|
||||
|
||||
tconn, err := Connect(req.Addr.String())
|
||||
if err != nil {
|
||||
glog.V(LWARNING).Infoln("[socks5] CONNECT", req.Addr, err)
|
||||
glog.V(LWARNING).Infof("[socks5-connect] %s -> %s : %s", conn.RemoteAddr(), req.Addr, err)
|
||||
rep := gosocks5.NewReply(gosocks5.HostUnreachable, nil)
|
||||
if err := rep.Write(conn); err != nil {
|
||||
glog.V(LWARNING).Infoln("socks5 connect:", err)
|
||||
glog.V(LWARNING).Infof("[socks5-connect] %s <- %s : %s", conn.RemoteAddr(), req.Addr, err)
|
||||
} else {
|
||||
glog.V(LDEBUG).Infoln(rep)
|
||||
glog.V(LDEBUG).Infof("[socks5-connect] %s <- %s\n%s", conn.RemoteAddr(), req.Addr, rep)
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -183,47 +183,50 @@ func handleSocks5Request(req *gosocks5.Request, conn net.Conn) {
|
||||
|
||||
rep := gosocks5.NewReply(gosocks5.Succeeded, nil)
|
||||
if err := rep.Write(conn); err != nil {
|
||||
glog.V(LWARNING).Infoln("socks5 connect:", err)
|
||||
glog.V(LWARNING).Infof("[socks5-connect] %s <- %s : %s", conn.RemoteAddr(), req.Addr, err)
|
||||
return
|
||||
}
|
||||
glog.V(LDEBUG).Infoln(rep)
|
||||
glog.V(LDEBUG).Infof("[socks5-connect] %s <- %s\n%s", conn.RemoteAddr(), req.Addr, rep)
|
||||
|
||||
glog.V(LINFO).Infoln("[socks5] CONNECT", req.Addr, "OK")
|
||||
glog.V(LINFO).Infof("[socks5-connect] %s <-> %s OK", conn.RemoteAddr(), req.Addr)
|
||||
Transport(conn, tconn)
|
||||
glog.V(LINFO).Infof("[socks5-connect] %s >-< %s DISCONNECTED", conn.RemoteAddr(), req.Addr)
|
||||
case gosocks5.CmdBind:
|
||||
glog.V(LINFO).Infoln("[socks5] BIND", req.Addr)
|
||||
glog.V(LINFO).Infof("[socks5-bind] %s -> %s", conn.RemoteAddr(), req.Addr)
|
||||
|
||||
if len(forwardArgs) > 0 {
|
||||
forwardBind(req, conn)
|
||||
} else {
|
||||
serveBind(conn)
|
||||
}
|
||||
glog.V(LINFO).Infof("[socks5-bind] %s >-< %s DISCONNECTED", conn.RemoteAddr(), req.Addr)
|
||||
case gosocks5.CmdUdp, CmdUdpTun:
|
||||
glog.V(LINFO).Infoln("[socks5] UDP ASSOCIATE", req.Addr)
|
||||
// TODO: udp tunnel <-> forward chain
|
||||
glog.V(LINFO).Infof("[socks5-udp] %s -> %s ASSOCIATE", conn.RemoteAddr(), req.Addr)
|
||||
uconn, err := net.ListenUDP("udp", nil)
|
||||
if err != nil {
|
||||
glog.V(LWARNING).Infoln("socks5 udp listen:", err)
|
||||
glog.V(LWARNING).Infof("[socks5-udp] %s -> %s : %s", conn.RemoteAddr(), req.Addr, err)
|
||||
|
||||
rep := gosocks5.NewReply(gosocks5.Failure, nil)
|
||||
if err := rep.Write(conn); err != nil {
|
||||
glog.V(LWARNING).Infoln("socks5 udp listen:", err)
|
||||
glog.V(LWARNING).Infof("[socks5-udp] %s <- %s : %s", conn.RemoteAddr(), req.Addr, err)
|
||||
} else {
|
||||
glog.V(LDEBUG).Infoln(rep)
|
||||
glog.V(LDEBUG).Infof("[socks5-udp] %s <- %s\n%s", conn.RemoteAddr(), req.Addr, rep)
|
||||
}
|
||||
return
|
||||
}
|
||||
defer uconn.Close()
|
||||
|
||||
addr := ToSocksAddr(uconn.LocalAddr())
|
||||
addr.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String())
|
||||
addr.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String()) // BUG: when server has multi-interfaces, this may cause a mistake
|
||||
|
||||
rep := gosocks5.NewReply(gosocks5.Succeeded, addr)
|
||||
if err := rep.Write(conn); err != nil {
|
||||
glog.V(LWARNING).Infoln("socks5 udp:", err)
|
||||
glog.V(LWARNING).Infof("[socks5-udp] %s <- %s : %s", conn.RemoteAddr(), req.Addr, err)
|
||||
return
|
||||
} else {
|
||||
glog.V(LDEBUG).Infoln(rep)
|
||||
glog.V(LINFO).Infoln("[socks5] UDP listen on", addr)
|
||||
glog.V(LDEBUG).Infof("[socks5-udp] %s <- %s\n%s", conn.RemoteAddr(), req.Addr, rep)
|
||||
glog.V(LINFO).Infof("[socks5-udp] %s -> %s LISTEN ON %s", conn.RemoteAddr(), req.Addr, addr)
|
||||
}
|
||||
|
||||
var cc *UDPConn
|
||||
@ -231,32 +234,32 @@ func handleSocks5Request(req *gosocks5.Request, conn net.Conn) {
|
||||
if req.Cmd == CmdUdpTun {
|
||||
dgram, err = gosocks5.ReadUDPDatagram(conn)
|
||||
if err != nil {
|
||||
glog.V(LWARNING).Infoln("socks5 udp:", err)
|
||||
glog.V(LWARNING).Infof("[socks5-udp] %s -> %s : %s", conn.RemoteAddr(), req.Addr, err)
|
||||
return
|
||||
}
|
||||
glog.V(LINFO).Infof("[socks5-udp] %s >>> %s, length %d", conn.RemoteAddr(), dgram.Header.Addr, len(dgram.Data))
|
||||
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)
|
||||
glog.V(LWARNING).Infof("[socks5-udp] %s -> %s : %s", conn.RemoteAddr(), req.Addr, err)
|
||||
return
|
||||
}
|
||||
dgram, err = gosocks5.ReadUDPDatagram(bytes.NewReader(b[:n]))
|
||||
if err != nil {
|
||||
glog.V(LWARNING).Infoln("socks5 udp:", err)
|
||||
glog.V(LWARNING).Infof("[socks5-udp] %s -> %s : %s", conn.RemoteAddr(), req.Addr, err)
|
||||
return
|
||||
}
|
||||
glog.V(LINFO).Infof("[socks5-udp] %s >>> %s, length %d", raddr, dgram.Header.Addr, len(dgram.Data))
|
||||
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)
|
||||
glog.V(LWARNING).Infof("[socks5-udp] %s", err)
|
||||
return
|
||||
}
|
||||
defer sc.Close()
|
||||
@ -270,7 +273,7 @@ func handleSocks5Request(req *gosocks5.Request, conn net.Conn) {
|
||||
glog.V(LWARNING).Infoln("socks5 udp:", err)
|
||||
return
|
||||
}
|
||||
glog.V(LINFO).Infof("[udp] <- %s, length %d", dgram.Header.Addr, len(dgram.Data))
|
||||
glog.V(LINFO).Infof("[socks5-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)
|
||||
|
Loading…
Reference in New Issue
Block a user