From e849cbfcd8bc4eacfc16d0fff2b7e594decf443f Mon Sep 17 00:00:00 2001 From: arraykeys Date: Sat, 16 Jun 2018 17:14:43 +0800 Subject: [PATCH] add secure dns proxy support --- README.md | 5 +- README_ZH.md | 76 ++++++- config.go | 79 +++++-- install_auto.sh | 2 +- main.go | 2 +- release.sh | 2 +- sdk/android-ios/dns.go | 256 ++++++++++++++++++++++ sdk/android-ios/release_android.sh | 2 +- sdk/android-ios/release_ios.sh | 2 +- sdk/android-ios/sdk.go | 77 ++++--- sdk/windows-linux/release_linux.sh | 2 +- sdk/windows-linux/release_mac.sh | 2 +- sdk/windows-linux/release_windows.sh | 2 +- services/args.go | 285 ------------------------- services/{ => http}/http.go | 51 ++++- services/{ => mux}/mux_bridge.go | 33 ++- services/{ => mux}/mux_client.go | 22 +- services/{ => mux}/mux_server.go | 61 ++++-- services/{ => socks}/socks.go | 50 ++++- services/{ => sps}/sps.go | 57 +++-- services/{ => tcp}/tcp.go | 42 ++-- services/{ => tunnel}/tunnel_bridge.go | 19 +- services/{ => tunnel}/tunnel_client.go | 19 +- services/{ => tunnel}/tunnel_server.go | 54 +++-- services/{ => udp}/udp.go | 24 ++- 25 files changed, 788 insertions(+), 438 deletions(-) create mode 100644 sdk/android-ios/dns.go delete mode 100644 services/args.go rename services/{ => http}/http.go (89%) rename services/{ => mux}/mux_bridge.go (92%) rename services/{ => mux}/mux_client.go (94%) rename services/{ => mux}/mux_server.go (94%) rename services/{ => socks}/socks.go (94%) rename services/{ => sps}/sps.go (89%) rename services/{ => tcp}/tcp.go (84%) rename services/{ => tunnel}/tunnel_bridge.go (93%) rename services/{ => tunnel}/tunnel_client.go (95%) rename services/{ => tunnel}/tunnel_server.go (95%) rename services/{ => udp}/udp.go (93%) diff --git a/README.md b/README.md index 6035367..15c7540 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,8 @@ Proxy is a high performance HTTP, HTTPS, HTTPS, websocket, TCP, UDP, Socks5 prox - ...   -This page is the v4.9 manual, and the other version of the manual can be checked by the following link. +This page is the v5.0 manual, and the other version of the manual can be checked by the following link. +- [v4.9 manual](https://github.com/snail007/goproxy/tree/v4.9) - [v4.8 manual](https://github.com/snail007/goproxy/tree/v4.8) - [v4.7 manual](https://github.com/snail007/goproxy/tree/v4.7) - [v4.6 manual](https://github.com/snail007/goproxy/tree/v4.6) @@ -163,7 +164,7 @@ If the installation fails or your VPS is not a linux64 system, please follow the Download address: https://github.com/snail007/goproxy/releases ```shell cd /root/proxy/ -wget https://github.com/snail007/goproxy/releases/download/v4.9/proxy-linux-amd64.tar.gz +wget https://github.com/snail007/goproxy/releases/download/v5.0/proxy-linux-amd64.tar.gz ``` #### **2.Download the automatic installation script** ```shell diff --git a/README_ZH.md b/README_ZH.md index ba32e0c..613e08b 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -26,6 +26,7 @@ Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5代理服务 - 协议转换,可以把已经存在的HTTP(S)或SOCKS5代理转换为一个端口同时支持HTTP(S)和SOCKS5代理,转换后的SOCKS5代理不支持UDP功能,同时支持强大的级联认证功能。 - 自定义底层加密传输,http(s)\sps\socks代理在tcp之上可以通过tls标准加密以及kcp协议加密tcp数据,除此之外还支持在tls和kcp之后进行自定义加密,也就是说自定义加密和tls|kcp是可以联合使用的,内部采用AES256加密,使用的时候只需要自己定义一个密码即可。 - 底层压缩高效传输,http(s)\sps\socks代理在tcp之上可以通过自定义加密和tls标准加密以及kcp协议加密tcp数据,在加密之后还可以对数据进行压缩,也就是说压缩功能和自定义加密和tls|kcp是可以联合使用的。 +- 安全的DNS代理,可以通过本地的proxy提供的DNS代理服务器与上级代理加密通讯实现安全防污染的DNS查询。 ### Why need these? - 当由于某某原因,我们不能访问我们在其它地方的服务,我们可以通过多个相连的proxy节点建立起一个安全的隧道访问我们的服务. @@ -37,7 +38,8 @@ Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5代理服务 - ... -本页是v4.9手册,其他版本手册请点击下面链接查看. +本页是v5.0手册,其他版本手册请点击下面链接查看. +- [v4.9手册](https://github.com/snail007/goproxy/tree/v4.9) - [v4.8手册](https://github.com/snail007/goproxy/tree/v4.8) - [v4.7手册](https://github.com/snail007/goproxy/tree/v4.7) - [v4.6手册](https://github.com/snail007/goproxy/tree/v4.6) @@ -145,6 +147,9 @@ Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5代理服务 - [7. KCP配置](#7kcp配置) - [7.1 配置介绍](#71-配置介绍) - [7.2 详细配置](#72-详细配置) +- [8. DNS防污染服务器](#8dns防污染服务器) + - [8.1 介绍](#81-介绍) + - [8.2 使用示例](#82-使用示例) ### Fast Start 提示:所有操作需要root权限. @@ -162,7 +167,7 @@ curl -L https://raw.githubusercontent.com/snail007/goproxy/master/install_auto.s 下载地址:https://github.com/snail007/goproxy/releases ```shell cd /root/proxy/ -wget https://github.com/snail007/goproxy/releases/download/v4.9/proxy-linux-amd64.tar.gz +wget https://github.com/snail007/goproxy/releases/download/v5.0/proxy-linux-amd64.tar.gz ``` #### **2.下载自动安装脚本** ```shell @@ -1041,6 +1046,73 @@ fast :`--nodelay=0 --interval=30 --resend=2 --nc=1` fast2:`--nodelay=1 --interval=20 --resend=2 --nc=1` fast3:`--nodelay=1 --interval=10 --resend=2 --nc=1` +### **8.DNS防污染服务器** + +#### **8.1 介绍** +众所周知DNS是UDP端口53提供的服务,但是随着网络的发展一些知名DNS服务器也支持TCP方式dns查询,比如谷歌的8.8.8.8,proxy的DNS防污染服务器原理就是在本地启动一个proxy的DNS代理服务器,它用TCP的方式通过上级代理进行dns查询。如果它和上级代理通讯采用加密的方式,那么就可以进行安全无污染的DNS解析。 + +#### **8.2 使用示例** + +***8.2.1 普通HTTP(S)上级代理*** +假设有一个上级代理:2.2.2.2:33080 +本地执行: +`proxy dns -S http -T tcp -P 2.2.2.2:33080 -p :53` +那么本地的UDP端口53就提供了DNS解析功能。 + +***8.2.2 普通SOCKS5上级代理*** +假设有一个上级代理:2.2.2.2:33080 +本地执行: +`proxy dns -S socks -T tcp -P 2.2.2.2:33080 -p :53` +那么本地的UDP端口53就提供了DNS解析功能。 + +***8.2.3 TLS加密的HTTP(S)上级代理*** +假设有一个上级代理:2.2.2.2:33080 +上级代理执行的命令是: +`proxy http -t tls -C proxy.crt -K proxy.key -p :33080` +本地执行: +`proxy dns -S http -T tls -P 2.2.2.2:33080 -C proxy.crt -K proxy.key -p :53` +那么本地的UDP端口53就提供了安全防污染DNS解析功能。 + +***8.2.4 TLS加密的SOCKS5上级代理*** +假设有一个上级代理:2.2.2.2:33080 +上级代理执行的命令是: +`proxy socks -t tls -C proxy.crt -K proxy.key -p :33080` +本地执行: +`proxy dns -S socks -T tls -P 2.2.2.2:33080 -C proxy.crt -K proxy.key -p :53` +那么本地的UDP端口53就提供了安全防污染DNS解析功能。 + +***8.2.5 KCP加密的HTTP(S)上级代理*** +假设有一个上级代理:2.2.2.2:33080 +上级代理执行的命令是: +`proxy http -t kcp -p :33080` +本地执行: +`proxy dns -S http -T kcp -P 2.2.2.2:33080 -p :53` +那么本地的UDP端口53就提供了安全防污染DNS解析功能。 + +***8.2.6 KCP加密的SOCKS5上级代理*** +假设有一个上级代理:2.2.2.2:33080 +上级代理执行的命令是: +`proxy socks -t kcp -p :33080` +本地执行: +`proxy dns -S socks -T kcp -P 2.2.2.2:33080 -p :53` +那么本地的UDP端口53就提供了安全防污染DNS解析功能。 + +***8.2.7 自定义加密的HTTP(S)上级代理*** +假设有一个上级代理:2.2.2.2:33080 +上级代理执行的命令是: +`proxy http -t tcp -p :33080 -z password` +本地执行: +`proxy dns -S http -T tcp -Z password -P 2.2.2.2:33080 -p :53` +那么本地的UDP端口53就提供了安全防污染DNS解析功能。 + +***8.2.8 自定义加密的SOCKS5上级代理*** +假设有一个上级代理:2.2.2.2:33080 +上级代理执行的命令是: +`proxy socks -t kcp -p :33080 -z password` +本地执行: +`proxy dns -S socks -T tcp -Z password -P 2.2.2.2:33080 -p :53` +那么本地的UDP端口53就提供了安全防污染DNS解析功能。 + ### TODO - http,socks代理多个上级负载均衡? - http(s)代理增加pac支持? diff --git a/config.go b/config.go index f8e1d1c..d9cd6c8 100755 --- a/config.go +++ b/config.go @@ -7,13 +7,24 @@ import ( logger "log" "os" "os/exec" + "path" + "path/filepath" "runtime/pprof" "time" + sdk "github.com/snail007/goproxy/sdk/android-ios" "github.com/snail007/goproxy/services" "github.com/snail007/goproxy/services/kcpcfg" "github.com/snail007/goproxy/utils" + httpx "github.com/snail007/goproxy/services/http" + mux "github.com/snail007/goproxy/services/mux" + socksx "github.com/snail007/goproxy/services/socks" + spsx "github.com/snail007/goproxy/services/sps" + tcpx "github.com/snail007/goproxy/services/tcp" + tunnel "github.com/snail007/goproxy/services/tunnel" + udpx "github.com/snail007/goproxy/services/udp" + kcp "github.com/xtaci/kcp-go" "golang.org/x/crypto/pbkdf2" kingpin "gopkg.in/alecthomas/kingpin.v2" @@ -37,18 +48,20 @@ func initConfig() (err error) { } //define args - tcpArgs := services.TCPArgs{} - httpArgs := services.HTTPArgs{} - tunnelServerArgs := services.TunnelServerArgs{} - tunnelClientArgs := services.TunnelClientArgs{} - tunnelBridgeArgs := services.TunnelBridgeArgs{} - muxServerArgs := services.MuxServerArgs{} - muxClientArgs := services.MuxClientArgs{} - muxBridgeArgs := services.MuxBridgeArgs{} - udpArgs := services.UDPArgs{} - socksArgs := services.SocksArgs{} - spsArgs := services.SPSArgs{} + tcpArgs := tcpx.TCPArgs{} + httpArgs := httpx.HTTPArgs{} + tunnelServerArgs := tunnel.TunnelServerArgs{} + tunnelClientArgs := tunnel.TunnelClientArgs{} + tunnelBridgeArgs := tunnel.TunnelBridgeArgs{} + muxServerArgs := mux.MuxServerArgs{} + muxClientArgs := mux.MuxClientArgs{} + muxBridgeArgs := mux.MuxBridgeArgs{} + udpArgs := udpx.UDPArgs{} + socksArgs := socksx.SocksArgs{} + spsArgs := spsx.SPSArgs{} + dnsArgs := sdk.DNSArgs{} kcpArgs := kcpcfg.KCPConfigArgs{} + //build srvice args app = kingpin.New("proxy", "happy with proxy") app.Author("snail").Version(APP_VERSION) @@ -248,6 +261,24 @@ func initConfig() (err error) { spsArgs.DisableHTTP = sps.Flag("disable-http", "disable http(s) proxy").Default("false").Bool() spsArgs.DisableSocks5 = sps.Flag("disable-socks", "disable socks proxy").Default("false").Bool() + //########dns######### + dns := app.Command("dns", "proxy on dns server mode") + dnsArgs.Parent = dns.Flag("parent", "parent address, such as: \"23.32.32.19:28008\"").Default("").Short('P').String() + dnsArgs.CertFile = dns.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String() + dnsArgs.KeyFile = dns.Flag("key", "key file for tls").Short('K').Default("proxy.key").String() + dnsArgs.CaCertFile = dns.Flag("ca", "ca cert file for tls").Default("").String() + dnsArgs.Timeout = dns.Flag("timeout", "tcp timeout milliseconds when connect to real server or parent proxy").Short('i').Default("2000").Int() + dnsArgs.ParentType = dns.Flag("parent-type", "parent protocol type ").Short('T').Enum("tls", "tcp", "kcp") + dnsArgs.Local = dns.Flag("local", "local ip:port to listen,multiple address use comma split,such as: 0.0.0.0:80,0.0.0.0:443").Short('p').Default(":53").String() + dnsArgs.ParentServiceType = dns.Flag("parent-service-type", "parent service type ").Short('S').Enum("http", "socks") + dnsArgs.RemoteDNSAddress = dns.Flag("dns-address", "remote dns for resolve doamin").Short('q').Default("8.8.8.8:53").String() + dnsArgs.DNSTTL = dns.Flag("dns-ttl", "caching seconds of dns query result").Short('e').Default("300").Int() + dnsArgs.ParentAuth = dns.Flag("parent-auth", "parent socks auth username and password, such as: -A user1:pass1").Short('A').String() + dnsArgs.ParentKey = dns.Flag("parent-key", "the password for auto encrypt/decrypt parent connection data").Short('Z').Default("").String() + dnsArgs.ParentCompress = dns.Flag("parent-compress", "auto compress/decompress data on parent connection").Short('M').Default("false").Bool() + dnsArgs.CacheFile = dns.Flag("cache-file", "dns result cached file").Short('f').Default(filepath.Join(path.Dir(os.Args[0]), "cache.dat")).String() + dnsArgs.LocalSocks5Port = dns.Flag("socks-port", "local socks5 port").Short('s').Default("65501").String() + //parse args serviceName := kingpin.MustParse(app.Parse(os.Args[1:])) @@ -304,6 +335,7 @@ func initConfig() (err error) { muxBridgeArgs.KCP = kcpArgs muxServerArgs.KCP = kcpArgs muxClientArgs.KCP = kcpArgs + dnsArgs.KCP = kcpArgs log := logger.New(os.Stderr, "", logger.Ldate|logger.Ltime) @@ -409,28 +441,31 @@ func initConfig() (err error) { //regist services and run service switch serviceName { case "http": - services.Regist(serviceName, services.NewHTTP(), httpArgs, log) + services.Regist(serviceName, httpx.NewHTTP(), httpArgs, log) case "tcp": - services.Regist(serviceName, services.NewTCP(), tcpArgs, log) + services.Regist(serviceName, tcpx.NewTCP(), tcpArgs, log) case "udp": - services.Regist(serviceName, services.NewUDP(), udpArgs, log) + services.Regist(serviceName, udpx.NewUDP(), udpArgs, log) case "tserver": - services.Regist(serviceName, services.NewTunnelServerManager(), tunnelServerArgs, log) + services.Regist(serviceName, tunnel.NewTunnelServerManager(), tunnelServerArgs, log) case "tclient": - services.Regist(serviceName, services.NewTunnelClient(), tunnelClientArgs, log) + services.Regist(serviceName, tunnel.NewTunnelClient(), tunnelClientArgs, log) case "tbridge": - services.Regist(serviceName, services.NewTunnelBridge(), tunnelBridgeArgs, log) + services.Regist(serviceName, tunnel.NewTunnelBridge(), tunnelBridgeArgs, log) case "server": - services.Regist(serviceName, services.NewMuxServerManager(), muxServerArgs, log) + services.Regist(serviceName, mux.NewMuxServerManager(), muxServerArgs, log) case "client": - services.Regist(serviceName, services.NewMuxClient(), muxClientArgs, log) + services.Regist(serviceName, mux.NewMuxClient(), muxClientArgs, log) case "bridge": - services.Regist(serviceName, services.NewMuxBridge(), muxBridgeArgs, log) + services.Regist(serviceName, mux.NewMuxBridge(), muxBridgeArgs, log) case "socks": - services.Regist(serviceName, services.NewSocks(), socksArgs, log) + services.Regist(serviceName, socksx.NewSocks(), socksArgs, log) case "sps": - services.Regist(serviceName, services.NewSPS(), spsArgs, log) + services.Regist(serviceName, spsx.NewSPS(), spsArgs, log) + case "dns": + services.Regist(serviceName, sdk.NewDNS(), dnsArgs, log) } + service, err = services.Run(serviceName, nil) if err != nil { log.Fatalf("run service [%s] fail, ERR:%s", serviceName, err) diff --git a/install_auto.sh b/install_auto.sh index 4eb34a2..64376d9 100755 --- a/install_auto.sh +++ b/install_auto.sh @@ -5,7 +5,7 @@ if [ -e /tmp/proxy ]; then fi mkdir /tmp/proxy cd /tmp/proxy -wget https://github.com/snail007/goproxy/releases/download/v4.9/proxy-linux-amd64.tar.gz +wget https://github.com/snail007/goproxy/releases/download/v5.0/proxy-linux-amd64.tar.gz # #install proxy tar zxvf proxy-linux-amd64.tar.gz diff --git a/main.go b/main.go index 6bf8f13..befdb93 100644 --- a/main.go +++ b/main.go @@ -9,7 +9,7 @@ import ( "github.com/snail007/goproxy/services" ) -const APP_VERSION = "4.9" +const APP_VERSION = "5.0" func main() { err := initConfig() diff --git a/release.sh b/release.sh index 9747785..dc969c8 100755 --- a/release.sh +++ b/release.sh @@ -1,5 +1,5 @@ #!/bin/bash -VER="4.9" +VER="5.0" RELEASE="release-${VER}" rm -rf .cert mkdir .cert diff --git a/sdk/android-ios/dns.go b/sdk/android-ios/dns.go new file mode 100644 index 0000000..bb2dc4a --- /dev/null +++ b/sdk/android-ios/dns.go @@ -0,0 +1,256 @@ +package proxy + +import ( + "crypto/md5" + "encoding/hex" + "fmt" + logger "log" + "net" + "runtime/debug" + "time" + + "golang.org/x/net/proxy" + + "github.com/miekg/dns" + gocache "github.com/pmylund/go-cache" + services "github.com/snail007/goproxy/services" + "github.com/snail007/goproxy/services/kcpcfg" +) + +type DNSArgs struct { + ParentServiceType *string + ParentType *string + Parent *string + ParentAuth *string + ParentKey *string + ParentCompress *bool + KCP kcpcfg.KCPConfigArgs + CertFile *string + KeyFile *string + CaCertFile *string + Local *string + Timeout *int + RemoteDNSAddress *string + DNSTTL *int + CacheFile *string + LocalSocks5Port *string +} +type DNS struct { + cfg DNSArgs + log *logger.Logger + cache *gocache.Cache + exitSig chan bool + serviceKey string + dialer proxy.Dialer +} + +func NewDNS() services.Service { + return &DNS{ + cfg: DNSArgs{}, + exitSig: make(chan bool, 1), + serviceKey: "dns-service-" + fmt.Sprintf("%d", time.Now().UnixNano()), + } +} +func (s *DNS) CheckArgs() (err error) { + return +} +func (s *DNS) InitService() (err error) { + s.cache = gocache.New(time.Second*time.Duration(*s.cfg.DNSTTL), time.Second*60) + s.cache.LoadFile(*s.cfg.CacheFile) + go func() { + for { + select { + case <-s.exitSig: + return + case <-time.After(time.Second * 60): + err := s.cache.SaveFile(*s.cfg.CacheFile) + if err == nil { + //s.log.Printf("cache saved: %s", *s.cfg.CacheFile) + } else { + s.log.Printf("cache save failed: %s, %s", *s.cfg.CacheFile, err) + } + } + } + }() + s.dialer, err = proxy.SOCKS5("tcp", *s.cfg.Parent, + nil, + &net.Dialer{ + Timeout: 5 * time.Second, + KeepAlive: 5 * time.Second, + }, + ) + if err != nil { + return + } + + sdkArgs := fmt.Sprintf("sps -S %s -T %s -P %s -C %s -K %s -i %d -p 127.0.0.1:%s --disable-http", + *s.cfg.ParentServiceType, + *s.cfg.ParentType, + *s.cfg.Parent, + *s.cfg.CertFile, + *s.cfg.KeyFile, + *s.cfg.Timeout, + *s.cfg.LocalSocks5Port, + ) + if *s.cfg.ParentKey != "" { + sdkArgs += " -Z " + *s.cfg.ParentKey + } + if *s.cfg.ParentAuth != "" { + sdkArgs += " -A " + *s.cfg.ParentAuth + } + if *s.cfg.CaCertFile != "" { + sdkArgs += " --ca " + *s.cfg.CaCertFile + } + if *s.cfg.ParentCompress { + sdkArgs += " -M" + } + s.log.Printf("start sps with : %s", sdkArgs) + errStr := Start(s.serviceKey, sdkArgs) + if errStr != "" { + err = fmt.Errorf("start sps service fail,%s", errStr) + } + return +} +func (s *DNS) StopService() { + defer func() { + e := recover() + if e != nil { + s.log.Printf("stop dns service crashed,%s", e) + } else { + s.log.Printf("service dns stoped") + } + }() + Stop(s.serviceKey) + s.cache.Flush() + s.exitSig <- true +} +func (s *DNS) Start(args interface{}, log *logger.Logger) (err error) { + s.log = log + s.cfg = args.(DNSArgs) + if err = s.CheckArgs(); err != nil { + return + } + if err = s.InitService(); err != nil { + return + } + dns.HandleFunc(".", s.callback) + go func() { + log.Printf("dns server on udp %s", *s.cfg.Local) + err := dns.ListenAndServe(*s.cfg.Local, "udp", nil) + if err != nil { + log.Printf("dns listen error: %s", err) + } + }() + return +} + +func (s *DNS) Clean() { + s.StopService() +} +func (s *DNS) callback(w dns.ResponseWriter, req *dns.Msg) { + defer func() { + if err := recover(); err != nil { + s.log.Printf("dns handler crashed with err : %s \nstack: %s", err, string(debug.Stack())) + } + }() + var ( + key string + m *dns.Msg + err error + data []byte + id uint16 + query []string + questions []dns.Question + ) + if req.MsgHdr.Response == true { + return + } + query = make([]string, len(req.Question)) + for i, q := range req.Question { + if q.Qtype != dns.TypeAAAA { + questions = append(questions, q) + } + query[i] = fmt.Sprintf("(%s %s %s)", q.Name, dns.ClassToString[q.Qclass], dns.TypeToString[q.Qtype]) + } + + if len(questions) == 0 { + return + } + + req.Question = questions + id = req.Id + req.Id = 0 + key = s.toMd5(req.String()) + req.Id = id + if reply, ok := s.cache.Get(key); ok { + data, _ = reply.([]byte) + } + if data != nil && len(data) > 0 { + m = &dns.Msg{} + m.Unpack(data) + m.Id = id + err = w.WriteMsg(m) + s.log.Printf("id: %5d cache: HIT %v", id, query) + return + + } else { + s.log.Printf("id: %5d cache: MISS %v", id, query) + } + + s.log.Printf("id: %5d resolve: %v %s", id, query, *s.cfg.RemoteDNSAddress) + + rawConn, err := s.dialer.Dial("tcp", *s.cfg.RemoteDNSAddress) + if err != nil { + s.log.Printf("dail to %s fail,%s", *s.cfg.RemoteDNSAddress, err) + return + } + defer rawConn.Close() + co := new(dns.Conn) + co.Conn = rawConn + defer co.Close() + if err = co.WriteMsg(req); err != nil { + s.log.Printf("write dns query fail,%s", err) + return + } + m, err = co.ReadMsg() + if err == nil && m.Id != req.Id { + s.log.Printf("id: %5d mismath", id) + return + } + if err != nil || len(m.Answer) == 0 { + s.log.Printf("dns query fail,%s", err) + return + } + data, err = m.Pack() + if err != nil { + s.log.Printf("dns query fail,%s", err) + return + } + + _, err = w.Write(data) + if err != nil { + s.log.Printf("dns query fail,%s", err) + return + } + m.Id = 0 + data, _ = m.Pack() + ttl := 0 + if len(m.Answer) > 0 { + if *s.cfg.DNSTTL > 0 { + ttl = *s.cfg.DNSTTL + } else { + ttl = int(m.Answer[0].Header().Ttl) + if ttl < 0 { + ttl = *s.cfg.DNSTTL + } + } + } + s.cache.Set(key, data, time.Second*time.Duration(ttl)) + m.Id = id + s.log.Printf("id: %5d cache: CACHED %v TTL %v", id, query, ttl) +} +func (s *DNS) toMd5(data string) string { + m := md5.New() + m.Write([]byte(data)) + return hex.EncodeToString(m.Sum(nil)) +} diff --git a/sdk/android-ios/release_android.sh b/sdk/android-ios/release_android.sh index d2af849..d591df8 100755 --- a/sdk/android-ios/release_android.sh +++ b/sdk/android-ios/release_android.sh @@ -1,5 +1,5 @@ #/bin/bash -VER="v4.9" +VER="v5.0" rm -rf sdk-android-*.tar.gz rm -rf android mkdir android diff --git a/sdk/android-ios/release_ios.sh b/sdk/android-ios/release_ios.sh index 23062f3..d7b6e00 100755 --- a/sdk/android-ios/release_ios.sh +++ b/sdk/android-ios/release_ios.sh @@ -1,5 +1,5 @@ #/bin/bash -VER="v4.9" +VER="v5.0" rm -rf sdk-ios-*.tar.gz rm -rf ios mkdir ios diff --git a/sdk/android-ios/sdk.go b/sdk/android-ios/sdk.go index 9d0446d..b42607c 100644 --- a/sdk/android-ios/sdk.go +++ b/sdk/android-ios/sdk.go @@ -5,17 +5,25 @@ import ( "fmt" logger "log" "os" + "path" + "path/filepath" "strings" "github.com/snail007/goproxy/services" + httpx "github.com/snail007/goproxy/services/http" "github.com/snail007/goproxy/services/kcpcfg" - + mux "github.com/snail007/goproxy/services/mux" + socksx "github.com/snail007/goproxy/services/socks" + spsx "github.com/snail007/goproxy/services/sps" + tcpx "github.com/snail007/goproxy/services/tcp" + tunnel "github.com/snail007/goproxy/services/tunnel" + udpx "github.com/snail007/goproxy/services/udp" kcp "github.com/xtaci/kcp-go" "golang.org/x/crypto/pbkdf2" kingpin "gopkg.in/alecthomas/kingpin.v2" ) -const SDK_VERSION = "4.9" +const SDK_VERSION = "5.0" var ( app *kingpin.Application @@ -32,17 +40,18 @@ var ( //if start success, errStr is empty. func Start(serviceID, serviceArgsStr string) (errStr string) { //define args - tcpArgs := services.TCPArgs{} - httpArgs := services.HTTPArgs{} - tunnelServerArgs := services.TunnelServerArgs{} - tunnelClientArgs := services.TunnelClientArgs{} - tunnelBridgeArgs := services.TunnelBridgeArgs{} - muxServerArgs := services.MuxServerArgs{} - muxClientArgs := services.MuxClientArgs{} - muxBridgeArgs := services.MuxBridgeArgs{} - udpArgs := services.UDPArgs{} - socksArgs := services.SocksArgs{} - spsArgs := services.SPSArgs{} + tcpArgs := tcpx.TCPArgs{} + httpArgs := httpx.HTTPArgs{} + tunnelServerArgs := tunnel.TunnelServerArgs{} + tunnelClientArgs := tunnel.TunnelClientArgs{} + tunnelBridgeArgs := tunnel.TunnelBridgeArgs{} + muxServerArgs := mux.MuxServerArgs{} + muxClientArgs := mux.MuxClientArgs{} + muxBridgeArgs := mux.MuxBridgeArgs{} + udpArgs := udpx.UDPArgs{} + socksArgs := socksx.SocksArgs{} + spsArgs := spsx.SPSArgs{} + dnsArgs := DNSArgs{} kcpArgs := kcpcfg.KCPConfigArgs{} //build srvice args app = kingpin.New("proxy", "happy with proxy") @@ -240,6 +249,23 @@ func Start(serviceID, serviceArgsStr string) (errStr string) { spsArgs.ParentCompress = sps.Flag("parent-compress", "auto compress/decompress data on parent connection").Short('M').Default("false").Bool() spsArgs.DisableHTTP = sps.Flag("disable-http", "disable http(s) proxy").Default("false").Bool() spsArgs.DisableSocks5 = sps.Flag("disable-socks", "disable socks proxy").Default("false").Bool() + //########dns######### + dns := app.Command("dns", "proxy on dns server mode") + dnsArgs.Parent = dns.Flag("parent", "parent address, such as: \"23.32.32.19:28008\"").Default("").Short('P').String() + dnsArgs.CertFile = dns.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String() + dnsArgs.KeyFile = dns.Flag("key", "key file for tls").Short('K').Default("proxy.key").String() + dnsArgs.CaCertFile = dns.Flag("ca", "ca cert file for tls").Default("").String() + dnsArgs.Timeout = dns.Flag("timeout", "tcp timeout milliseconds when connect to real server or parent proxy").Short('i').Default("2000").Int() + dnsArgs.ParentType = dns.Flag("parent-type", "parent protocol type ").Short('T').Enum("tls", "tcp", "kcp") + dnsArgs.Local = dns.Flag("local", "local ip:port to listen,multiple address use comma split,such as: 0.0.0.0:80,0.0.0.0:443").Short('p').Default(":33080").String() + dnsArgs.ParentServiceType = dns.Flag("parent-service-type", "parent service type ").Short('S').Enum("http", "socks") + dnsArgs.RemoteDNSAddress = dns.Flag("dns-address", "remote dns for resolve doamin").Short('q').Default("8.8.8.8:53").String() + dnsArgs.DNSTTL = dns.Flag("dns-ttl", "caching seconds of dns query result").Short('e').Default("300").Int() + dnsArgs.ParentAuth = dns.Flag("parent-auth", "parent socks auth username and password, such as: -A user1:pass1").Short('A').String() + dnsArgs.ParentKey = dns.Flag("parent-key", "the password for auto encrypt/decrypt parent connection data").Short('Z').Default("").String() + dnsArgs.ParentCompress = dns.Flag("parent-compress", "auto compress/decompress data on parent connection").Short('M').Default("false").Bool() + dnsArgs.CacheFile = dns.Flag("cache-file", "dns result cached file").Short('f').Default(filepath.Join(path.Dir(os.Args[0]), "cache.dat")).String() + dnsArgs.LocalSocks5Port = dns.Flag("socks-port", "local socks5 port").Short('s').Default("65501").String() //parse args _args := strings.Fields(strings.Trim(serviceArgsStr, " ")) @@ -302,6 +328,7 @@ func Start(serviceID, serviceArgsStr string) (errStr string) { muxBridgeArgs.KCP = kcpArgs muxServerArgs.KCP = kcpArgs muxClientArgs.KCP = kcpArgs + dnsArgs.KCP = kcpArgs log := logger.New(os.Stderr, "", logger.Ldate|logger.Ltime) flags := logger.Ldate @@ -323,27 +350,29 @@ func Start(serviceID, serviceArgsStr string) (errStr string) { //regist services and run service switch serviceName { case "http": - services.Regist(serviceID, services.NewHTTP(), httpArgs, log) + services.Regist(serviceID, httpx.NewHTTP(), httpArgs, log) case "tcp": - services.Regist(serviceID, services.NewTCP(), tcpArgs, log) + services.Regist(serviceID, tcpx.NewTCP(), tcpArgs, log) case "udp": - services.Regist(serviceID, services.NewUDP(), udpArgs, log) + services.Regist(serviceID, udpx.NewUDP(), udpArgs, log) case "tserver": - services.Regist(serviceID, services.NewTunnelServerManager(), tunnelServerArgs, log) + services.Regist(serviceID, tunnel.NewTunnelServerManager(), tunnelServerArgs, log) case "tclient": - services.Regist(serviceID, services.NewTunnelClient(), tunnelClientArgs, log) + services.Regist(serviceID, tunnel.NewTunnelClient(), tunnelClientArgs, log) case "tbridge": - services.Regist(serviceID, services.NewTunnelBridge(), tunnelBridgeArgs, log) + services.Regist(serviceID, tunnel.NewTunnelBridge(), tunnelBridgeArgs, log) case "server": - services.Regist(serviceID, services.NewMuxServerManager(), muxServerArgs, log) + services.Regist(serviceID, mux.NewMuxServerManager(), muxServerArgs, log) case "client": - services.Regist(serviceID, services.NewMuxClient(), muxClientArgs, log) + services.Regist(serviceID, mux.NewMuxClient(), muxClientArgs, log) case "bridge": - services.Regist(serviceID, services.NewMuxBridge(), muxBridgeArgs, log) + services.Regist(serviceID, mux.NewMuxBridge(), muxBridgeArgs, log) case "socks": - services.Regist(serviceID, services.NewSocks(), socksArgs, log) + services.Regist(serviceID, socksx.NewSocks(), socksArgs, log) case "sps": - services.Regist(serviceID, services.NewSPS(), spsArgs, log) + services.Regist(serviceID, spsx.NewSPS(), spsArgs, log) + case "dns": + services.Regist(serviceName, NewDNS(), dnsArgs, log) } _, err = services.Run(serviceID, nil) if err != nil { diff --git a/sdk/windows-linux/release_linux.sh b/sdk/windows-linux/release_linux.sh index 0ca404f..de15e3d 100755 --- a/sdk/windows-linux/release_linux.sh +++ b/sdk/windows-linux/release_linux.sh @@ -1,5 +1,5 @@ #/bin/bash -VER="v4.9" +VER="v5.0" rm -rf sdk-linux-*.tar.gz rm -rf README.md libproxy-sdk.so libproxy-sdk.h libproxy-sdk.a diff --git a/sdk/windows-linux/release_mac.sh b/sdk/windows-linux/release_mac.sh index af3f974..afa9a02 100755 --- a/sdk/windows-linux/release_mac.sh +++ b/sdk/windows-linux/release_mac.sh @@ -1,5 +1,5 @@ #/bin/bash -VER="v4.9" +VER="v5.0" rm -rf *.tar.gz rm -rf README.md libproxy-sdk.dylib libproxy-sdk.h diff --git a/sdk/windows-linux/release_windows.sh b/sdk/windows-linux/release_windows.sh index 64ab452..7a3b06d 100755 --- a/sdk/windows-linux/release_windows.sh +++ b/sdk/windows-linux/release_windows.sh @@ -1,5 +1,5 @@ #/bin/bash -VER="v4.9" +VER="v5.0" sudo rm /usr/local/go sudo ln -s /usr/local/go1.10.1 /usr/local/go diff --git a/services/args.go b/services/args.go deleted file mode 100644 index b7593dd..0000000 --- a/services/args.go +++ /dev/null @@ -1,285 +0,0 @@ -package services - -import ( - "github.com/snail007/goproxy/services/kcpcfg" - - "golang.org/x/crypto/ssh" -) - -// tcp := app.Command("tcp", "proxy on tcp mode") -// t := tcp.Flag("tcp-timeout", "tcp timeout milliseconds when connect to real server or parent proxy").Default("2000").Int() - -const ( - TYPE_TCP = "tcp" - TYPE_UDP = "udp" - TYPE_HTTP = "http" - TYPE_TLS = "tls" - TYPE_KCP = "kcp" - CONN_CLIENT_CONTROL = uint8(1) - CONN_CLIENT_HEARBEAT = uint8(2) - CONN_SERVER_HEARBEAT = uint8(3) - CONN_SERVER = uint8(4) - CONN_CLIENT = uint8(5) - CONN_SERVER_MUX = uint8(6) - CONN_CLIENT_MUX = uint8(7) -) - -type MuxServerArgs struct { - Parent *string - ParentType *string - CertFile *string - KeyFile *string - CertBytes []byte - KeyBytes []byte - Local *string - IsUDP *bool - Key *string - Remote *string - Timeout *int - Route *[]string - Mgr *MuxServerManager - IsCompress *bool - SessionCount *int - KCP kcpcfg.KCPConfigArgs -} -type MuxClientArgs struct { - Parent *string - ParentType *string - CertFile *string - KeyFile *string - CertBytes []byte - KeyBytes []byte - Key *string - Timeout *int - IsCompress *bool - SessionCount *int - KCP kcpcfg.KCPConfigArgs -} -type MuxBridgeArgs struct { - CertFile *string - KeyFile *string - CertBytes []byte - KeyBytes []byte - Local *string - LocalType *string - Timeout *int - IsCompress *bool - KCP kcpcfg.KCPConfigArgs -} -type TunnelServerArgs struct { - Parent *string - CertFile *string - KeyFile *string - CertBytes []byte - KeyBytes []byte - Local *string - IsUDP *bool - Key *string - Remote *string - Timeout *int - Route *[]string - Mgr *TunnelServerManager - Mux *bool -} -type TunnelClientArgs struct { - Parent *string - CertFile *string - KeyFile *string - CertBytes []byte - KeyBytes []byte - Key *string - Timeout *int - Mux *bool -} -type TunnelBridgeArgs struct { - Parent *string - CertFile *string - KeyFile *string - CertBytes []byte - KeyBytes []byte - Local *string - Timeout *int - Mux *bool -} -type TCPArgs struct { - Parent *string - CertFile *string - KeyFile *string - CertBytes []byte - KeyBytes []byte - Local *string - ParentType *string - LocalType *string - Timeout *int - CheckParentInterval *int - KCP kcpcfg.KCPConfigArgs -} - -type HTTPArgs struct { - Parent *string - CertFile *string - KeyFile *string - CaCertFile *string - CaCertBytes []byte - CertBytes []byte - KeyBytes []byte - Local *string - Always *bool - HTTPTimeout *int - Interval *int - Blocked *string - Direct *string - AuthFile *string - Auth *[]string - AuthURL *string - AuthURLOkCode *int - AuthURLTimeout *int - AuthURLRetry *int - ParentType *string - LocalType *string - Timeout *int - CheckParentInterval *int - SSHKeyFile *string - SSHKeyFileSalt *string - SSHPassword *string - SSHUser *string - SSHKeyBytes []byte - SSHAuthMethod ssh.AuthMethod - KCP kcpcfg.KCPConfigArgs - LocalIPS *[]string - DNSAddress *string - DNSTTL *int - LocalKey *string - ParentKey *string - LocalCompress *bool - ParentCompress *bool -} -type UDPArgs struct { - Parent *string - CertFile *string - KeyFile *string - CertBytes []byte - KeyBytes []byte - Local *string - ParentType *string - Timeout *int - CheckParentInterval *int -} -type SocksArgs struct { - Parent *string - ParentType *string - Local *string - LocalType *string - CertFile *string - KeyFile *string - CaCertFile *string - CaCertBytes []byte - CertBytes []byte - KeyBytes []byte - SSHKeyFile *string - SSHKeyFileSalt *string - SSHPassword *string - SSHUser *string - SSHKeyBytes []byte - SSHAuthMethod ssh.AuthMethod - Timeout *int - Always *bool - Interval *int - Blocked *string - Direct *string - AuthFile *string - Auth *[]string - AuthURL *string - AuthURLOkCode *int - AuthURLTimeout *int - AuthURLRetry *int - KCP kcpcfg.KCPConfigArgs - UDPParent *string - UDPLocal *string - LocalIPS *[]string - DNSAddress *string - DNSTTL *int - LocalKey *string - ParentKey *string - LocalCompress *bool - ParentCompress *bool -} -type SPSArgs struct { - Parent *string - CertFile *string - KeyFile *string - CaCertFile *string - CaCertBytes []byte - CertBytes []byte - KeyBytes []byte - Local *string - ParentType *string - LocalType *string - Timeout *int - KCP kcpcfg.KCPConfigArgs - ParentServiceType *string - DNSAddress *string - DNSTTL *int - AuthFile *string - Auth *[]string - AuthURL *string - AuthURLOkCode *int - AuthURLTimeout *int - AuthURLRetry *int - LocalIPS *[]string - ParentAuth *string - LocalKey *string - ParentKey *string - LocalCompress *bool - ParentCompress *bool - DisableHTTP *bool - DisableSocks5 *bool -} -type DNSArgs struct { - Parent *string - CertFile *string - KeyFile *string - CaCertFile *string - CaCertBytes []byte - CertBytes []byte - KeyBytes []byte - Local *string - ParentType *string - LocalType *string - Timeout *int - KCP kcpcfg.KCPConfigArgs - ParentServiceType *string - DNSAddress *string - DNSTTL *int - AuthFile *string - Auth *[]string - AuthURL *string - AuthURLOkCode *int - AuthURLTimeout *int - AuthURLRetry *int - LocalIPS *[]string - ParentAuth *string - LocalKey *string - ParentKey *string - LocalCompress *bool - ParentCompress *bool - DisableHTTP *bool - DisableSocks5 *bool -} -func (a *SPSArgs) Protocol() string { - return ProtocoStrl(*a.LocalType) -} -func (a *TCPArgs) Protocol() string { - return ProtocoStrl(*a.LocalType) -} -func ProtocoStrl(t string) string { - switch t { - case TYPE_TLS: - return TYPE_TLS - case TYPE_TCP: - return TYPE_TCP - case TYPE_KCP: - return TYPE_KCP - } - return "unknown" -} \ No newline at end of file diff --git a/services/http.go b/services/http/http.go similarity index 89% rename from services/http.go rename to services/http/http.go index b8dccbd..f8bef2e 100644 --- a/services/http.go +++ b/services/http/http.go @@ -11,12 +11,53 @@ import ( "strings" "time" + "github.com/snail007/goproxy/services" + "github.com/snail007/goproxy/services/kcpcfg" "github.com/snail007/goproxy/utils" "github.com/snail007/goproxy/utils/conncrypt" "golang.org/x/crypto/ssh" ) +type HTTPArgs struct { + Parent *string + CertFile *string + KeyFile *string + CaCertFile *string + CaCertBytes []byte + CertBytes []byte + KeyBytes []byte + Local *string + Always *bool + HTTPTimeout *int + Interval *int + Blocked *string + Direct *string + AuthFile *string + Auth *[]string + AuthURL *string + AuthURLOkCode *int + AuthURLTimeout *int + AuthURLRetry *int + ParentType *string + LocalType *string + Timeout *int + CheckParentInterval *int + SSHKeyFile *string + SSHKeyFileSalt *string + SSHPassword *string + SSHUser *string + SSHKeyBytes []byte + SSHAuthMethod ssh.AuthMethod + KCP kcpcfg.KCPConfigArgs + LocalIPS *[]string + DNSAddress *string + DNSTTL *int + LocalKey *string + ParentKey *string + LocalCompress *bool + ParentCompress *bool +} type HTTP struct { outPool utils.OutConn cfg HTTPArgs @@ -31,7 +72,7 @@ type HTTP struct { log *logger.Logger } -func NewHTTP() Service { +func NewHTTP() services.Service { return &HTTP{ outPool: utils.OutConn{}, cfg: HTTPArgs{}, @@ -182,11 +223,11 @@ func (s *HTTP) Start(args interface{}, log *logger.Logger) (err error) { host, port, _ := net.SplitHostPort(addr) p, _ := strconv.Atoi(port) sc := utils.NewServerChannel(host, p, s.log) - if *s.cfg.LocalType == TYPE_TCP { + if *s.cfg.LocalType == "tcp" { err = sc.ListenTCP(s.callback) - } else if *s.cfg.LocalType == TYPE_TLS { + } else if *s.cfg.LocalType == "tls" { err = sc.ListenTls(s.cfg.CertBytes, s.cfg.KeyBytes, s.cfg.CaCertBytes, s.callback) - } else if *s.cfg.LocalType == TYPE_KCP { + } else if *s.cfg.LocalType == "kcp" { err = sc.ListenKCP(s.cfg.KCP, s.callback, s.log) } if err != nil { @@ -396,7 +437,7 @@ func (s *HTTP) ConnectSSH() (err error) { return } func (s *HTTP) InitOutConnPool() { - if *s.cfg.ParentType == TYPE_TLS || *s.cfg.ParentType == TYPE_TCP || *s.cfg.ParentType == TYPE_KCP { + if *s.cfg.ParentType == "tls" || *s.cfg.ParentType == "tcp" || *s.cfg.ParentType == "kcp" { //dur int, isTLS bool, certBytes, keyBytes []byte, //parent string, timeout int, InitialCap int, MaxCap int s.outPool = utils.NewOutConn( diff --git a/services/mux_bridge.go b/services/mux/mux_bridge.go similarity index 92% rename from services/mux_bridge.go rename to services/mux/mux_bridge.go index 09a8fd6..e80b7c5 100644 --- a/services/mux_bridge.go +++ b/services/mux/mux_bridge.go @@ -1,4 +1,4 @@ -package services +package mux import ( "bufio" @@ -12,12 +12,29 @@ import ( "sync" "time" + "github.com/snail007/goproxy/services" + "github.com/snail007/goproxy/services/kcpcfg" "github.com/snail007/goproxy/utils" - //"github.com/xtaci/smux" smux "github.com/hashicorp/yamux" ) +const ( + CONN_SERVER = uint8(4) + CONN_CLIENT = uint8(5) +) + +type MuxBridgeArgs struct { + CertFile *string + KeyFile *string + CertBytes []byte + KeyBytes []byte + Local *string + LocalType *string + Timeout *int + IsCompress *bool + KCP kcpcfg.KCPConfigArgs +} type MuxBridge struct { cfg MuxBridgeArgs clientControlConns utils.ConcurrentMap @@ -29,7 +46,7 @@ type MuxBridge struct { log *logger.Logger } -func NewMuxBridge() Service { +func NewMuxBridge() services.Service { b := &MuxBridge{ cfg: MuxBridgeArgs{}, clientControlConns: utils.NewConcurrentMap(), @@ -49,7 +66,7 @@ func (s *MuxBridge) CheckArgs() (err error) { err = fmt.Errorf("cert and key file required") return } - if *s.cfg.LocalType == TYPE_TLS { + if *s.cfg.LocalType == "tls" { s.cfg.CertBytes, s.cfg.KeyBytes, err = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile) if err != nil { return @@ -69,7 +86,7 @@ func (s *MuxBridge) StopService() { s.isStop = true if s.sc != nil && (*s.sc).Listener != nil { (*(*s.sc).Listener).Close() - } + } for _, g := range s.clientControlConns.Items() { for _, session := range g.(utils.ConcurrentMap).Items() { (session.(*smux.Session)).Close() @@ -92,11 +109,11 @@ func (s *MuxBridge) Start(args interface{}, log *logger.Logger) (err error) { host, port, _ := net.SplitHostPort(*s.cfg.Local) p, _ := strconv.Atoi(port) sc := utils.NewServerChannel(host, p, s.log) - if *s.cfg.LocalType == TYPE_TCP { + if *s.cfg.LocalType == "tcp" { err = sc.ListenTCP(s.handler) - } else if *s.cfg.LocalType == TYPE_TLS { + } else if *s.cfg.LocalType == "tls" { err = sc.ListenTls(s.cfg.CertBytes, s.cfg.KeyBytes, nil, s.handler) - } else if *s.cfg.LocalType == TYPE_KCP { + } else if *s.cfg.LocalType == "kcp" { err = sc.ListenKCP(s.cfg.KCP, s.handler, s.log) } if err != nil { diff --git a/services/mux_client.go b/services/mux/mux_client.go similarity index 94% rename from services/mux_client.go rename to services/mux/mux_client.go index 6148c64..b5c263a 100644 --- a/services/mux_client.go +++ b/services/mux/mux_client.go @@ -1,4 +1,4 @@ -package services +package mux import ( "crypto/tls" @@ -8,13 +8,27 @@ import ( "net" "time" - "github.com/snail007/goproxy/utils" - "github.com/golang/snappy" + "github.com/snail007/goproxy/services" + "github.com/snail007/goproxy/services/kcpcfg" + "github.com/snail007/goproxy/utils" //"github.com/xtaci/smux" smux "github.com/hashicorp/yamux" ) +type MuxClientArgs struct { + Parent *string + ParentType *string + CertFile *string + KeyFile *string + CertBytes []byte + KeyBytes []byte + Key *string + Timeout *int + IsCompress *bool + SessionCount *int + KCP kcpcfg.KCPConfigArgs +} type MuxClient struct { cfg MuxClientArgs isStop bool @@ -22,7 +36,7 @@ type MuxClient struct { log *logger.Logger } -func NewMuxClient() Service { +func NewMuxClient() services.Service { return &MuxClient{ cfg: MuxClientArgs{}, isStop: false, diff --git a/services/mux_server.go b/services/mux/mux_server.go similarity index 94% rename from services/mux_server.go rename to services/mux/mux_server.go index c3e5acf..5f34715 100644 --- a/services/mux_server.go +++ b/services/mux/mux_server.go @@ -1,4 +1,4 @@ -package services +package mux import ( "crypto/tls" @@ -12,6 +12,8 @@ import ( "strings" "time" + "github.com/snail007/goproxy/services" + "github.com/snail007/goproxy/services/kcpcfg" "github.com/snail007/goproxy/utils" "github.com/golang/snappy" @@ -19,31 +21,45 @@ import ( smux "github.com/hashicorp/yamux" ) -type MuxServer struct { - cfg MuxServerArgs - udpChn chan MuxUDPItem - sc utils.ServerChannel - sessions utils.ConcurrentMap - lockChn chan bool - isStop bool - udpConn *net.Conn - log *logger.Logger +type MuxServerArgs struct { + Parent *string + ParentType *string + CertFile *string + KeyFile *string + CertBytes []byte + KeyBytes []byte + Local *string + IsUDP *bool + Key *string + Remote *string + Timeout *int + Route *[]string + Mgr *MuxServerManager + IsCompress *bool + SessionCount *int + KCP kcpcfg.KCPConfigArgs +} + +type MuxUDPItem struct { + packet *[]byte + localAddr *net.UDPAddr + srcAddr *net.UDPAddr } type MuxServerManager struct { cfg MuxServerArgs udpChn chan MuxUDPItem serverID string - servers []*Service + servers []*services.Service log *logger.Logger } -func NewMuxServerManager() Service { +func NewMuxServerManager() services.Service { return &MuxServerManager{ cfg: MuxServerArgs{}, udpChn: make(chan MuxUDPItem, 50000), serverID: utils.Uniqueid(), - servers: []*Service{}, + servers: []*services.Service{}, } } @@ -139,7 +155,18 @@ func (s *MuxServerManager) InitService() (err error) { return } -func NewMuxServer() Service { +type MuxServer struct { + cfg MuxServerArgs + udpChn chan MuxUDPItem + sc utils.ServerChannel + sessions utils.ConcurrentMap + lockChn chan bool + isStop bool + udpConn *net.Conn + log *logger.Logger +} + +func NewMuxServer() services.Service { return &MuxServer{ cfg: MuxServerArgs{}, udpChn: make(chan MuxUDPItem, 50000), @@ -149,12 +176,6 @@ func NewMuxServer() Service { } } -type MuxUDPItem struct { - packet *[]byte - localAddr *net.UDPAddr - srcAddr *net.UDPAddr -} - func (s *MuxServer) StopService() { defer func() { e := recover() diff --git a/services/socks.go b/services/socks/socks.go similarity index 94% rename from services/socks.go rename to services/socks/socks.go index b26627e..8e45c78 100644 --- a/services/socks.go +++ b/services/socks/socks.go @@ -10,14 +10,54 @@ import ( "strings" "time" + "github.com/snail007/goproxy/services" + "github.com/snail007/goproxy/services/kcpcfg" "github.com/snail007/goproxy/utils" "github.com/snail007/goproxy/utils/aes" "github.com/snail007/goproxy/utils/conncrypt" "github.com/snail007/goproxy/utils/socks" - "golang.org/x/crypto/ssh" ) +type SocksArgs struct { + Parent *string + ParentType *string + Local *string + LocalType *string + CertFile *string + KeyFile *string + CaCertFile *string + CaCertBytes []byte + CertBytes []byte + KeyBytes []byte + SSHKeyFile *string + SSHKeyFileSalt *string + SSHPassword *string + SSHUser *string + SSHKeyBytes []byte + SSHAuthMethod ssh.AuthMethod + Timeout *int + Always *bool + Interval *int + Blocked *string + Direct *string + AuthFile *string + Auth *[]string + AuthURL *string + AuthURLOkCode *int + AuthURLTimeout *int + AuthURLRetry *int + KCP kcpcfg.KCPConfigArgs + UDPParent *string + UDPLocal *string + LocalIPS *[]string + DNSAddress *string + DNSTTL *int + LocalKey *string + ParentKey *string + LocalCompress *bool + ParentCompress *bool +} type Socks struct { cfg SocksArgs checker utils.Checker @@ -32,7 +72,7 @@ type Socks struct { log *logger.Logger } -func NewSocks() Service { +func NewSocks() services.Service { return &Socks{ cfg: SocksArgs{}, checker: utils.Checker{}, @@ -198,11 +238,11 @@ func (s *Socks) Start(args interface{}, log *logger.Logger) (err error) { s.log.Printf("use socks udp parent %s", *s.cfg.UDPParent) } sc := utils.NewServerChannelHost(*s.cfg.Local, s.log) - if *s.cfg.LocalType == TYPE_TCP { + if *s.cfg.LocalType == "tcp" { err = sc.ListenTCP(s.socksConnCallback) - } else if *s.cfg.LocalType == TYPE_TLS { + } else if *s.cfg.LocalType == "tls" { err = sc.ListenTls(s.cfg.CertBytes, s.cfg.KeyBytes, nil, s.socksConnCallback) - } else if *s.cfg.LocalType == TYPE_KCP { + } else if *s.cfg.LocalType == "kcp" { err = sc.ListenKCP(s.cfg.KCP, s.socksConnCallback, s.log) } if err != nil { diff --git a/services/sps.go b/services/sps/sps.go similarity index 89% rename from services/sps.go rename to services/sps/sps.go index 44c606e..ca05c7a 100644 --- a/services/sps.go +++ b/services/sps/sps.go @@ -13,11 +13,44 @@ import ( "strings" "time" + "github.com/snail007/goproxy/services" + "github.com/snail007/goproxy/services/kcpcfg" "github.com/snail007/goproxy/utils" "github.com/snail007/goproxy/utils/conncrypt" "github.com/snail007/goproxy/utils/socks" ) +type SPSArgs struct { + Parent *string + CertFile *string + KeyFile *string + CaCertFile *string + CaCertBytes []byte + CertBytes []byte + KeyBytes []byte + Local *string + ParentType *string + LocalType *string + Timeout *int + KCP kcpcfg.KCPConfigArgs + ParentServiceType *string + DNSAddress *string + DNSTTL *int + AuthFile *string + Auth *[]string + AuthURL *string + AuthURLOkCode *int + AuthURLTimeout *int + AuthURLRetry *int + LocalIPS *[]string + ParentAuth *string + LocalKey *string + ParentKey *string + LocalCompress *bool + ParentCompress *bool + DisableHTTP *bool + DisableSocks5 *bool +} type SPS struct { outPool utils.OutConn cfg SPSArgs @@ -28,7 +61,7 @@ type SPS struct { log *logger.Logger } -func NewSPS() Service { +func NewSPS() services.Service { return &SPS{ outPool: utils.OutConn{}, cfg: SPSArgs{}, @@ -39,14 +72,14 @@ func NewSPS() Service { } func (s *SPS) CheckArgs() (err error) { if *s.cfg.Parent == "" { - err = fmt.Errorf("parent required for %s %s", s.cfg.Protocol(), *s.cfg.Local) + err = fmt.Errorf("parent required for %s %s", *s.cfg.LocalType, *s.cfg.Local) return } if *s.cfg.ParentType == "" { err = fmt.Errorf("parent type unkown,use -T ") return } - if *s.cfg.ParentType == TYPE_TLS || *s.cfg.LocalType == TYPE_TLS { + if *s.cfg.ParentType == "tls" || *s.cfg.LocalType == "tls" { s.cfg.CertBytes, s.cfg.KeyBytes, err = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile) if err != nil { return @@ -70,7 +103,7 @@ func (s *SPS) InitService() (err error) { return } func (s *SPS) InitOutConnPool() { - if *s.cfg.ParentType == TYPE_TLS || *s.cfg.ParentType == TYPE_TCP || *s.cfg.ParentType == TYPE_KCP { + if *s.cfg.ParentType == "tls" || *s.cfg.ParentType == "tcp" || *s.cfg.ParentType == "kcp" { //dur int, isTLS bool, certBytes, keyBytes []byte, //parent string, timeout int, InitialCap int, MaxCap int s.outPool = utils.NewOutConn( @@ -125,17 +158,17 @@ func (s *SPS) Start(args interface{}, log *logger.Logger) (err error) { host, port, _ := net.SplitHostPort(*s.cfg.Local) p, _ := strconv.Atoi(port) sc := utils.NewServerChannel(host, p, s.log) - if *s.cfg.LocalType == TYPE_TCP { + if *s.cfg.LocalType == "tcp" { err = sc.ListenTCP(s.callback) - } else if *s.cfg.LocalType == TYPE_TLS { + } else if *s.cfg.LocalType == "tls" { err = sc.ListenTls(s.cfg.CertBytes, s.cfg.KeyBytes, s.cfg.CaCertBytes, s.callback) - } else if *s.cfg.LocalType == TYPE_KCP { + } else if *s.cfg.LocalType == "kcp" { err = sc.ListenKCP(s.cfg.KCP, s.callback, s.log) } if err != nil { return } - s.log.Printf("%s http(s)+socks proxy on %s", s.cfg.Protocol(), (*sc.Listener).Addr()) + s.log.Printf("%s http(s)+socks proxy on %s", *s.cfg.LocalType, (*sc.Listener).Addr()) s.serverChannels = append(s.serverChannels, &sc) } } @@ -148,7 +181,7 @@ func (s *SPS) Clean() { func (s *SPS) callback(inConn net.Conn) { defer func() { if err := recover(); err != nil { - s.log.Printf("%s conn handler crashed with err : %s \nstack: %s", s.cfg.Protocol(), err, string(debug.Stack())) + s.log.Printf("%s conn handler crashed with err : %s \nstack: %s", *s.cfg.LocalType, err, string(debug.Stack())) } }() if *s.cfg.LocalCompress { @@ -161,11 +194,11 @@ func (s *SPS) callback(inConn net.Conn) { } var err error switch *s.cfg.ParentType { - case TYPE_KCP: + case "kcp": fallthrough - case TYPE_TCP: + case "tcp": fallthrough - case TYPE_TLS: + case "tls": err = s.OutToTCP(&inConn) default: err = fmt.Errorf("unkown parent type %s", *s.cfg.ParentType) diff --git a/services/tcp.go b/services/tcp/tcp.go similarity index 84% rename from services/tcp.go rename to services/tcp/tcp.go index eab2830..43e612d 100644 --- a/services/tcp.go +++ b/services/tcp/tcp.go @@ -9,11 +9,27 @@ import ( "runtime/debug" "time" + "github.com/snail007/goproxy/services" + "github.com/snail007/goproxy/services/kcpcfg" "github.com/snail007/goproxy/utils" "strconv" ) +type TCPArgs struct { + Parent *string + CertFile *string + KeyFile *string + CertBytes []byte + KeyBytes []byte + Local *string + ParentType *string + LocalType *string + Timeout *int + CheckParentInterval *int + KCP kcpcfg.KCPConfigArgs +} + type TCP struct { outPool utils.OutConn cfg TCPArgs @@ -23,7 +39,7 @@ type TCP struct { log *logger.Logger } -func NewTCP() Service { +func NewTCP() services.Service { return &TCP{ outPool: utils.OutConn{}, cfg: TCPArgs{}, @@ -33,14 +49,14 @@ func NewTCP() Service { } func (s *TCP) CheckArgs() (err error) { if *s.cfg.Parent == "" { - err = fmt.Errorf("parent required for %s %s", s.cfg.Protocol(), *s.cfg.Local) + err = fmt.Errorf("parent required for %s %s", *s.cfg.LocalType, *s.cfg.Local) return } if *s.cfg.ParentType == "" { err = fmt.Errorf("parent type unkown,use -T ") return } - if *s.cfg.ParentType == TYPE_TLS || *s.cfg.LocalType == TYPE_TLS { + if *s.cfg.ParentType == "tls" || *s.cfg.LocalType == "tls" { s.cfg.CertBytes, s.cfg.KeyBytes, err = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile) if err != nil { return @@ -86,17 +102,17 @@ func (s *TCP) Start(args interface{}, log *logger.Logger) (err error) { p, _ := strconv.Atoi(port) sc := utils.NewServerChannel(host, p, s.log) - if *s.cfg.LocalType == TYPE_TCP { + if *s.cfg.LocalType == "tcp" { err = sc.ListenTCP(s.callback) - } else if *s.cfg.LocalType == TYPE_TLS { + } else if *s.cfg.LocalType == "tls" { err = sc.ListenTls(s.cfg.CertBytes, s.cfg.KeyBytes, nil, s.callback) - } else if *s.cfg.LocalType == TYPE_KCP { + } else if *s.cfg.LocalType == "kcp" { err = sc.ListenKCP(s.cfg.KCP, s.callback, s.log) } if err != nil { return } - s.log.Printf("%s proxy on %s", s.cfg.Protocol(), (*sc.Listener).Addr()) + s.log.Printf("%s proxy on %s", *s.cfg.LocalType, (*sc.Listener).Addr()) s.sc = &sc return } @@ -107,18 +123,18 @@ func (s *TCP) Clean() { func (s *TCP) callback(inConn net.Conn) { defer func() { if err := recover(); err != nil { - s.log.Printf("%s conn handler crashed with err : %s \nstack: %s", s.cfg.Protocol(), err, string(debug.Stack())) + s.log.Printf("%s conn handler crashed with err : %s \nstack: %s", *s.cfg.LocalType, err, string(debug.Stack())) } }() var err error switch *s.cfg.ParentType { - case TYPE_KCP: + case "kcp": fallthrough - case TYPE_TCP: + case "tcp": fallthrough - case TYPE_TLS: + case "tls": err = s.OutToTCP(&inConn) - case TYPE_UDP: + case "udp": err = s.OutToUDP(&inConn) default: err = fmt.Errorf("unkown parent type %s", *s.cfg.ParentType) @@ -204,7 +220,7 @@ func (s *TCP) OutToUDP(inConn *net.Conn) (err error) { } func (s *TCP) InitOutConnPool() { - if *s.cfg.ParentType == TYPE_TLS || *s.cfg.ParentType == TYPE_TCP || *s.cfg.ParentType == TYPE_KCP { + if *s.cfg.ParentType == "tls" || *s.cfg.ParentType == "tcp" || *s.cfg.ParentType == "kcp" { //dur int, isTLS bool, certBytes, keyBytes []byte, //parent string, timeout int, InitialCap int, MaxCap int s.outPool = utils.NewOutConn( diff --git a/services/tunnel_bridge.go b/services/tunnel/tunnel_bridge.go similarity index 93% rename from services/tunnel_bridge.go rename to services/tunnel/tunnel_bridge.go index 8352d15..ccb7564 100644 --- a/services/tunnel_bridge.go +++ b/services/tunnel/tunnel_bridge.go @@ -9,12 +9,29 @@ import ( "strconv" "time" + "github.com/snail007/goproxy/services" "github.com/snail007/goproxy/utils" //"github.com/xtaci/smux" smux "github.com/hashicorp/yamux" ) +const ( + CONN_CLIENT_CONTROL = uint8(1) + CONN_SERVER = uint8(4) + CONN_CLIENT = uint8(5) +) + +type TunnelBridgeArgs struct { + Parent *string + CertFile *string + KeyFile *string + CertBytes []byte + KeyBytes []byte + Local *string + Timeout *int + Mux *bool +} type ServerConn struct { //ClientLocalAddr string //tcp:2.2.22:333@ID Conn *net.Conn @@ -27,7 +44,7 @@ type TunnelBridge struct { log *logger.Logger } -func NewTunnelBridge() Service { +func NewTunnelBridge() services.Service { return &TunnelBridge{ cfg: TunnelBridgeArgs{}, serverConns: utils.NewConcurrentMap(), diff --git a/services/tunnel_client.go b/services/tunnel/tunnel_client.go similarity index 95% rename from services/tunnel_client.go rename to services/tunnel/tunnel_client.go index 120d450..5fdabef 100644 --- a/services/tunnel_client.go +++ b/services/tunnel/tunnel_client.go @@ -9,12 +9,27 @@ import ( "os" "time" + "github.com/snail007/goproxy/services" "github.com/snail007/goproxy/utils" - //"github.com/xtaci/smux" smux "github.com/hashicorp/yamux" ) +const ( + CONN_SERVER_MUX = uint8(6) + CONN_CLIENT_MUX = uint8(7) +) + +type TunnelClientArgs struct { + Parent *string + CertFile *string + KeyFile *string + CertBytes []byte + KeyBytes []byte + Key *string + Timeout *int + Mux *bool +} type TunnelClient struct { cfg TunnelClientArgs ctrlConn net.Conn @@ -23,7 +38,7 @@ type TunnelClient struct { log *logger.Logger } -func NewTunnelClient() Service { +func NewTunnelClient() services.Service { return &TunnelClient{ cfg: TunnelClientArgs{}, userConns: utils.NewConcurrentMap(), diff --git a/services/tunnel_server.go b/services/tunnel/tunnel_server.go similarity index 95% rename from services/tunnel_server.go rename to services/tunnel/tunnel_server.go index 91f7306..eac5cc6 100644 --- a/services/tunnel_server.go +++ b/services/tunnel/tunnel_server.go @@ -12,36 +12,47 @@ import ( "strings" "time" + "github.com/snail007/goproxy/services" "github.com/snail007/goproxy/utils" //"github.com/xtaci/smux" smux "github.com/hashicorp/yamux" ) -type TunnelServer struct { - cfg TunnelServerArgs - udpChn chan UDPItem - sc utils.ServerChannel - isStop bool - udpConn *net.Conn - userConns utils.ConcurrentMap - log *logger.Logger +type TunnelServerArgs struct { + Parent *string + CertFile *string + KeyFile *string + CertBytes []byte + KeyBytes []byte + Local *string + IsUDP *bool + Key *string + Remote *string + Timeout *int + Route *[]string + Mgr *TunnelServerManager + Mux *bool +} +type UDPItem struct { + packet *[]byte + localAddr *net.UDPAddr + srcAddr *net.UDPAddr } - type TunnelServerManager struct { cfg TunnelServerArgs udpChn chan UDPItem serverID string - servers []*Service + servers []*services.Service log *logger.Logger } -func NewTunnelServerManager() Service { +func NewTunnelServerManager() services.Service { return &TunnelServerManager{ cfg: TunnelServerArgs{}, udpChn: make(chan UDPItem, 50000), serverID: utils.Uniqueid(), - servers: []*Service{}, + servers: []*services.Service{}, } } func (s *TunnelServerManager) Start(args interface{}, log *logger.Logger) (err error) { @@ -146,7 +157,18 @@ func (s *TunnelServerManager) GetConn() (conn net.Conn, err error) { } return } -func NewTunnelServer() Service { + +type TunnelServer struct { + cfg TunnelServerArgs + udpChn chan UDPItem + sc utils.ServerChannel + isStop bool + udpConn *net.Conn + userConns utils.ConcurrentMap + log *logger.Logger +} + +func NewTunnelServer() services.Service { return &TunnelServer{ cfg: TunnelServerArgs{}, udpChn: make(chan UDPItem, 50000), @@ -155,12 +177,6 @@ func NewTunnelServer() Service { } } -type UDPItem struct { - packet *[]byte - localAddr *net.UDPAddr - srcAddr *net.UDPAddr -} - func (s *TunnelServer) StopService() { defer func() { e := recover() diff --git a/services/udp.go b/services/udp/udp.go similarity index 93% rename from services/udp.go rename to services/udp/udp.go index 57cdd59..7bd309d 100644 --- a/services/udp.go +++ b/services/udp/udp.go @@ -12,10 +12,22 @@ import ( "strings" "time" + "github.com/snail007/goproxy/services" "github.com/snail007/goproxy/services/kcpcfg" "github.com/snail007/goproxy/utils" ) +type UDPArgs struct { + Parent *string + CertFile *string + KeyFile *string + CertBytes []byte + KeyBytes []byte + Local *string + ParentType *string + Timeout *int + CheckParentInterval *int +} type UDP struct { p utils.ConcurrentMap outPool utils.OutConn @@ -25,7 +37,7 @@ type UDP struct { log *logger.Logger } -func NewUDP() Service { +func NewUDP() services.Service { return &UDP{ outPool: utils.OutConn{}, p: utils.NewConcurrentMap(), @@ -50,7 +62,7 @@ func (s *UDP) CheckArgs() (err error) { return } func (s *UDP) InitService() (err error) { - if *s.cfg.ParentType != TYPE_UDP { + if *s.cfg.ParentType != "udp" { s.InitOutConnPool() } return @@ -105,11 +117,11 @@ func (s *UDP) callback(packet []byte, localAddr, srcAddr *net.UDPAddr) { }() var err error switch *s.cfg.ParentType { - case TYPE_TCP: + case "tcp": fallthrough - case TYPE_TLS: + case "tls": err = s.OutToTCP(packet, localAddr, srcAddr) - case TYPE_UDP: + case "udp": err = s.OutToUDP(packet, localAddr, srcAddr) default: err = fmt.Errorf("unkown parent type %s", *s.cfg.ParentType) @@ -234,7 +246,7 @@ func (s *UDP) OutToUDP(packet []byte, localAddr, srcAddr *net.UDPAddr) (err erro return } func (s *UDP) InitOutConnPool() { - if *s.cfg.ParentType == TYPE_TLS || *s.cfg.ParentType == TYPE_TCP { + if *s.cfg.ParentType == "tls" || *s.cfg.ParentType == "tcp" { //dur int, isTLS bool, certBytes, keyBytes []byte, //parent string, timeout int, InitialCap int, MaxCap int s.outPool = utils.NewOutConn(