diff --git a/CHANGELOG b/CHANGELOG index de63afb..8977cda 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,7 +1,9 @@ proxy更新日志 v3.4 1.tcp代理增加了kcp协议传输数据. - +2.优化了死循环检查,增加了添加本地IP参数,当VPS在nat设备后面, + vps上网卡IP都是内网IP,这个时候可以通过-g参数添加vps的外网ip防止死循环. + v3.4 1.socks5代理新增了用户名密码验证支持. 2.socks5,http(s)代理增加了kcp传输协议支持. diff --git a/README.md b/README.md index 67d5337..2af889d 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5代理服务 - [环境](#使用教程) - [使用配置文件](#使用配置文件) - [生成通讯证书文件](#生成加密通讯需要的证书文件) +- [安全建议](#安全建议) ### 手册目录 - [1. HTTP代理](#1http代理) @@ -149,6 +150,11 @@ http,tcp,udp代理过程会和上级通讯,为了安全我们采用加密通讯, `./proxy keygen` 默认会在当前程序目录下面生成证书文件proxy.crt和key文件proxy.key。 +### 安全建议 +当VPS在nat设备后面,vps上网卡IP都是内网IP,这个时候可以通过-g参数添加vps的外网ip防止死循环. +假设你的vps外网ip是23.23.23.23,下面命令通过-g参数设置23.23.23.23 +`./proxy http -g "23.23.23.23"` + ### 1.HTTP代理 #### **1.1.普通HTTP代理** `./proxy http -t tcp -p "0.0.0.0:38080"` diff --git a/config.go b/config.go index ebacbd4..5e43e03 100755 --- a/config.go +++ b/config.go @@ -60,6 +60,7 @@ func initConfig() (err error) { httpArgs.SSHPassword = http.Flag("ssh-password", "password for ssh").Short('A').Default("").String() httpArgs.KCPKey = http.Flag("kcp-key", "key for kcp encrypt/decrypt data").Short('B').Default("encrypt").String() httpArgs.KCPMethod = http.Flag("kcp-method", "kcp encrypt/decrypt method").Short('M').Default("3des").String() + httpArgs.LocalIPS = http.Flag("local bind ips", "if your host behind a nat,set your public ip here avoid dead loop").Short('g').Strings() //########tcp######### tcp := app.Command("tcp", "proxy on tcp mode") @@ -134,6 +135,7 @@ func initConfig() (err error) { socksArgs.Auth = socks.Flag("auth", "socks auth username and password, mutiple user repeat -a ,such as: -a user1:pass1 -a user2:pass2").Short('a').Strings() socksArgs.KCPKey = socks.Flag("kcp-key", "key for kcp encrypt/decrypt data").Short('B').Default("encrypt").String() socksArgs.KCPMethod = socks.Flag("kcp-method", "kcp encrypt/decrypt method").Short('M').Default("3des").String() + socksArgs.LocalIPS = socks.Flag("local bind ips", "if your host behind a nat,set your public ip here avoid dead loop").Short('g').Strings() //parse args serviceName := kingpin.MustParse(app.Parse(os.Args[1:])) diff --git a/services/args.go b/services/args.go index 6a3106c..c448fc9 100644 --- a/services/args.go +++ b/services/args.go @@ -93,6 +93,7 @@ type HTTPArgs struct { SSHAuthMethod ssh.AuthMethod KCPMethod *string KCPKey *string + LocalIPS *[]string } type UDPArgs struct { Parent *string @@ -132,6 +133,7 @@ type SocksArgs struct { KCPKey *string UDPParent *string UDPLocal *string + LocalIPS *[]string } func (a *TCPArgs) Protocol() string { diff --git a/services/http.go b/services/http.go index 4d3e0bf..8931b6b 100644 --- a/services/http.go +++ b/services/http.go @@ -362,6 +362,9 @@ func (s *HTTP) IsDeadLoop(inLocalAddr string, host string) bool { } } interfaceIPs, err := utils.GetAllInterfaceAddr() + for _, ip := range *s.cfg.LocalIPS { + interfaceIPs = append(interfaceIPs, net.ParseIP(ip).To4()) + } if err == nil { for _, localIP := range interfaceIPs { for _, outIP := range outIPs { diff --git a/services/socks.go b/services/socks.go index 8dbe6f9..9221e05 100644 --- a/services/socks.go +++ b/services/socks.go @@ -167,6 +167,11 @@ func (s *Socks) udpCallback(b []byte, localAddr, srcAddr *net.UDPAddr) { log.Printf("parse udp packet fail, ERR:%s", err) return } + //防止死循环 + if s.IsDeadLoop((*localAddr).String(), p.Host()) { + log.Printf("dead loop detected , %s", p.Host()) + return + } //log.Printf("##########udp to -> %s:%s###########", p.Host(), p.Port()) if *s.cfg.Parent != "" { //有上级代理,转发给上级 @@ -398,6 +403,13 @@ func (s *Socks) proxyTCP(inConn *net.Conn, methodReq socks.MethodsRequest, reque useProxy := true tryCount := 0 maxTryCount := 5 + //防止死循环 + if s.IsDeadLoop((*inConn).LocalAddr().String(), request.Host()) { + utils.CloseConn(inConn) + log.Printf("dead loop detected , %s", request.Host()) + utils.CloseConn(inConn) + return + } for { if *s.cfg.Always { outConn, err = s.getOutConn(methodReq.Bytes(), request.Bytes(), request.Addr()) @@ -568,3 +580,38 @@ func (s *Socks) InitBasicAuth() (err error) { func (s *Socks) IsBasicAuth() bool { return *s.cfg.AuthFile != "" || len(*s.cfg.Auth) > 0 } +func (s *Socks) IsDeadLoop(inLocalAddr string, host string) bool { + inIP, inPort, err := net.SplitHostPort(inLocalAddr) + if err != nil { + return false + } + outDomain, outPort, err := net.SplitHostPort(host) + if err != nil { + return false + } + if inPort == outPort { + var outIPs []net.IP + outIPs, err = net.LookupIP(outDomain) + if err == nil { + for _, ip := range outIPs { + if ip.String() == inIP { + return true + } + } + } + interfaceIPs, err := utils.GetAllInterfaceAddr() + for _, ip := range *s.cfg.LocalIPS { + interfaceIPs = append(interfaceIPs, net.ParseIP(ip).To4()) + } + if err == nil { + for _, localIP := range interfaceIPs { + for _, outIP := range outIPs { + if localIP.Equal(outIP) { + return true + } + } + } + } + } + return false +}