Compare commits
36 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bb933cfb6e | ||
|
|
2603802dd9 | ||
|
|
68ad904772 | ||
|
|
af19e5d25b | ||
|
|
62907efe0c | ||
|
|
29e4cdf4e2 | ||
|
|
3a4a9a3a27 | ||
|
|
04ef338807 | ||
|
|
3c070a7da3 | ||
|
|
c34f7db239 | ||
|
|
1f655808c6 | ||
|
|
0226d2cde3 | ||
|
|
61bb2d8ca0 | ||
|
|
f5d09b878b | ||
|
|
6b4ee97f05 | ||
|
|
12dd591c58 | ||
|
|
3b49f17e01 | ||
|
|
cb8d0c0b42 | ||
|
|
e92375f6a9 | ||
|
|
c20e19d74f | ||
|
|
50886bd69a | ||
|
|
eaf836eff3 | ||
|
|
bf72325fc0 | ||
|
|
846956a9fe | ||
|
|
20c31b0c68 | ||
|
|
d84a4bec86 | ||
|
|
05d2f16777 | ||
|
|
9fa1c4932b | ||
|
|
0932aecff3 | ||
|
|
a9f8acd98d | ||
|
|
2336e77ac4 | ||
|
|
1ef8d7c82a | ||
|
|
24d54725df | ||
|
|
9b430b5ba4 | ||
|
|
0ee7abbd6a | ||
|
|
361215fb6f |
@ -1,4 +1,9 @@
|
||||
proxy更新日志
|
||||
v5.2
|
||||
1.修复了HTTP(S)\SPS反向代理无法正常工作的问题.
|
||||
2.优化了智能判断,减少不必要的DNS解析.
|
||||
3.重构了SOCKS和SPS的UDP功能,基于UDP的游戏加速嗖嗖的.
|
||||
|
||||
v5.1
|
||||
1.优化了kcp默认mtu配置,调整为450.
|
||||
2.优化了HTTP(S)\SOCKS5代理智能判断,更加精确。
|
||||
|
||||
59
README.md
59
README.md
@ -6,7 +6,18 @@ Proxy is a high performance HTTP, HTTPS, HTTPS, websocket, TCP, UDP, Socks5 prox
|
||||
|
||||
[](https://github.com/snail007/goproxy/) []() [](https://github.com/snail007/goproxy/releases) [](https://github.com/snail007/goproxy/releases)
|
||||
|
||||
[中文手册](/README_ZH.md) **[全平台GUI版本](/gui/README.md)** **[全平台SDK](/sdk/README.md)**
|
||||
**[中文手册](/README_ZH.md)**
|
||||
|
||||
**[全平台图形界面版本](/gui/README.md)**
|
||||
|
||||
**[全平台SDK](/sdk/README.md)**
|
||||
|
||||
### How to contribute to the code (Pull Request)?
|
||||
|
||||
Pull Request is welcomed.
|
||||
First, you need to clone the project to your account, and then modify the code on the dev branch.
|
||||
Finally, Pull Request to dev branch of goproxy project, and contribute code for efficiency.
|
||||
PR needs to explain what changes have been made and why you change them.
|
||||
|
||||
### Features
|
||||
- chain-style proxy: the program itself can be a primary proxy, and if a parent proxy is set, it can be used as a second level proxy or even a N level proxy.
|
||||
@ -37,26 +48,7 @@ Proxy is a high performance HTTP, HTTPS, HTTPS, websocket, TCP, UDP, Socks5 prox
|
||||
- ...
|
||||
|
||||
|
||||
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)
|
||||
- [v4.5 manual](https://github.com/snail007/goproxy/tree/v4.5)
|
||||
- [v4.4 manual](https://github.com/snail007/goproxy/tree/v4.4)
|
||||
- [v4.3 manual](https://github.com/snail007/goproxy/tree/v4.3)
|
||||
- [v4.2 manual](https://github.com/snail007/goproxy/tree/v4.2)
|
||||
- [v4.0-4.1 manual](https://github.com/snail007/goproxy/tree/v4.1)
|
||||
- [v3.9 manual](https://github.com/snail007/goproxy/tree/v3.9)
|
||||
- [v3.8 manual](https://github.com/snail007/goproxy/tree/v3.8)
|
||||
- [v3.6-v3.7 manual](https://github.com/snail007/goproxy/tree/v3.6)
|
||||
- [v3.5 manual](https://github.com/snail007/goproxy/tree/v3.5)
|
||||
- [v3.4 manual](https://github.com/snail007/goproxy/tree/v3.4)
|
||||
- [v3.3 manual](https://github.com/snail007/goproxy/tree/v3.3)
|
||||
- [v3.2 manual](https://github.com/snail007/goproxy/tree/v3.2)
|
||||
- [v3.1 manual](https://github.com/snail007/goproxy/tree/v3.1)
|
||||
- [v3.0 manual](https://github.com/snail007/goproxy/tree/v3.0)
|
||||
- [v2.x manual](https://github.com/snail007/goproxy/tree/v2.2)
|
||||
This page is the v5.2 manual, and the other version of the manual can be checked by the following [link](docs/old-release.md).
|
||||
|
||||
### How to find the organization?
|
||||
[Click to join the proxy group of gitter](https://gitter.im/go-proxy/Lobby?utm_source=share-link&utm_medium=link&utm_campaign=share-link)
|
||||
@ -235,9 +227,18 @@ for example, --log proxy.log, The log will be exported to proxy.log file which i
|
||||
|
||||
### **Generating a communication certificate file**
|
||||
HTTP, TCP, UDP proxy process will communicate with parent proxy. In order to secure, we use encrypted communication. Of course, we can choose not to encrypted communication. All communication with parent proxy in this tutorial is encrypted, requiring certificate files.
|
||||
The OpenSSL command is installed on the Linux and encrypted certificate can be generated directly through the following command.
|
||||
`./proxy keygen`
|
||||
By default, the certificate file proxy.crt and the key file proxy.key are generated under the current program directory.
|
||||
|
||||
1.Generate signed certificates and key files through the following commands.
|
||||
`./proxy keygen -C proxy`
|
||||
The certificate file proxy.crt and key file proxy.key will be generated under the current directory.
|
||||
|
||||
2.Through the following commands, use the signed certificate proxy.crt and key file proxy.key to issue new certificates: goproxy.crt and goproxy.key.
|
||||
`./proxy keygen -s -C proxy -c goproxy`
|
||||
The certificate file goproxy.crt and key file goproxy.key will be generated under the current program directory.
|
||||
|
||||
3.By default, the domain name in the certificate is a random domain and can be specified using the `-n test.com` parameter.
|
||||
|
||||
4.More usage:`proxy keygen --help`。
|
||||
|
||||
### **Daemon mode**
|
||||
After the default execution of proxy, if you want to keep proxy running, you can't close the command line.
|
||||
@ -831,7 +832,7 @@ through this way, When you visits the website by local proxy 8080, it visits the
|
||||
### **6.Proxy protocol conversion**
|
||||
|
||||
#### **6.1.Functional introduction**
|
||||
The proxy protocol conversion use the SPS subcommand (abbreviation of socks+https), SPS itself does not provide the proxy function, just accept the proxy request and then converse protocol and forwarded to the existing HTTP (s) or Socks5 proxy. SPS can use existing HTTP (s) or Socks5 proxy converse to support HTTP (s) and Socks5 HTTP (s) proxy at the same time by one port, and proxy supports forward and reverse proxy (SNI), SOCKS5 proxy which is conversed does not support UDP. in addition to the existing HTTP or Socks5 proxy, which supports TLS, TCP, KCP three modes and chain-style connection. That is more than one SPS node connection can build encryption channel.
|
||||
The proxy protocol conversion use the SPS subcommand (abbreviation of socks+https), SPS itself does not provide the proxy function, just accept the proxy request and then converse protocol and forwarded to the existing HTTP (s) or Socks5 proxy. SPS can use existing HTTP (s) or Socks5 proxy converse to support HTTP (s) and Socks5 HTTP (s) proxy at the same time by one port, and proxy supports forward and reverse proxy (SNI), SOCKS5 proxy which is also does support UDP when parent is Socks5. in addition to the existing HTTP or Socks5 proxy, which supports TLS, TCP, KCP three modes and chain-style connection. That is more than one SPS node connection can build encryption channel.
|
||||
|
||||
#### **6.2.HTTP(S) to HTTP(S) + SOCKS5**
|
||||
Suppose there is a common HTTP (s) proxy: 127.0.0.1:8080. Now we turn it into a common proxy that supports HTTP (s) and Socks5 at the same time. The local port after transformation is 18080.
|
||||
@ -1073,19 +1074,15 @@ Then the local UDP port 53 provides a security and anti pollution DNS analysis.
|
||||
- HTTP (s) proxy support PAC?
|
||||
- Welcome joining group feedback...
|
||||
|
||||
### How to contribute to the code (Pull Request)?
|
||||
First, you need to clone the project to your account, and then modify the code on the dev branch.
|
||||
Finally, Pull Request to dev branch of goproxy project, and contribute code for efficiency.
|
||||
PR needs to explain what changes have been made and why you change them.
|
||||
### How to use the source code?
|
||||
|
||||
### How to use the source code?
|
||||
Recommend go1.10.1.
|
||||
`go get github.com/snail007/goproxy`
|
||||
use command cd to enter your go SRC directory
|
||||
then cd to enter `github.com/snail007/goproxy`.
|
||||
Direct compilation:`go build -o proxy`
|
||||
execution: `go run *.go`
|
||||
`utils` is a toolkit, and `service` is a specific service class.
|
||||
`utils` is a toolkit, and `service` is a specific service class.
|
||||
|
||||
### License
|
||||
Proxy is licensed under GPLv3 license.
|
||||
|
||||
32
README_ZH.md
32
README_ZH.md
@ -7,7 +7,17 @@ Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5代理服务
|
||||
|
||||
[](https://github.com/snail007/goproxy/) []() [](https://github.com/snail007/goproxy/releases) [](https://github.com/snail007/goproxy/releases)
|
||||
|
||||
**[English Manual](/README.md)** **[全平台GUI版本](/gui/README.md)** **[全平台SDK](/sdk/README.md)**
|
||||
**[English Manual](/README.md)**
|
||||
|
||||
**[全平台图形界面版本](/gui/README.md)**
|
||||
|
||||
**[全平台SDK](/sdk/README.md)**
|
||||
|
||||
### 如何贡献代码(Pull Request)?
|
||||
|
||||
欢迎加入一起发展壮大proxy.首先需要clone本项目到自己的帐号下面,
|
||||
然后在dev分支上面修改代码,最后发Pull Request到goproxy项目的dev分支即可,
|
||||
为了高效贡献代码,pr的时候需要说明做了什么变更,原因是什么.
|
||||
|
||||
### Features
|
||||
- 链式代理,程序本身可以作为一级代理,如果设置了上级代理那么可以作为二级代理,乃至N级代理.
|
||||
@ -38,7 +48,7 @@ Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5代理服务
|
||||
- ...
|
||||
|
||||
|
||||
本页是v5.1手册,其他版本手册请点击[这里](docs/old-release.md)查看.
|
||||
本页是v5.2手册,其他版本手册请点击[这里](docs/old-release.md)查看.
|
||||
|
||||
|
||||
### 怎么找到组织?
|
||||
@ -689,7 +699,14 @@ server连接到bridge的时候,如果同时有多个client连接到同一个brid
|
||||
`./proxy help client`
|
||||
|
||||
### **5.SOCKS5代理**
|
||||
提示:SOCKS5代理,支持CONNECT,UDP协议,不支持BIND,支持用户名密码认证.
|
||||
提示:
|
||||
|
||||
SOCKS5代理,支持CONNECT,UDP协议,不支持BIND,支持用户名密码认证.
|
||||
|
||||
***如果你的VPS是阿里云,腾讯云这种VPS,就是ifconfig看不见你的公网IP,只能看见内网IP,***
|
||||
|
||||
***那么需要加上`-g VPS公网IP`参数,SOCKS5代理的UDP功能才能正常工作。***
|
||||
|
||||
#### **5.1.普通SOCKS5代理**
|
||||
`./proxy socks -t tcp -p "0.0.0.0:38080"`
|
||||
|
||||
@ -837,7 +854,7 @@ proxy的socks代理在tcp之上可以通过自定义加密和tls标准加密以
|
||||
### **6.代理协议转换**
|
||||
|
||||
#### **6.1 功能介绍**
|
||||
代理协议转换使用的是sps子命令(socks+https的缩写),sps本身不提供代理功能,只是接受代理请求"转换并转发"给已经存在的http(s)代理或者socks5代理;sps可以把已经存在的http(s)代理或者socks5代理转换为一个端口同时支持http(s)和socks5代理,而且http(s)代理支持正向代理和反向代理(SNI),转换后的SOCKS5代理不支持UDP功能;另外对于已经存在的http(s)代理或者socks5代理,支持tls、tcp、kcp三种模式,支持链式连接,也就是可以多个sps结点层级连接构建加密通道。
|
||||
代理协议转换使用的是sps子命令(socks+https的缩写),sps本身不提供代理功能,只是接受代理请求"转换并转发"给已经存在的http(s)代理或者socks5代理;sps可以把已经存在的http(s)代理或者socks5代理转换为一个端口同时支持http(s)和socks5代理,而且http(s)代理支持正向代理和反向代理(SNI),转换后的SOCKS5代理,当上级是SOCKS5时仍然支持UDP功能;另外对于已经存在的http(s)代理或者socks5代理,支持tls、tcp、kcp三种模式,支持链式连接,也就是可以多个sps结点层级连接构建加密通道。
|
||||
|
||||
#### **6.2 HTTP(S)转HTTP(S)+SOCKS5**
|
||||
假设已经存在一个普通的http(s)代理:127.0.0.1:8080,现在我们把它转为同时支持http(s)和socks5的普通代理,转换后的本地端口为18080。
|
||||
@ -1109,11 +1126,6 @@ fast3:`--nodelay=1 --interval=10 --resend=2 --nc=1`
|
||||
- http(s)代理增加pac支持?
|
||||
- 欢迎加群反馈...
|
||||
|
||||
### 如何贡献代码(Pull Request)?
|
||||
首先需要clone本项目到自己的帐号下面,然后在dev分支上面修改代码,
|
||||
最后发Pull Request到goproxy项目的dev分支即可,为了高效贡献代码,
|
||||
pr的时候需要说明做了什么变更,原因是什么.
|
||||
|
||||
### 如何使用源码?
|
||||
建议go1.10.1.
|
||||
`go get github.com/snail007/goproxy`
|
||||
@ -1133,5 +1145,3 @@ QQ交流群:189618940
|
||||
如果proxy帮助你解决了很多问题,你可以通过下面的捐赠更好的支持proxy.
|
||||
<img src="https://github.com/snail007/goproxy/blob/master/docs/images/alipay.jpg?raw=true" width="200"/>
|
||||
<img src="https://github.com/snail007/goproxy/blob/master/docs/images/wxpay.jpg?raw=true" width="200"/>
|
||||
|
||||
|
||||
|
||||
@ -198,8 +198,6 @@ func initConfig() (err error) {
|
||||
socksArgs.ParentType = socks.Flag("parent-type", "parent protocol type <tls|tcp|kcp|ssh>").Default("tcp").Short('T').Enum("tls", "tcp", "kcp", "ssh")
|
||||
socksArgs.LocalType = socks.Flag("local-type", "local protocol type <tls|tcp|kcp>").Default("tcp").Short('t').Enum("tls", "tcp", "kcp")
|
||||
socksArgs.Local = socks.Flag("local", "local ip:port to listen").Short('p').Default(":33080").String()
|
||||
socksArgs.UDPParent = socks.Flag("udp-parent", "udp parent address, such as: \"23.32.32.19:33090\"").Default("").Short('X').String()
|
||||
socksArgs.UDPLocal = socks.Flag("udp-local", "udp local ip:port to listen").Short('x').Default(":33090").String()
|
||||
socksArgs.CertFile = socks.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String()
|
||||
socksArgs.CaCertFile = socks.Flag("ca", "ca cert file for tls").Default("").String()
|
||||
socksArgs.KeyFile = socks.Flag("key", "key file for tls").Short('K').Default("proxy.key").String()
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
# Old Versions of Proxy
|
||||
|
||||
- [v5.1手册](https://github.com/snail007/goproxy/tree/v5.1)
|
||||
- [v5.0手册](https://github.com/snail007/goproxy/tree/v5.0)
|
||||
- [v4.9手册](https://github.com/snail007/goproxy/tree/v4.9)
|
||||
- [v4.8手册](https://github.com/snail007/goproxy/tree/v4.8)
|
||||
|
||||
@ -5,7 +5,7 @@ if [ -e /tmp/proxy ]; then
|
||||
fi
|
||||
mkdir /tmp/proxy
|
||||
cd /tmp/proxy
|
||||
wget https://github.com/snail007/goproxy/releases/download/v5.1/proxy-linux-amd64.tar.gz
|
||||
wget https://github.com/snail007/goproxy/releases/download/v5.2/proxy-linux-amd64.tar.gz
|
||||
|
||||
# #install proxy
|
||||
tar zxvf proxy-linux-amd64.tar.gz
|
||||
@ -19,7 +19,7 @@ fi
|
||||
|
||||
if [ ! -e /etc/proxy/proxy.crt ]; then
|
||||
cd /etc/proxy/
|
||||
proxy keygen >/dev/null 2>&1
|
||||
proxy keygen -C proxy >/dev/null 2>&1
|
||||
fi
|
||||
rm -rf /tmp/proxy
|
||||
echo "install done"
|
||||
|
||||
2
main.go
2
main.go
@ -9,7 +9,7 @@ import (
|
||||
"github.com/snail007/goproxy/services"
|
||||
)
|
||||
|
||||
const APP_VERSION = "5.1"
|
||||
const APP_VERSION = "5.2"
|
||||
|
||||
func main() {
|
||||
err := initConfig()
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#!/bin/bash
|
||||
VER="5.1"
|
||||
VER="5.2"
|
||||
RELEASE="release-${VER}"
|
||||
rm -rf .cert
|
||||
mkdir .cert
|
||||
|
||||
@ -76,7 +76,7 @@ func (s *DNS) InitService() (err error) {
|
||||
nil,
|
||||
&net.Dialer{
|
||||
Timeout: 5 * time.Second,
|
||||
KeepAlive: 5 * time.Second,
|
||||
KeepAlive: 2 * time.Second,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
|
||||
@ -194,8 +194,6 @@ func Start(serviceID, serviceArgsStr string) (errStr string) {
|
||||
socksArgs.ParentType = socks.Flag("parent-type", "parent protocol type <tls|tcp|kcp|ssh>").Default("tcp").Short('T').Enum("tls", "tcp", "kcp", "ssh")
|
||||
socksArgs.LocalType = socks.Flag("local-type", "local protocol type <tls|tcp|kcp>").Default("tcp").Short('t').Enum("tls", "tcp", "kcp")
|
||||
socksArgs.Local = socks.Flag("local", "local ip:port to listen").Short('p').Default(":33080").String()
|
||||
socksArgs.UDPParent = socks.Flag("udp-parent", "udp parent address, such as: \"23.32.32.19:33090\"").Default("").Short('X').String()
|
||||
socksArgs.UDPLocal = socks.Flag("udp-local", "udp local ip:port to listen").Short('x').Default(":33090").String()
|
||||
socksArgs.CertFile = socks.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String()
|
||||
socksArgs.CaCertFile = socks.Flag("ca", "ca cert file for tls").Default("").String()
|
||||
socksArgs.KeyFile = socks.Flag("key", "key file for tls").Short('K').Default("proxy.key").String()
|
||||
|
||||
@ -277,10 +277,11 @@ func (s *HTTP) callback(inConn net.Conn) {
|
||||
} else if *s.cfg.Always {
|
||||
useProxy = true
|
||||
} else {
|
||||
k := s.Resolve(address)
|
||||
s.checker.Add(address, k)
|
||||
//var n, m uint
|
||||
useProxy, _, _ = s.checker.IsBlocked(k)
|
||||
var isInMap bool
|
||||
useProxy, isInMap, _, _ = s.checker.IsBlocked(address)
|
||||
if !isInMap {
|
||||
s.checker.Add(address, s.Resolve(address))
|
||||
}
|
||||
//s.log.Printf("blocked ? : %v, %s , fail:%d ,success:%d", useProxy, address, n, m)
|
||||
}
|
||||
}
|
||||
@ -344,7 +345,6 @@ func (s *HTTP) OutToTCP(useProxy bool, address string, inConn *net.Conn, req *ut
|
||||
Password: *s.cfg.ParentKey,
|
||||
})
|
||||
}
|
||||
|
||||
outAddr := outConn.RemoteAddr().String()
|
||||
//outLocalAddr := outConn.LocalAddr().String()
|
||||
if req.IsHTTPS() && (!useProxy || *s.cfg.ParentType == "ssh") {
|
||||
@ -353,8 +353,8 @@ func (s *HTTP) OutToTCP(useProxy bool, address string, inConn *net.Conn, req *ut
|
||||
} else {
|
||||
//https或者http,上级是代理,proxy需要转发
|
||||
outConn.SetDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout)))
|
||||
//直连目标或上级非代理,清理HTTP头部的代理头信息
|
||||
if !useProxy || *s.cfg.ParentType == "ssh" {
|
||||
//直连目标或上级非代理或非SNI,清理HTTP头部的代理头信息.
|
||||
if (!useProxy || *s.cfg.ParentType == "ssh") && !req.IsSNI {
|
||||
_, err = outConn.Write(utils.RemoveProxyHeaders(req.HeadBuf))
|
||||
} else {
|
||||
_, err = outConn.Write(req.HeadBuf)
|
||||
@ -524,6 +524,7 @@ func (s *HTTP) Resolve(address string) string {
|
||||
ip, err := s.domainResolver.Resolve(address)
|
||||
if err != nil {
|
||||
s.log.Printf("dns error %s , ERR:%s", address, err)
|
||||
return address
|
||||
}
|
||||
return ip
|
||||
}
|
||||
|
||||
@ -88,7 +88,7 @@ func (s *MuxBridge) StopService() {
|
||||
(*(*s.sc).Listener).Close()
|
||||
}
|
||||
for _, g := range s.clientControlConns.Items() {
|
||||
for _, session := range g.(utils.ConcurrentMap).Items() {
|
||||
for _, session := range g.(*utils.ConcurrentMap).Items() {
|
||||
(session.(*smux.Session)).Close()
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@ package socks
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
logger "log"
|
||||
"net"
|
||||
@ -13,7 +14,6 @@ import (
|
||||
"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"
|
||||
@ -48,8 +48,6 @@ type SocksArgs struct {
|
||||
AuthURLTimeout *int
|
||||
AuthURLRetry *int
|
||||
KCP kcpcfg.KCPConfigArgs
|
||||
UDPParent *string
|
||||
UDPLocal *string
|
||||
LocalIPS *[]string
|
||||
DNSAddress *string
|
||||
DNSTTL *int
|
||||
@ -59,27 +57,31 @@ type SocksArgs struct {
|
||||
ParentCompress *bool
|
||||
}
|
||||
type Socks struct {
|
||||
cfg SocksArgs
|
||||
checker utils.Checker
|
||||
basicAuth utils.BasicAuth
|
||||
sshClient *ssh.Client
|
||||
lockChn chan bool
|
||||
udpSC utils.ServerChannel
|
||||
sc *utils.ServerChannel
|
||||
domainResolver utils.DomainResolver
|
||||
isStop bool
|
||||
userConns utils.ConcurrentMap
|
||||
log *logger.Logger
|
||||
cfg SocksArgs
|
||||
checker utils.Checker
|
||||
basicAuth utils.BasicAuth
|
||||
sshClient *ssh.Client
|
||||
lockChn chan bool
|
||||
udpSC utils.ServerChannel
|
||||
sc *utils.ServerChannel
|
||||
domainResolver utils.DomainResolver
|
||||
isStop bool
|
||||
userConns utils.ConcurrentMap
|
||||
log *logger.Logger
|
||||
udpRelatedPacketConns utils.ConcurrentMap
|
||||
udpLocalKey []byte
|
||||
udpParentKey []byte
|
||||
}
|
||||
|
||||
func NewSocks() services.Service {
|
||||
return &Socks{
|
||||
cfg: SocksArgs{},
|
||||
checker: utils.Checker{},
|
||||
basicAuth: utils.BasicAuth{},
|
||||
lockChn: make(chan bool, 1),
|
||||
isStop: false,
|
||||
userConns: utils.NewConcurrentMap(),
|
||||
cfg: SocksArgs{},
|
||||
checker: utils.Checker{},
|
||||
basicAuth: utils.BasicAuth{},
|
||||
lockChn: make(chan bool, 1),
|
||||
isStop: false,
|
||||
userConns: utils.NewConcurrentMap(),
|
||||
udpRelatedPacketConns: utils.NewConcurrentMap(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -103,17 +105,6 @@ func (s *Socks) CheckArgs() (err error) {
|
||||
err = fmt.Errorf("parent type unkown,use -T <tls|tcp|ssh|kcp>")
|
||||
return
|
||||
}
|
||||
host, _, e := net.SplitHostPort(*s.cfg.Parent)
|
||||
if e != nil {
|
||||
err = fmt.Errorf("parent format error : %s", e)
|
||||
return
|
||||
}
|
||||
if *s.cfg.UDPParent == "" {
|
||||
*s.cfg.UDPParent = net.JoinHostPort(host, "33090")
|
||||
}
|
||||
if strings.HasPrefix(*s.cfg.UDPParent, ":") {
|
||||
*s.cfg.UDPParent = net.JoinHostPort(host, strings.TrimLeft(*s.cfg.UDPParent, ":"))
|
||||
}
|
||||
if *s.cfg.ParentType == "ssh" {
|
||||
if *s.cfg.SSHUser == "" {
|
||||
err = fmt.Errorf("ssh user required")
|
||||
@ -145,6 +136,9 @@ func (s *Socks) CheckArgs() (err error) {
|
||||
}
|
||||
}
|
||||
}
|
||||
s.udpLocalKey = s.LocalUDPKey()
|
||||
s.udpParentKey = s.ParentUDPKey()
|
||||
//s.log.Printf("udpLocalKey : %v , udpParentKey : %v", s.udpLocalKey, s.udpParentKey)
|
||||
return
|
||||
}
|
||||
func (s *Socks) InitService() (err error) {
|
||||
@ -186,14 +180,6 @@ func (s *Socks) InitService() (err error) {
|
||||
}
|
||||
if *s.cfg.ParentType == "ssh" {
|
||||
s.log.Printf("warn: socks udp not suppored for ssh")
|
||||
} else {
|
||||
s.udpSC = utils.NewServerChannelHost(*s.cfg.UDPLocal, s.log)
|
||||
e := s.udpSC.ListenUDP(s.udpCallback)
|
||||
if e != nil {
|
||||
err = fmt.Errorf("init udp service fail, ERR: %s", e)
|
||||
return
|
||||
}
|
||||
s.log.Printf("udp socks proxy on %s", s.udpSC.UDPListener.LocalAddr())
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -220,6 +206,9 @@ func (s *Socks) StopService() {
|
||||
for _, c := range s.userConns.Items() {
|
||||
(*c.(*net.Conn)).Close()
|
||||
}
|
||||
for _, c := range s.udpRelatedPacketConns.Items() {
|
||||
(*c.(*net.UDPConn)).Close()
|
||||
}
|
||||
}
|
||||
func (s *Socks) Start(args interface{}, log *logger.Logger) (err error) {
|
||||
s.log = log
|
||||
@ -234,9 +223,6 @@ func (s *Socks) Start(args interface{}, log *logger.Logger) (err error) {
|
||||
if *s.cfg.Parent != "" {
|
||||
s.log.Printf("use %s parent %s", *s.cfg.ParentType, *s.cfg.Parent)
|
||||
}
|
||||
if *s.cfg.UDPParent != "" {
|
||||
s.log.Printf("use socks udp parent %s", *s.cfg.UDPParent)
|
||||
}
|
||||
sc := utils.NewServerChannelHost(*s.cfg.Local, s.log)
|
||||
if *s.cfg.LocalType == "tcp" {
|
||||
err = sc.ListenTCP(s.socksConnCallback)
|
||||
@ -255,165 +241,7 @@ func (s *Socks) Start(args interface{}, log *logger.Logger) (err error) {
|
||||
func (s *Socks) Clean() {
|
||||
s.StopService()
|
||||
}
|
||||
func (s *Socks) UDPKey() []byte {
|
||||
return s.cfg.KeyBytes[:32]
|
||||
}
|
||||
func (s *Socks) udpCallback(b []byte, localAddr, srcAddr *net.UDPAddr) {
|
||||
rawB := b
|
||||
var err error
|
||||
if *s.cfg.LocalType == "tls" {
|
||||
//decode b
|
||||
rawB, err = goaes.Decrypt(s.UDPKey(), b)
|
||||
if err != nil {
|
||||
s.log.Printf("decrypt udp packet fail from %s", srcAddr.String())
|
||||
return
|
||||
}
|
||||
}
|
||||
p, err := socks.ParseUDPPacket(rawB)
|
||||
s.log.Printf("udp revecived:%v", len(p.Data()))
|
||||
if err != nil {
|
||||
s.log.Printf("parse udp packet fail, ERR:%s", err)
|
||||
return
|
||||
}
|
||||
//防止死循环
|
||||
if s.IsDeadLoop((*localAddr).String(), p.Host()) {
|
||||
s.log.Printf("dead loop detected , %s", p.Host())
|
||||
return
|
||||
}
|
||||
//s.log.Printf("##########udp to -> %s:%s###########", p.Host(), p.Port())
|
||||
if *s.cfg.Parent != "" {
|
||||
//有上级代理,转发给上级
|
||||
if *s.cfg.ParentType == "tls" {
|
||||
//encode b
|
||||
rawB, err = goaes.Encrypt(s.UDPKey(), rawB)
|
||||
if err != nil {
|
||||
s.log.Printf("encrypt udp data fail to %s", *s.cfg.Parent)
|
||||
return
|
||||
}
|
||||
}
|
||||
parent := *s.cfg.UDPParent
|
||||
if parent == "" {
|
||||
parent = *s.cfg.Parent
|
||||
}
|
||||
dstAddr, err := net.ResolveUDPAddr("udp", s.Resolve(parent))
|
||||
if err != nil {
|
||||
s.log.Printf("can't resolve address: %s", err)
|
||||
return
|
||||
}
|
||||
clientSrcAddr := &net.UDPAddr{IP: net.IPv4zero, Port: 0}
|
||||
conn, err := net.DialUDP("udp", clientSrcAddr, dstAddr)
|
||||
if err != nil {
|
||||
s.log.Printf("connect to udp %s fail,ERR:%s", dstAddr.String(), err)
|
||||
return
|
||||
}
|
||||
conn.SetDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout*5)))
|
||||
_, err = conn.Write(rawB)
|
||||
conn.SetDeadline(time.Time{})
|
||||
s.log.Printf("udp request:%v", len(rawB))
|
||||
if err != nil {
|
||||
s.log.Printf("send udp packet to %s fail,ERR:%s", dstAddr.String(), err)
|
||||
conn.Close()
|
||||
return
|
||||
}
|
||||
|
||||
//s.log.Printf("send udp packet to %s success", dstAddr.String())
|
||||
buf := make([]byte, 10*1024)
|
||||
conn.SetDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout)))
|
||||
length, _, err := conn.ReadFromUDP(buf)
|
||||
conn.SetDeadline(time.Time{})
|
||||
if err != nil {
|
||||
s.log.Printf("read udp response from %s fail ,ERR:%s", dstAddr.String(), err)
|
||||
conn.Close()
|
||||
return
|
||||
}
|
||||
respBody := buf[0:length]
|
||||
s.log.Printf("udp response:%v", len(respBody))
|
||||
//s.log.Printf("revecived udp packet from %s", dstAddr.String())
|
||||
if *s.cfg.ParentType == "tls" {
|
||||
//decode b
|
||||
respBody, err = goaes.Decrypt(s.UDPKey(), respBody)
|
||||
if err != nil {
|
||||
s.log.Printf("encrypt udp data fail to %s", *s.cfg.Parent)
|
||||
conn.Close()
|
||||
return
|
||||
}
|
||||
}
|
||||
if *s.cfg.LocalType == "tls" {
|
||||
d, err := goaes.Encrypt(s.UDPKey(), respBody)
|
||||
if err != nil {
|
||||
s.log.Printf("encrypt udp data fail from %s", dstAddr.String())
|
||||
conn.Close()
|
||||
return
|
||||
}
|
||||
s.udpSC.UDPListener.SetDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout)))
|
||||
s.udpSC.UDPListener.WriteToUDP(d, srcAddr)
|
||||
s.udpSC.UDPListener.SetDeadline(time.Time{})
|
||||
s.log.Printf("udp reply:%v", len(d))
|
||||
d = nil
|
||||
} else {
|
||||
s.udpSC.UDPListener.SetDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout)))
|
||||
s.udpSC.UDPListener.WriteToUDP(respBody, srcAddr)
|
||||
s.udpSC.UDPListener.SetDeadline(time.Time{})
|
||||
s.log.Printf("udp reply:%v", len(respBody))
|
||||
}
|
||||
|
||||
} else {
|
||||
//本地代理
|
||||
dstAddr, err := net.ResolveUDPAddr("udp", net.JoinHostPort(s.Resolve(p.Host()), p.Port()))
|
||||
if err != nil {
|
||||
s.log.Printf("can't resolve address: %s", err)
|
||||
return
|
||||
}
|
||||
clientSrcAddr := &net.UDPAddr{IP: net.IPv4zero, Port: 0}
|
||||
conn, err := net.DialUDP("udp", clientSrcAddr, dstAddr)
|
||||
if err != nil {
|
||||
s.log.Printf("connect to udp %s fail,ERR:%s", dstAddr.String(), err)
|
||||
return
|
||||
}
|
||||
conn.SetDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout*3)))
|
||||
_, err = conn.Write(p.Data())
|
||||
conn.SetDeadline(time.Time{})
|
||||
s.log.Printf("udp send:%v", len(p.Data()))
|
||||
if err != nil {
|
||||
s.log.Printf("send udp packet to %s fail,ERR:%s", dstAddr.String(), err)
|
||||
conn.Close()
|
||||
return
|
||||
}
|
||||
//s.log.Printf("send udp packet to %s success", dstAddr.String())
|
||||
buf := make([]byte, 10*1024)
|
||||
conn.SetDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout)))
|
||||
length, _, err := conn.ReadFromUDP(buf)
|
||||
conn.SetDeadline(time.Time{})
|
||||
|
||||
if err != nil {
|
||||
s.log.Printf("read udp response from %s fail ,ERR:%s", dstAddr.String(), err)
|
||||
conn.Close()
|
||||
return
|
||||
}
|
||||
respBody := buf[0:length]
|
||||
//封装来自真实服务器的数据,返回给访问者
|
||||
respPacket := p.NewReply(respBody)
|
||||
//s.log.Printf("revecived udp packet from %s", dstAddr.String())
|
||||
if *s.cfg.LocalType == "tls" {
|
||||
d, err := goaes.Encrypt(s.UDPKey(), respPacket)
|
||||
if err != nil {
|
||||
s.log.Printf("encrypt udp data fail from %s", dstAddr.String())
|
||||
conn.Close()
|
||||
return
|
||||
}
|
||||
s.udpSC.UDPListener.SetDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout)))
|
||||
s.udpSC.UDPListener.WriteToUDP(d, srcAddr)
|
||||
s.udpSC.UDPListener.SetDeadline(time.Time{})
|
||||
d = nil
|
||||
} else {
|
||||
s.udpSC.UDPListener.SetDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout)))
|
||||
s.udpSC.UDPListener.WriteToUDP(respPacket, srcAddr)
|
||||
s.udpSC.UDPListener.SetDeadline(time.Time{})
|
||||
}
|
||||
s.log.Printf("udp reply:%v", len(respPacket))
|
||||
}
|
||||
|
||||
}
|
||||
func (s *Socks) socksConnCallback(inConn net.Conn) {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
@ -438,7 +266,9 @@ func (s *Socks) socksConnCallback(inConn net.Conn) {
|
||||
if err != nil {
|
||||
methodReq.Reply(socks.Method_NONE_ACCEPTABLE)
|
||||
utils.CloseConn(&inConn)
|
||||
s.log.Printf("new methods request fail,ERR: %s", err)
|
||||
if err != io.EOF {
|
||||
s.log.Printf("new methods request fail,ERR: %s", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -526,16 +356,7 @@ func (s *Socks) socksConnCallback(inConn net.Conn) {
|
||||
}
|
||||
|
||||
}
|
||||
func (s *Socks) proxyUDP(inConn *net.Conn, methodReq socks.MethodsRequest, request socks.Request) {
|
||||
if *s.cfg.ParentType == "ssh" {
|
||||
utils.CloseConn(inConn)
|
||||
return
|
||||
}
|
||||
host, _, _ := net.SplitHostPort((*inConn).LocalAddr().String())
|
||||
_, port, _ := net.SplitHostPort(s.udpSC.UDPListener.LocalAddr().String())
|
||||
s.log.Printf("proxy udp on %s", net.JoinHostPort(host, port))
|
||||
request.UDPReply(socks.REP_SUCCESS, net.JoinHostPort(host, port))
|
||||
}
|
||||
|
||||
func (s *Socks) proxyTCP(inConn *net.Conn, methodReq socks.MethodsRequest, request socks.Request) {
|
||||
var outConn net.Conn
|
||||
var err interface{}
|
||||
@ -554,7 +375,7 @@ func (s *Socks) proxyTCP(inConn *net.Conn, methodReq socks.MethodsRequest, reque
|
||||
return
|
||||
}
|
||||
if *s.cfg.Always {
|
||||
outConn, err = s.getOutConn(methodReq.Bytes(), request.Bytes(), request.Addr())
|
||||
outConn, err = s.getOutConn(methodReq.Bytes(), request.Bytes(), request.Addr(), true)
|
||||
} else {
|
||||
if *s.cfg.Parent != "" {
|
||||
host, _, _ := net.SplitHostPort(request.Addr())
|
||||
@ -562,12 +383,14 @@ func (s *Socks) proxyTCP(inConn *net.Conn, methodReq socks.MethodsRequest, reque
|
||||
if utils.IsIternalIP(host, *s.cfg.Always) {
|
||||
useProxy = false
|
||||
} else {
|
||||
k := s.Resolve(request.Addr())
|
||||
s.checker.Add(request.Addr(), k)
|
||||
useProxy, _, _ = s.checker.IsBlocked(k)
|
||||
var isInMap bool
|
||||
useProxy, isInMap, _, _ = s.checker.IsBlocked(request.Addr())
|
||||
if !isInMap {
|
||||
s.checker.Add(request.Addr(), s.Resolve(request.Addr()))
|
||||
}
|
||||
}
|
||||
if useProxy {
|
||||
outConn, err = s.getOutConn(methodReq.Bytes(), request.Bytes(), request.Addr())
|
||||
outConn, err = s.getOutConn(methodReq.Bytes(), request.Bytes(), request.Addr(), true)
|
||||
} else {
|
||||
outConn, err = utils.ConnectHost(s.Resolve(request.Addr()), *s.cfg.Timeout)
|
||||
}
|
||||
@ -607,7 +430,7 @@ func (s *Socks) proxyTCP(inConn *net.Conn, methodReq socks.MethodsRequest, reque
|
||||
}
|
||||
s.userConns.Set(inAddr, inConn)
|
||||
}
|
||||
func (s *Socks) getOutConn(methodBytes, reqBytes []byte, host string) (outConn net.Conn, err interface{}) {
|
||||
func (s *Socks) getOutConn(methodBytes, reqBytes []byte, host string, handshake bool) (outConn net.Conn, err interface{}) {
|
||||
switch *s.cfg.ParentType {
|
||||
case "kcp":
|
||||
fallthrough
|
||||
@ -635,6 +458,9 @@ func (s *Socks) getOutConn(methodBytes, reqBytes []byte, host string) (outConn n
|
||||
Password: *s.cfg.ParentKey,
|
||||
})
|
||||
}
|
||||
if !handshake {
|
||||
return
|
||||
}
|
||||
var buf = make([]byte, 1024)
|
||||
//var n int
|
||||
outConn.SetDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout)))
|
||||
@ -804,6 +630,7 @@ func (s *Socks) Resolve(address string) string {
|
||||
ip, err := s.domainResolver.Resolve(address)
|
||||
if err != nil {
|
||||
s.log.Printf("dns error %s , ERR:%s", address, err)
|
||||
return address
|
||||
}
|
||||
return ip
|
||||
}
|
||||
|
||||
321
services/socks/udp.go
Normal file
321
services/socks/udp.go
Normal file
@ -0,0 +1,321 @@
|
||||
package socks
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"net"
|
||||
"runtime/debug"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/snail007/goproxy/utils"
|
||||
goaes "github.com/snail007/goproxy/utils/aes"
|
||||
"github.com/snail007/goproxy/utils/socks"
|
||||
)
|
||||
|
||||
func (s *Socks) ParentUDPKey() (key []byte) {
|
||||
switch *s.cfg.ParentType {
|
||||
case "tcp":
|
||||
if *s.cfg.ParentKey != "" {
|
||||
v := fmt.Sprintf("%x", md5.Sum([]byte(*s.cfg.ParentKey)))
|
||||
return []byte(v)[:24]
|
||||
}
|
||||
case "tls":
|
||||
return s.cfg.KeyBytes[:24]
|
||||
case "kcp":
|
||||
v := fmt.Sprintf("%x", md5.Sum([]byte(*s.cfg.KCP.Key)))
|
||||
return []byte(v)[:24]
|
||||
}
|
||||
return
|
||||
}
|
||||
func (s *Socks) LocalUDPKey() (key []byte) {
|
||||
switch *s.cfg.LocalType {
|
||||
case "tcp":
|
||||
if *s.cfg.LocalKey != "" {
|
||||
v := fmt.Sprintf("%x", md5.Sum([]byte(*s.cfg.LocalKey)))
|
||||
return []byte(v)[:24]
|
||||
}
|
||||
case "tls":
|
||||
return s.cfg.KeyBytes[:24]
|
||||
case "kcp":
|
||||
v := fmt.Sprintf("%x", md5.Sum([]byte(*s.cfg.KCP.Key)))
|
||||
return []byte(v)[:24]
|
||||
}
|
||||
return
|
||||
}
|
||||
func (s *Socks) proxyUDP(inConn *net.Conn, methodReq socks.MethodsRequest, request socks.Request) {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
s.log.Printf("udp local->out io copy crashed:\n%s\n%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
if *s.cfg.ParentType == "ssh" {
|
||||
utils.CloseConn(inConn)
|
||||
return
|
||||
}
|
||||
srcIP, _, _ := net.SplitHostPort((*inConn).RemoteAddr().String())
|
||||
inconnRemoteAddr := (*inConn).RemoteAddr().String()
|
||||
localAddr := &net.UDPAddr{IP: net.IPv4zero, Port: 0}
|
||||
udpListener, err := net.ListenUDP("udp", localAddr)
|
||||
if err != nil {
|
||||
(*inConn).Close()
|
||||
udpListener.Close()
|
||||
s.log.Printf("udp bind fail , %s", err)
|
||||
return
|
||||
}
|
||||
host, _, _ := net.SplitHostPort((*inConn).LocalAddr().String())
|
||||
_, port, _ := net.SplitHostPort(udpListener.LocalAddr().String())
|
||||
if len(*s.cfg.LocalIPS) > 0 {
|
||||
host = (*s.cfg.LocalIPS)[0]
|
||||
}
|
||||
s.log.Printf("proxy udp on %s , for %s", net.JoinHostPort(host, port), inconnRemoteAddr)
|
||||
request.UDPReply(socks.REP_SUCCESS, net.JoinHostPort(host, port))
|
||||
s.userConns.Set(inconnRemoteAddr, inConn)
|
||||
var (
|
||||
outUDPConn *net.UDPConn
|
||||
outconn net.Conn
|
||||
outconnLocalAddr string
|
||||
isClosedErr = func(err error) bool {
|
||||
return err != nil && strings.Contains(err.Error(), "use of closed network connection")
|
||||
}
|
||||
destAddr *net.UDPAddr
|
||||
)
|
||||
var clean = func(msg, err string) {
|
||||
raddr := ""
|
||||
if outUDPConn != nil {
|
||||
raddr = outUDPConn.RemoteAddr().String()
|
||||
outUDPConn.Close()
|
||||
}
|
||||
if msg != "" {
|
||||
if raddr != "" {
|
||||
s.log.Printf("%s , %s , %s -> %s", msg, err, inconnRemoteAddr, raddr)
|
||||
} else {
|
||||
s.log.Printf("%s , %s , from : %s", msg, err, inconnRemoteAddr)
|
||||
}
|
||||
}
|
||||
(*inConn).Close()
|
||||
udpListener.Close()
|
||||
s.userConns.Remove(inconnRemoteAddr)
|
||||
if outconn != nil {
|
||||
outconn.Close()
|
||||
}
|
||||
if outconnLocalAddr != "" {
|
||||
s.userConns.Remove(outconnLocalAddr)
|
||||
}
|
||||
}
|
||||
defer clean("", "")
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
s.log.Printf("udp related client tcp conn read crashed:\n%s\n%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
buf := make([]byte, 1)
|
||||
(*inConn).SetReadDeadline(time.Time{})
|
||||
if _, err := (*inConn).Read(buf); err != nil {
|
||||
clean("udp related tcp conn disconnected with read", err.Error())
|
||||
}
|
||||
}()
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
s.log.Printf("udp related client tcp conn write crashed:\n%s\n%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
for {
|
||||
(*inConn).SetWriteDeadline(time.Now().Add(time.Second * 5))
|
||||
if _, err := (*inConn).Write([]byte{0x00}); err != nil {
|
||||
clean("udp related tcp conn disconnected with write", err.Error())
|
||||
return
|
||||
}
|
||||
(*inConn).SetWriteDeadline(time.Time{})
|
||||
time.Sleep(time.Second * 5)
|
||||
}
|
||||
}()
|
||||
useProxy := true
|
||||
if *s.cfg.Parent != "" {
|
||||
dstHost, _, _ := net.SplitHostPort(request.Addr())
|
||||
if utils.IsIternalIP(dstHost, *s.cfg.Always) {
|
||||
useProxy = false
|
||||
} else {
|
||||
var isInMap bool
|
||||
useProxy, isInMap, _, _ = s.checker.IsBlocked(request.Addr())
|
||||
if !isInMap {
|
||||
s.checker.Add(request.Addr(), s.Resolve(request.Addr()))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
useProxy = false
|
||||
}
|
||||
if useProxy {
|
||||
//parent proxy
|
||||
outconn, err := s.getOutConn(nil, nil, "", false)
|
||||
if err != nil {
|
||||
clean("connnect fail", fmt.Sprintf("%s", err))
|
||||
return
|
||||
}
|
||||
client := socks.NewClientConn(&outconn, "udp", request.Addr(), time.Millisecond*time.Duration(*s.cfg.Timeout), nil, nil)
|
||||
if err = client.Handshake(); err != nil {
|
||||
clean("handshake fail", fmt.Sprintf("%s", err))
|
||||
return
|
||||
}
|
||||
//outconnRemoteAddr := outconn.RemoteAddr().String()
|
||||
outconnLocalAddr = outconn.LocalAddr().String()
|
||||
s.userConns.Set(outconnLocalAddr, &outconn)
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
s.log.Printf("udp related parent tcp conn read crashed:\n%s\n%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
buf := make([]byte, 1)
|
||||
outconn.SetReadDeadline(time.Time{})
|
||||
if _, err := outconn.Read(buf); err != nil {
|
||||
clean("udp parent tcp conn disconnected", fmt.Sprintf("%s", err))
|
||||
}
|
||||
}()
|
||||
//forward to parent udp
|
||||
//s.log.Printf("parent udp address %s", client.UDPAddr)
|
||||
destAddr, _ = net.ResolveUDPAddr("udp", client.UDPAddr)
|
||||
}
|
||||
s.log.Printf("use proxy %v : udp %s", useProxy, request.Addr())
|
||||
//relay
|
||||
for {
|
||||
buf := utils.LeakyBuffer.Get()
|
||||
defer utils.LeakyBuffer.Put(buf)
|
||||
n, srcAddr, err := udpListener.ReadFromUDP(buf)
|
||||
if err != nil {
|
||||
s.log.Printf("udp listener read fail, %s", err.Error())
|
||||
if isClosedErr(err) {
|
||||
return
|
||||
}
|
||||
continue
|
||||
}
|
||||
srcIP0, _, _ := net.SplitHostPort(srcAddr.String())
|
||||
//IP not match drop it
|
||||
if srcIP != srcIP0 {
|
||||
continue
|
||||
}
|
||||
p := socks.NewPacketUDP()
|
||||
//convert data to raw
|
||||
if len(s.udpLocalKey) > 0 {
|
||||
var v []byte
|
||||
v, err = goaes.Decrypt(s.udpLocalKey, buf[:n])
|
||||
if err == nil {
|
||||
err = p.Parse(v)
|
||||
}
|
||||
} else {
|
||||
err = p.Parse(buf[:n])
|
||||
}
|
||||
//err = p.Parse(buf[:n])
|
||||
if err != nil {
|
||||
s.log.Printf("udp listener parse packet fail, %s", err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
port, _ := strconv.Atoi(p.Port())
|
||||
|
||||
if v, ok := s.udpRelatedPacketConns.Get(srcAddr.String()); !ok {
|
||||
if destAddr == nil {
|
||||
destAddr = &net.UDPAddr{IP: net.ParseIP(p.Host()), Port: port}
|
||||
}
|
||||
outUDPConn, err = net.DialUDP("udp", localAddr, destAddr)
|
||||
if err != nil {
|
||||
s.log.Printf("create out udp conn fail , %s , from : %s", err, srcAddr)
|
||||
continue
|
||||
}
|
||||
s.udpRelatedPacketConns.Set(srcAddr.String(), outUDPConn)
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
s.log.Printf("udp out->local io copy crashed:\n%s\n%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
defer s.udpRelatedPacketConns.Remove(srcAddr.String())
|
||||
//out->local io copy
|
||||
buf := utils.LeakyBuffer.Get()
|
||||
defer utils.LeakyBuffer.Put(buf)
|
||||
for {
|
||||
n, err := outUDPConn.Read(buf)
|
||||
if err != nil {
|
||||
s.log.Printf("read out udp data fail , %s , from : %s", err, srcAddr)
|
||||
if isClosedErr(err) {
|
||||
return
|
||||
}
|
||||
continue
|
||||
}
|
||||
//var dlen = n
|
||||
if useProxy {
|
||||
//forward to local
|
||||
var v []byte
|
||||
//convert parent data to raw
|
||||
if len(s.udpParentKey) > 0 {
|
||||
v, err = goaes.Decrypt(s.udpParentKey, buf[:n])
|
||||
if err != nil {
|
||||
s.log.Printf("udp outconn parse packet fail, %s", err.Error())
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
v = buf[:n]
|
||||
}
|
||||
//now v is raw, try convert v to local
|
||||
if len(s.udpLocalKey) > 0 {
|
||||
v, _ = goaes.Encrypt(s.udpLocalKey, v)
|
||||
}
|
||||
_, err = udpListener.WriteTo(v, srcAddr)
|
||||
// _, err = udpListener.WriteTo(buf[:n], srcAddr)
|
||||
} else {
|
||||
rp := socks.NewPacketUDP()
|
||||
rp.Build(destAddr.String(), buf[:n])
|
||||
v := rp.Bytes()
|
||||
//dlen = len(v)
|
||||
//rp.Bytes() v is raw, try convert to local
|
||||
if len(s.udpLocalKey) > 0 {
|
||||
v, _ = goaes.Encrypt(s.udpLocalKey, v)
|
||||
}
|
||||
_, err = udpListener.WriteTo(v, srcAddr)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
s.udpRelatedPacketConns.Remove(srcAddr.String())
|
||||
s.log.Printf("write out data to local fail , %s , from : %s", err, srcAddr)
|
||||
if isClosedErr(err) {
|
||||
return
|
||||
}
|
||||
continue
|
||||
} else {
|
||||
//s.log.Printf("send udp data to local success , len %d, for : %s", dlen, srcAddr)
|
||||
}
|
||||
}
|
||||
}()
|
||||
} else {
|
||||
outUDPConn = v.(*net.UDPConn)
|
||||
}
|
||||
//local->out io copy
|
||||
if useProxy {
|
||||
//forward to parent
|
||||
//p is raw, now convert it to parent
|
||||
var v []byte
|
||||
if len(s.udpParentKey) > 0 {
|
||||
v, _ = goaes.Encrypt(s.udpParentKey, p.Bytes())
|
||||
} else {
|
||||
v = p.Bytes()
|
||||
}
|
||||
_, err = outUDPConn.Write(v)
|
||||
// _, err = outUDPConn.Write(p.Bytes())
|
||||
} else {
|
||||
_, err = outUDPConn.Write(p.Data())
|
||||
}
|
||||
if err != nil {
|
||||
if isClosedErr(err) {
|
||||
return
|
||||
}
|
||||
s.log.Printf("send out udp data fail , %s , from : %s", err, srcAddr)
|
||||
continue
|
||||
} else {
|
||||
//s.log.Printf("send udp data to remote success , len %d, for : %s", len(p.Data()), srcAddr)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
306
services/sps/socksudp.go
Normal file
306
services/sps/socksudp.go
Normal file
@ -0,0 +1,306 @@
|
||||
package sps
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"net"
|
||||
"runtime/debug"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/snail007/goproxy/utils"
|
||||
goaes "github.com/snail007/goproxy/utils/aes"
|
||||
"github.com/snail007/goproxy/utils/conncrypt"
|
||||
"github.com/snail007/goproxy/utils/socks"
|
||||
)
|
||||
|
||||
func (s *SPS) ParentUDPKey() (key []byte) {
|
||||
switch *s.cfg.ParentType {
|
||||
case "tcp":
|
||||
if *s.cfg.ParentKey != "" {
|
||||
v := fmt.Sprintf("%x", md5.Sum([]byte(*s.cfg.ParentKey)))
|
||||
return []byte(v)[:24]
|
||||
}
|
||||
case "tls":
|
||||
return s.cfg.KeyBytes[:24]
|
||||
case "kcp":
|
||||
v := fmt.Sprintf("%x", md5.Sum([]byte(*s.cfg.KCP.Key)))
|
||||
return []byte(v)[:24]
|
||||
}
|
||||
return
|
||||
}
|
||||
func (s *SPS) LocalUDPKey() (key []byte) {
|
||||
switch *s.cfg.LocalType {
|
||||
case "tcp":
|
||||
if *s.cfg.LocalKey != "" {
|
||||
v := fmt.Sprintf("%x", md5.Sum([]byte(*s.cfg.LocalKey)))
|
||||
return []byte(v)[:24]
|
||||
}
|
||||
case "tls":
|
||||
return s.cfg.KeyBytes[:24]
|
||||
case "kcp":
|
||||
v := fmt.Sprintf("%x", md5.Sum([]byte(*s.cfg.KCP.Key)))
|
||||
return []byte(v)[:24]
|
||||
}
|
||||
return
|
||||
}
|
||||
func (s *SPS) proxyUDP(inConn *net.Conn, serverConn *socks.ServerConn) {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
s.log.Printf("udp local->out io copy crashed:\n%s\n%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
if *s.cfg.ParentType == "ssh" {
|
||||
utils.CloseConn(inConn)
|
||||
return
|
||||
}
|
||||
srcIP, _, _ := net.SplitHostPort((*inConn).RemoteAddr().String())
|
||||
inconnRemoteAddr := (*inConn).RemoteAddr().String()
|
||||
localAddr := &net.UDPAddr{IP: net.IPv4zero, Port: 0}
|
||||
udpListener := serverConn.UDPConnListener
|
||||
s.log.Printf("proxy udp on %s , for %s", udpListener.LocalAddr(), inconnRemoteAddr)
|
||||
s.userConns.Set(inconnRemoteAddr, inConn)
|
||||
var (
|
||||
outUDPConn *net.UDPConn
|
||||
outconn net.Conn
|
||||
outconnLocalAddr string
|
||||
isClosedErr = func(err error) bool {
|
||||
return err != nil && strings.Contains(err.Error(), "use of closed network connection")
|
||||
}
|
||||
destAddr *net.UDPAddr
|
||||
)
|
||||
var clean = func(msg, err string) {
|
||||
raddr := ""
|
||||
if outUDPConn != nil {
|
||||
raddr = outUDPConn.RemoteAddr().String()
|
||||
outUDPConn.Close()
|
||||
}
|
||||
if msg != "" {
|
||||
if raddr != "" {
|
||||
s.log.Printf("%s , %s , %s -> %s", msg, err, inconnRemoteAddr, raddr)
|
||||
} else {
|
||||
s.log.Printf("%s , %s , from : %s", msg, err, inconnRemoteAddr)
|
||||
}
|
||||
}
|
||||
(*inConn).Close()
|
||||
udpListener.Close()
|
||||
s.userConns.Remove(inconnRemoteAddr)
|
||||
if outconn != nil {
|
||||
outconn.Close()
|
||||
}
|
||||
if outconnLocalAddr != "" {
|
||||
s.userConns.Remove(outconnLocalAddr)
|
||||
}
|
||||
}
|
||||
defer clean("", "")
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
s.log.Printf("udp related client tcp conn read crashed:\n%s\n%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
buf := make([]byte, 1)
|
||||
(*inConn).SetReadDeadline(time.Time{})
|
||||
if _, err := (*inConn).Read(buf); err != nil {
|
||||
clean("udp related tcp conn disconnected with read", err.Error())
|
||||
}
|
||||
}()
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
s.log.Printf("udp related client tcp conn write crashed:\n%s\n%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
for {
|
||||
(*inConn).SetWriteDeadline(time.Now().Add(time.Second * 5))
|
||||
if _, err := (*inConn).Write([]byte{0x00}); err != nil {
|
||||
clean("udp related tcp conn disconnected with write", err.Error())
|
||||
return
|
||||
}
|
||||
(*inConn).SetWriteDeadline(time.Time{})
|
||||
time.Sleep(time.Second * 5)
|
||||
}
|
||||
}()
|
||||
//parent proxy
|
||||
outconn, err := s.outPool.Get()
|
||||
//outconn, err := s.GetParentConn(nil, nil, "", false)
|
||||
if err != nil {
|
||||
clean("connnect fail", fmt.Sprintf("%s", err))
|
||||
return
|
||||
}
|
||||
if *s.cfg.ParentCompress {
|
||||
outconn = utils.NewCompConn(outconn)
|
||||
}
|
||||
if *s.cfg.ParentKey != "" {
|
||||
outconn = conncrypt.New(outconn, &conncrypt.Config{
|
||||
Password: *s.cfg.ParentKey,
|
||||
})
|
||||
}
|
||||
|
||||
s.log.Printf("connect %s for udp", serverConn.Target())
|
||||
//socks client
|
||||
var client *socks.ClientConn
|
||||
auth := serverConn.AuthData()
|
||||
if *s.cfg.ParentAuth != "" {
|
||||
a := strings.Split(*s.cfg.ParentAuth, ":")
|
||||
if len(a) != 2 {
|
||||
err = fmt.Errorf("parent auth data format error")
|
||||
return
|
||||
}
|
||||
client = socks.NewClientConn(&outconn, "udp", serverConn.Target(), time.Millisecond*time.Duration(*s.cfg.Timeout), &socks.Auth{User: a[0], Password: a[1]}, nil)
|
||||
} else {
|
||||
if !s.IsBasicAuth() && auth.Password != "" && auth.User != "" {
|
||||
client = socks.NewClientConn(&outconn, "udp", serverConn.Target(), time.Millisecond*time.Duration(*s.cfg.Timeout), &auth, nil)
|
||||
} else {
|
||||
client = socks.NewClientConn(&outconn, "udp", serverConn.Target(), time.Millisecond*time.Duration(*s.cfg.Timeout), nil, nil)
|
||||
}
|
||||
}
|
||||
|
||||
if err = client.Handshake(); err != nil {
|
||||
clean("handshake fail", fmt.Sprintf("%s", err))
|
||||
return
|
||||
}
|
||||
|
||||
//outconnRemoteAddr := outconn.RemoteAddr().String()
|
||||
outconnLocalAddr = outconn.LocalAddr().String()
|
||||
s.userConns.Set(outconnLocalAddr, &outconn)
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
s.log.Printf("udp related parent tcp conn read crashed:\n%s\n%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
buf := make([]byte, 1)
|
||||
outconn.SetReadDeadline(time.Time{})
|
||||
if _, err := outconn.Read(buf); err != nil {
|
||||
clean("udp parent tcp conn disconnected", fmt.Sprintf("%s", err))
|
||||
}
|
||||
}()
|
||||
//forward to parent udp
|
||||
//s.log.Printf("parent udp address %s", client.UDPAddr)
|
||||
destAddr, _ = net.ResolveUDPAddr("udp", client.UDPAddr)
|
||||
//relay
|
||||
buf := utils.LeakyBuffer.Get()
|
||||
defer utils.LeakyBuffer.Put(buf)
|
||||
for {
|
||||
n, srcAddr, err := udpListener.ReadFromUDP(buf)
|
||||
if err != nil {
|
||||
s.log.Printf("udp listener read fail, %s", err.Error())
|
||||
if isClosedErr(err) {
|
||||
return
|
||||
}
|
||||
continue
|
||||
}
|
||||
srcIP0, _, _ := net.SplitHostPort(srcAddr.String())
|
||||
//IP not match drop it
|
||||
if srcIP != srcIP0 {
|
||||
continue
|
||||
}
|
||||
p := socks.NewPacketUDP()
|
||||
//convert data to raw
|
||||
if len(s.udpLocalKey) > 0 {
|
||||
var v []byte
|
||||
v, err = goaes.Decrypt(s.udpLocalKey, buf[:n])
|
||||
if err == nil {
|
||||
err = p.Parse(v)
|
||||
}
|
||||
} else {
|
||||
err = p.Parse(buf[:n])
|
||||
}
|
||||
if err != nil {
|
||||
s.log.Printf("udp listener parse packet fail, %s", err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
port, _ := strconv.Atoi(p.Port())
|
||||
|
||||
if v, ok := s.udpRelatedPacketConns.Get(srcAddr.String()); !ok {
|
||||
if destAddr == nil {
|
||||
destAddr = &net.UDPAddr{IP: net.ParseIP(p.Host()), Port: port}
|
||||
}
|
||||
outUDPConn, err = net.DialUDP("udp", localAddr, destAddr)
|
||||
if err != nil {
|
||||
s.log.Printf("create out udp conn fail , %s , from : %s", err, srcAddr)
|
||||
continue
|
||||
}
|
||||
s.udpRelatedPacketConns.Set(srcAddr.String(), outUDPConn)
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
s.log.Printf("udp out->local io copy crashed:\n%s\n%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
defer s.udpRelatedPacketConns.Remove(srcAddr.String())
|
||||
//out->local io copy
|
||||
buf := utils.LeakyBuffer.Get()
|
||||
defer utils.LeakyBuffer.Put(buf)
|
||||
for {
|
||||
outUDPConn.SetReadDeadline(time.Now().Add(time.Second * 5))
|
||||
n, err := outUDPConn.Read(buf)
|
||||
outUDPConn.SetReadDeadline(time.Time{})
|
||||
if err != nil {
|
||||
s.log.Printf("read out udp data fail , %s , from : %s", err, srcAddr)
|
||||
if isClosedErr(err) {
|
||||
return
|
||||
}
|
||||
continue
|
||||
}
|
||||
//var dlen = n
|
||||
//forward to local
|
||||
var v []byte
|
||||
//convert parent data to raw
|
||||
if len(s.udpParentKey) > 0 {
|
||||
v, err = goaes.Decrypt(s.udpParentKey, buf[:n])
|
||||
if err != nil {
|
||||
s.log.Printf("udp outconn parse packet fail, %s", err.Error())
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
v = buf[:n]
|
||||
}
|
||||
//now v is raw, try convert v to local
|
||||
if len(s.udpLocalKey) > 0 {
|
||||
v, _ = goaes.Encrypt(s.udpLocalKey, v)
|
||||
}
|
||||
_, err = udpListener.WriteTo(v, srcAddr)
|
||||
// _, err = udpListener.WriteTo(buf[:n], srcAddr)
|
||||
|
||||
if err != nil {
|
||||
s.udpRelatedPacketConns.Remove(srcAddr.String())
|
||||
s.log.Printf("write out data to local fail , %s , from : %s", err, srcAddr)
|
||||
if isClosedErr(err) {
|
||||
return
|
||||
}
|
||||
continue
|
||||
} else {
|
||||
//s.log.Printf("send udp data to local success , len %d, for : %s", dlen, srcAddr)
|
||||
}
|
||||
}
|
||||
}()
|
||||
} else {
|
||||
outUDPConn = v.(*net.UDPConn)
|
||||
}
|
||||
//local->out io copy
|
||||
//forward to parent
|
||||
//p is raw, now convert it to parent
|
||||
var v []byte
|
||||
if len(s.udpParentKey) > 0 {
|
||||
v, _ = goaes.Encrypt(s.udpParentKey, p.Bytes())
|
||||
} else {
|
||||
v = p.Bytes()
|
||||
}
|
||||
_, err = outUDPConn.Write(v)
|
||||
// _, err = outUDPConn.Write(p.Bytes())
|
||||
if err != nil {
|
||||
if isClosedErr(err) {
|
||||
return
|
||||
}
|
||||
s.log.Printf("send out udp data fail , %s , from : %s", err, srcAddr)
|
||||
continue
|
||||
} else {
|
||||
//s.log.Printf("send udp data to remote success , len %d, for : %s", len(p.Data()), srcAddr)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -17,6 +17,7 @@ import (
|
||||
"github.com/snail007/goproxy/services/kcpcfg"
|
||||
"github.com/snail007/goproxy/utils"
|
||||
"github.com/snail007/goproxy/utils/conncrypt"
|
||||
"github.com/snail007/goproxy/utils/sni"
|
||||
"github.com/snail007/goproxy/utils/socks"
|
||||
)
|
||||
|
||||
@ -52,22 +53,26 @@ type SPSArgs struct {
|
||||
DisableSocks5 *bool
|
||||
}
|
||||
type SPS struct {
|
||||
outPool utils.OutConn
|
||||
cfg SPSArgs
|
||||
domainResolver utils.DomainResolver
|
||||
basicAuth utils.BasicAuth
|
||||
serverChannels []*utils.ServerChannel
|
||||
userConns utils.ConcurrentMap
|
||||
log *logger.Logger
|
||||
outPool utils.OutConn
|
||||
cfg SPSArgs
|
||||
domainResolver utils.DomainResolver
|
||||
basicAuth utils.BasicAuth
|
||||
serverChannels []*utils.ServerChannel
|
||||
userConns utils.ConcurrentMap
|
||||
log *logger.Logger
|
||||
udpRelatedPacketConns utils.ConcurrentMap
|
||||
udpLocalKey []byte
|
||||
udpParentKey []byte
|
||||
}
|
||||
|
||||
func NewSPS() services.Service {
|
||||
return &SPS{
|
||||
outPool: utils.OutConn{},
|
||||
cfg: SPSArgs{},
|
||||
basicAuth: utils.BasicAuth{},
|
||||
serverChannels: []*utils.ServerChannel{},
|
||||
userConns: utils.NewConcurrentMap(),
|
||||
outPool: utils.OutConn{},
|
||||
cfg: SPSArgs{},
|
||||
basicAuth: utils.BasicAuth{},
|
||||
serverChannels: []*utils.ServerChannel{},
|
||||
userConns: utils.NewConcurrentMap(),
|
||||
udpRelatedPacketConns: utils.NewConcurrentMap(),
|
||||
}
|
||||
}
|
||||
func (s *SPS) CheckArgs() (err error) {
|
||||
@ -92,6 +97,8 @@ func (s *SPS) CheckArgs() (err error) {
|
||||
}
|
||||
}
|
||||
}
|
||||
s.udpLocalKey = s.LocalUDPKey()
|
||||
s.udpParentKey = s.ParentUDPKey()
|
||||
return
|
||||
}
|
||||
func (s *SPS) InitService() (err error) {
|
||||
@ -209,6 +216,11 @@ func (s *SPS) callback(inConn net.Conn) {
|
||||
}
|
||||
}
|
||||
func (s *SPS) OutToTCP(inConn *net.Conn) (err error) {
|
||||
enableUDP := *s.cfg.ParentServiceType == "socks"
|
||||
udpIP, _, _ := net.SplitHostPort((*inConn).LocalAddr().String())
|
||||
if len(*s.cfg.LocalIPS) > 0 {
|
||||
udpIP = (*s.cfg.LocalIPS)[0]
|
||||
}
|
||||
bInConn := utils.NewBufferedConn(*inConn)
|
||||
//important
|
||||
//action read will regist read event to system,
|
||||
@ -218,7 +230,7 @@ func (s *SPS) OutToTCP(inConn *net.Conn) (err error) {
|
||||
bInConn.ReadByte()
|
||||
bInConn.UnreadByte()
|
||||
|
||||
n := 8
|
||||
n := 2048
|
||||
if n > bInConn.Buffered() {
|
||||
n = bInConn.Buffered()
|
||||
}
|
||||
@ -228,12 +240,12 @@ func (s *SPS) OutToTCP(inConn *net.Conn) (err error) {
|
||||
(*inConn).Close()
|
||||
return
|
||||
}
|
||||
|
||||
isSNI, _ := sni.ServerNameFromBytes(h)
|
||||
*inConn = bInConn
|
||||
address := ""
|
||||
var auth socks.Auth
|
||||
var forwardBytes []byte
|
||||
//fmt.Printf("%v", header)
|
||||
//fmt.Printf("%v", h)
|
||||
if utils.IsSocks5(h) {
|
||||
if *s.cfg.DisableSocks5 {
|
||||
(*inConn).Close()
|
||||
@ -242,16 +254,20 @@ func (s *SPS) OutToTCP(inConn *net.Conn) (err error) {
|
||||
//socks5 server
|
||||
var serverConn *socks.ServerConn
|
||||
if s.IsBasicAuth() {
|
||||
serverConn = socks.NewServerConn(inConn, time.Millisecond*time.Duration(*s.cfg.Timeout), &s.basicAuth, "", nil)
|
||||
serverConn = socks.NewServerConn(inConn, time.Millisecond*time.Duration(*s.cfg.Timeout), &s.basicAuth, enableUDP, udpIP, nil)
|
||||
} else {
|
||||
serverConn = socks.NewServerConn(inConn, time.Millisecond*time.Duration(*s.cfg.Timeout), nil, "", nil)
|
||||
serverConn = socks.NewServerConn(inConn, time.Millisecond*time.Duration(*s.cfg.Timeout), nil, enableUDP, udpIP, nil)
|
||||
}
|
||||
if err = serverConn.Handshake(); err != nil {
|
||||
return
|
||||
}
|
||||
address = serverConn.Target()
|
||||
auth = serverConn.AuthData()
|
||||
} else if utils.IsHTTP(h) {
|
||||
if serverConn.IsUDP() {
|
||||
s.proxyUDP(inConn, serverConn)
|
||||
return
|
||||
}
|
||||
} else if utils.IsHTTP(h) || isSNI != "" {
|
||||
if *s.cfg.DisableHTTP {
|
||||
(*inConn).Close()
|
||||
return
|
||||
@ -495,6 +511,7 @@ func (s *SPS) Resolve(address string) string {
|
||||
ip, err := s.domainResolver.Resolve(address)
|
||||
if err != nil {
|
||||
s.log.Printf("dns error %s , ERR:%s", address, err)
|
||||
return address
|
||||
}
|
||||
return ip
|
||||
}
|
||||
|
||||
@ -73,7 +73,7 @@ func CreateSignCert(rootCa *x509.Certificate, rootKey *rsa.PrivateKey, domainOrI
|
||||
|
||||
buf := x509.MarshalPKCS1PrivateKey(priKey)
|
||||
keyPem := &pem.Block{
|
||||
Type: "PRIVATE KEY",
|
||||
Type: "RSA PRIVATE KEY",
|
||||
Bytes: buf,
|
||||
}
|
||||
keyBytes = pem.EncodeToMemory(keyPem)
|
||||
@ -109,7 +109,7 @@ func CreateCa(organization string, expireDays int) (certBytes []byte, keyBytes [
|
||||
NotAfter: time.Now().Add(time.Hour * 24 * time.Duration(expireDays)),
|
||||
|
||||
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
|
||||
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
|
||||
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
|
||||
BasicConstraintsValid: true,
|
||||
IsCA: true,
|
||||
}
|
||||
|
||||
@ -12,8 +12,8 @@ import (
|
||||
)
|
||||
|
||||
//Confg defaults
|
||||
const DefaultIterations = 2048
|
||||
const DefaultKeySize = 32 //256bits
|
||||
const DefaultIterations = 1024
|
||||
const DefaultKeySize = 24 //256bits
|
||||
var DefaultHashFunc = sha256.New
|
||||
var DefaultSalt = []byte(`
|
||||
(;QUHj.BQ?RXzYSO]ifkXp/G!kFmWyXyEV6Nt!d|@bo+N$L9+<d$|g6e26T}
|
||||
|
||||
@ -17,7 +17,6 @@ import (
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
"github.com/snail007/goproxy/services/kcpcfg"
|
||||
|
||||
@ -209,98 +208,6 @@ func CloseConn(conn *net.Conn) {
|
||||
(*conn).Close()
|
||||
}
|
||||
}
|
||||
func Keygen() (err error) {
|
||||
CList := []string{"AD", "AE", "AF", "AG", "AI", "AL", "AM", "AO", "AR", "AT", "AU", "AZ", "BB", "BD", "BE", "BF", "BG", "BH", "BI", "BJ", "BL", "BM", "BN", "BO", "BR", "BS", "BW", "BY", "BZ", "CA", "CF", "CG", "CH", "CK", "CL", "CM", "CN", "CO", "CR", "CS", "CU", "CY", "CZ", "DE", "DJ", "DK", "DO", "DZ", "EC", "EE", "EG", "ES", "ET", "FI", "FJ", "FR", "GA", "GB", "GD", "GE", "GF", "GH", "GI", "GM", "GN", "GR", "GT", "GU", "GY", "HK", "HN", "HT", "HU", "ID", "IE", "IL", "IN", "IQ", "IR", "IS", "IT", "JM", "JO", "JP", "KE", "KG", "KH", "KP", "KR", "KT", "KW", "KZ", "LA", "LB", "LC", "LI", "LK", "LR", "LS", "LT", "LU", "LV", "LY", "MA", "MC", "MD", "MG", "ML", "MM", "MN", "MO", "MS", "MT", "MU", "MV", "MW", "MX", "MY", "MZ", "NA", "NE", "NG", "NI", "NL", "NO", "NP", "NR", "NZ", "OM", "PA", "PE", "PF", "PG", "PH", "PK", "PL", "PR", "PT", "PY", "QA", "RO", "RU", "SA", "SB", "SC", "SD", "SE", "SG", "SI", "SK", "SL", "SM", "SN", "SO", "SR", "ST", "SV", "SY", "SZ", "TD", "TG", "TH", "TJ", "TM", "TN", "TO", "TR", "TT", "TW", "TZ", "UA", "UG", "US", "UY", "UZ", "VC", "VE", "VN", "YE", "YU", "ZA", "ZM", "ZR", "ZW"}
|
||||
domainSubfixList := []string{".com", ".edu", ".gov", ".int", ".mil", ".net", ".org", ".biz", ".info", ".pro", ".name", ".museum", ".coop", ".aero", ".xxx", ".idv", ".ac", ".ad", ".ae", ".af", ".ag", ".ai", ".al", ".am", ".an", ".ao", ".aq", ".ar", ".as", ".at", ".au", ".aw", ".az", ".ba", ".bb", ".bd", ".be", ".bf", ".bg", ".bh", ".bi", ".bj", ".bm", ".bn", ".bo", ".br", ".bs", ".bt", ".bv", ".bw", ".by", ".bz", ".ca", ".cc", ".cd", ".cf", ".cg", ".ch", ".ci", ".ck", ".cl", ".cm", ".cn", ".co", ".cr", ".cu", ".cv", ".cx", ".cy", ".cz", ".de", ".dj", ".dk", ".dm", ".do", ".dz", ".ec", ".ee", ".eg", ".eh", ".er", ".es", ".et", ".eu", ".fi", ".fj", ".fk", ".fm", ".fo", ".fr", ".ga", ".gd", ".ge", ".gf", ".gg", ".gh", ".gi", ".gl", ".gm", ".gn", ".gp", ".gq", ".gr", ".gs", ".gt", ".gu", ".gw", ".gy", ".hk", ".hm", ".hn", ".hr", ".ht", ".hu", ".id", ".ie", ".il", ".im", ".in", ".io", ".iq", ".ir", ".is", ".it", ".je", ".jm", ".jo", ".jp", ".ke", ".kg", ".kh", ".ki", ".km", ".kn", ".kp", ".kr", ".kw", ".ky", ".kz", ".la", ".lb", ".lc", ".li", ".lk", ".lr", ".ls", ".lt", ".lu", ".lv", ".ly", ".ma", ".mc", ".md", ".mg", ".mh", ".mk", ".ml", ".mm", ".mn", ".mo", ".mp", ".mq", ".mr", ".ms", ".mt", ".mu", ".mv", ".mw", ".mx", ".my", ".mz", ".na", ".nc", ".ne", ".nf", ".ng", ".ni", ".nl", ".no", ".np", ".nr", ".nu", ".nz", ".om", ".pa", ".pe", ".pf", ".pg", ".ph", ".pk", ".pl", ".pm", ".pn", ".pr", ".ps", ".pt", ".pw", ".py", ".qa", ".re", ".ro", ".ru", ".rw", ".sa", ".sb", ".sc", ".sd", ".se", ".sg", ".sh", ".si", ".sj", ".sk", ".sl", ".sm", ".sn", ".so", ".sr", ".st", ".sv", ".sy", ".sz", ".tc", ".td", ".tf", ".tg", ".th", ".tj", ".tk", ".tl", ".tm", ".tn", ".to", ".tp", ".tr", ".tt", ".tv", ".tw", ".tz", ".ua", ".ug", ".uk", ".um", ".us", ".uy", ".uz", ".va", ".vc", ".ve", ".vg", ".vi", ".vn", ".vu", ".wf", ".ws", ".ye", ".yt", ".yu", ".yr", ".za", ".zm", ".zw"}
|
||||
C := CList[int(RandInt(4))%len(CList)]
|
||||
ST := RandString(int(RandInt(4) % 10))
|
||||
O := RandString(int(RandInt(4) % 10))
|
||||
CN := strings.ToLower(RandString(int(RandInt(4)%10)) + domainSubfixList[int(RandInt(4))%len(domainSubfixList)])
|
||||
//log.Printf("C: %s, ST: %s, O: %s, CN: %s", C, ST, O, CN)
|
||||
var out []byte
|
||||
if len(os.Args) == 3 && os.Args[2] == "ca" {
|
||||
cmd := exec.Command("sh", "-c", "openssl genrsa -out ca.key 2048")
|
||||
out, err = cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
logger.Printf("err:%s", err)
|
||||
return
|
||||
}
|
||||
fmt.Println(string(out))
|
||||
|
||||
cmdStr := fmt.Sprintf("openssl req -new -key ca.key -x509 -days 36500 -out ca.crt -subj /C=%s/ST=%s/O=%s/CN=%s", C, ST, O, "*."+CN)
|
||||
cmd = exec.Command("sh", "-c", cmdStr)
|
||||
out, err = cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
logger.Printf("err:%s", err)
|
||||
return
|
||||
}
|
||||
fmt.Println(string(out))
|
||||
} else if len(os.Args) == 5 && os.Args[2] == "ca" && os.Args[3] != "" && os.Args[4] != "" {
|
||||
certBytes, _ := ioutil.ReadFile("ca.crt")
|
||||
block, _ := pem.Decode(certBytes)
|
||||
if block == nil || certBytes == nil {
|
||||
panic("failed to parse ca certificate PEM")
|
||||
}
|
||||
x509Cert, _ := x509.ParseCertificate(block.Bytes)
|
||||
if x509Cert == nil {
|
||||
panic("failed to parse block")
|
||||
}
|
||||
name := os.Args[3]
|
||||
days := os.Args[4]
|
||||
cmd := exec.Command("sh", "-c", "openssl genrsa -out "+name+".key 2048")
|
||||
out, err = cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
logger.Printf("err:%s", err)
|
||||
return
|
||||
}
|
||||
fmt.Println(string(out))
|
||||
|
||||
cmdStr := fmt.Sprintf("openssl req -new -key %s.key -out %s.csr -subj /C=%s/ST=%s/O=%s/CN=%s", name, name, C, ST, O, CN)
|
||||
fmt.Printf("%s", cmdStr)
|
||||
cmd = exec.Command("sh", "-c", cmdStr)
|
||||
out, err = cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
logger.Printf("err:%s", err)
|
||||
return
|
||||
}
|
||||
fmt.Println(string(out))
|
||||
|
||||
cmdStr = fmt.Sprintf("openssl x509 -req -days %s -in %s.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out %s.crt", days, name, name)
|
||||
fmt.Printf("%s", cmdStr)
|
||||
cmd = exec.Command("sh", "-c", cmdStr)
|
||||
out, err = cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
logger.Printf("err:%s", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(string(out))
|
||||
} else if len(os.Args) == 3 && os.Args[2] == "usage" {
|
||||
fmt.Println(`proxy keygen //generate proxy.crt and proxy.key
|
||||
proxy keygen ca //generate ca.crt and ca.key
|
||||
proxy keygen ca client0 30 //generate client0.crt client0.key and use ca.crt sign it with 30 days
|
||||
`)
|
||||
} else if len(os.Args) == 2 {
|
||||
cmd := exec.Command("sh", "-c", "openssl genrsa -out proxy.key 2048")
|
||||
out, err = cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
logger.Printf("err:%s", err)
|
||||
return
|
||||
}
|
||||
fmt.Println(string(out))
|
||||
|
||||
cmdStr := fmt.Sprintf("openssl req -new -key proxy.key -x509 -days 36500 -out proxy.crt -subj /C=%s/ST=%s/O=%s/CN=%s", C, ST, O, CN)
|
||||
cmd = exec.Command("sh", "-c", cmdStr)
|
||||
out, err = cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
logger.Printf("err:%s", err)
|
||||
return
|
||||
}
|
||||
fmt.Println(string(out))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
func GetAllInterfaceAddr() ([]net.IP, error) {
|
||||
|
||||
ifaces, err := net.Interfaces()
|
||||
|
||||
@ -33,7 +33,7 @@ type ClientConn struct {
|
||||
timeout time.Duration
|
||||
addr string
|
||||
network string
|
||||
udpAddr string
|
||||
UDPAddr string
|
||||
}
|
||||
|
||||
// SOCKS5 returns a Dialer that makes SOCKSv5 connections to the given address
|
||||
@ -168,14 +168,14 @@ func (s *ClientConn) Handshake() error {
|
||||
}
|
||||
p := binary.BigEndian.Uint16([]byte{buf[0], buf[1]})
|
||||
//log.Printf("%v", p)
|
||||
s.udpAddr = net.JoinHostPort(ipStr, fmt.Sprintf("%d", p))
|
||||
s.UDPAddr = net.JoinHostPort(ipStr, fmt.Sprintf("%d", p))
|
||||
//log.Printf("%v", s.udpAddr)
|
||||
(*s.conn).SetDeadline(time.Time{})
|
||||
return nil
|
||||
}
|
||||
func (s *ClientConn) SendUDP(data []byte, addr string) (respData []byte, err error) {
|
||||
|
||||
c, err := net.DialTimeout("udp", s.udpAddr, s.timeout)
|
||||
c, err := net.DialTimeout("udp", s.UDPAddr, s.timeout)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@ -2,10 +2,11 @@ package socks
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/snail007/goproxy/utils"
|
||||
"net"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/snail007/goproxy/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -54,26 +55,27 @@ type ServerConn struct {
|
||||
methods []uint8
|
||||
method uint8
|
||||
//request
|
||||
cmd uint8
|
||||
reserve uint8
|
||||
addressType uint8
|
||||
dstAddr string
|
||||
dstPort string
|
||||
dstHost string
|
||||
udpAddress string
|
||||
cmd uint8
|
||||
reserve uint8
|
||||
addressType uint8
|
||||
dstAddr string
|
||||
dstPort string
|
||||
dstHost string
|
||||
UDPConnListener *net.UDPConn
|
||||
enableUDP bool
|
||||
udpIP string
|
||||
}
|
||||
|
||||
func NewServerConn(conn *net.Conn, timeout time.Duration, auth *utils.BasicAuth, udpAddress string, header []byte) *ServerConn {
|
||||
if udpAddress == "" {
|
||||
udpAddress = "0.0.0.0:16666"
|
||||
}
|
||||
func NewServerConn(conn *net.Conn, timeout time.Duration, auth *utils.BasicAuth, enableUDP bool, udpHost string, header []byte) *ServerConn {
|
||||
|
||||
s := &ServerConn{
|
||||
conn: conn,
|
||||
timeout: timeout,
|
||||
auth: auth,
|
||||
header: header,
|
||||
ver: VERSION_V5,
|
||||
udpAddress: udpAddress,
|
||||
conn: conn,
|
||||
timeout: timeout,
|
||||
auth: auth,
|
||||
header: header,
|
||||
ver: VERSION_V5,
|
||||
enableUDP: enableUDP,
|
||||
udpIP: udpHost,
|
||||
}
|
||||
return s
|
||||
|
||||
@ -84,6 +86,12 @@ func (s *ServerConn) Close() {
|
||||
func (s *ServerConn) AuthData() Auth {
|
||||
return Auth{s.user, s.password}
|
||||
}
|
||||
func (s *ServerConn) IsUDP() bool {
|
||||
return s.cmd == CMD_ASSOCIATE
|
||||
}
|
||||
func (s *ServerConn) IsTCP() bool {
|
||||
return s.cmd == CMD_CONNECT
|
||||
}
|
||||
func (s *ServerConn) Method() uint8 {
|
||||
return s.method
|
||||
}
|
||||
@ -205,11 +213,29 @@ func (s *ServerConn) Handshake() (err error) {
|
||||
return
|
||||
}
|
||||
case CMD_ASSOCIATE:
|
||||
err = request.UDPReply(REP_SUCCESS, s.udpAddress)
|
||||
if !s.enableUDP {
|
||||
request.UDPReply(REP_UNKNOWN, "0.0.0.0:0")
|
||||
if err != nil {
|
||||
err = fmt.Errorf("UDPReply REP_UNKNOWN to %s fail,ERR: %s", remoteAddr, err)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("cmd associate not supported, form: %s", remoteAddr)
|
||||
return
|
||||
}
|
||||
a, _ := net.ResolveUDPAddr("udp", ":0")
|
||||
s.UDPConnListener, err = net.ListenUDP("udp", a)
|
||||
if err != nil {
|
||||
request.UDPReply(REP_UNKNOWN, "0.0.0.0:0")
|
||||
err = fmt.Errorf("udp bind fail,ERR: %s , for %s", err, remoteAddr)
|
||||
return
|
||||
}
|
||||
_, port, _ := net.SplitHostPort(s.UDPConnListener.LocalAddr().String())
|
||||
err = request.UDPReply(REP_SUCCESS, net.JoinHostPort(s.udpIP, port))
|
||||
if err != nil {
|
||||
err = fmt.Errorf("UDPReply REP_SUCCESS to %s fail,ERR: %s", remoteAddr, err)
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//fill socks info
|
||||
|
||||
@ -33,15 +33,11 @@ type Checker struct {
|
||||
log *logger.Logger
|
||||
}
|
||||
type CheckerItem struct {
|
||||
IsHTTPS bool
|
||||
Method string
|
||||
URL string
|
||||
Domain string
|
||||
Host string
|
||||
Data []byte
|
||||
Address string
|
||||
SuccessCount uint
|
||||
FailCount uint
|
||||
Key string
|
||||
Lasttime int64
|
||||
}
|
||||
|
||||
//NewChecker args:
|
||||
@ -101,17 +97,23 @@ func (c *Checker) start() {
|
||||
//log.Printf("check %s", item.Host)
|
||||
var conn net.Conn
|
||||
var err error
|
||||
conn, err = ConnectHost(item.Host, c.timeout)
|
||||
var now = time.Now().Unix()
|
||||
conn, err = ConnectHost(item.Address, c.timeout)
|
||||
if err == nil {
|
||||
conn.SetDeadline(time.Now().Add(time.Millisecond))
|
||||
conn.Close()
|
||||
}
|
||||
if now-item.Lasttime > 1800 {
|
||||
item.FailCount = 0
|
||||
item.SuccessCount = 0
|
||||
}
|
||||
if err != nil {
|
||||
item.FailCount = item.FailCount + 1
|
||||
} else {
|
||||
item.SuccessCount = item.SuccessCount + 1
|
||||
}
|
||||
c.data.Set(item.Host, item)
|
||||
item.Lasttime = now
|
||||
c.data.Set(item.Domain, item)
|
||||
}
|
||||
}(v.(CheckerItem))
|
||||
}
|
||||
@ -124,32 +126,37 @@ func (c *Checker) start() {
|
||||
}
|
||||
func (c *Checker) isNeedCheck(item CheckerItem) bool {
|
||||
var minCount uint = 5
|
||||
if (item.SuccessCount >= minCount && item.SuccessCount > item.FailCount) ||
|
||||
(item.FailCount >= minCount && item.SuccessCount > item.FailCount) ||
|
||||
c.domainIsInMap(item.Host, false) ||
|
||||
c.domainIsInMap(item.Host, true) {
|
||||
var now = time.Now().Unix()
|
||||
if (item.SuccessCount >= minCount && item.SuccessCount > item.FailCount && now-item.Lasttime < 1800) ||
|
||||
(item.FailCount >= minCount && item.SuccessCount > item.FailCount && now-item.Lasttime < 1800) ||
|
||||
c.domainIsInMap(item.Domain, false) ||
|
||||
c.domainIsInMap(item.Domain, true) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
func (c *Checker) IsBlocked(address string) (blocked bool, failN, successN uint) {
|
||||
if c.domainIsInMap(address, true) {
|
||||
//log.Printf("%s in blocked ? true", address)
|
||||
return true, 0, 0
|
||||
func (c *Checker) IsBlocked(domain string) (blocked, isInMap bool, failN, successN uint) {
|
||||
h, _, _ := net.SplitHostPort(domain)
|
||||
if h != "" {
|
||||
domain = h
|
||||
}
|
||||
if c.domainIsInMap(address, false) {
|
||||
if c.domainIsInMap(domain, true) {
|
||||
//log.Printf("%s in blocked ? true", address)
|
||||
return true, true, 0, 0
|
||||
}
|
||||
if c.domainIsInMap(domain, false) {
|
||||
//log.Printf("%s in direct ? true", address)
|
||||
return false, 0, 0
|
||||
return false, true, 0, 0
|
||||
}
|
||||
|
||||
_item, ok := c.data.Get(address)
|
||||
_item, ok := c.data.Get(domain)
|
||||
if !ok {
|
||||
//log.Printf("%s not in map, blocked true", address)
|
||||
return true, 0, 0
|
||||
return true, false, 0, 0
|
||||
}
|
||||
item := _item.(CheckerItem)
|
||||
|
||||
return item.FailCount >= item.SuccessCount, item.FailCount, item.SuccessCount
|
||||
return (item.FailCount >= item.SuccessCount) && (time.Now().Unix()-item.Lasttime < 1800), true, item.FailCount, item.SuccessCount
|
||||
}
|
||||
func (c *Checker) domainIsInMap(address string, blockedMap bool) bool {
|
||||
u, err := url.Parse("http://" + address)
|
||||
@ -174,16 +181,20 @@ func (c *Checker) domainIsInMap(address string, blockedMap bool) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
func (c *Checker) Add(key, address string) {
|
||||
if c.domainIsInMap(key, false) || c.domainIsInMap(key, true) {
|
||||
func (c *Checker) Add(domain, address string) {
|
||||
h, _, _ := net.SplitHostPort(domain)
|
||||
if h != "" {
|
||||
domain = h
|
||||
}
|
||||
if c.domainIsInMap(domain, false) || c.domainIsInMap(domain, true) {
|
||||
return
|
||||
}
|
||||
var item CheckerItem
|
||||
item = CheckerItem{
|
||||
Host: address,
|
||||
Key: key,
|
||||
Domain: domain,
|
||||
Address: address,
|
||||
}
|
||||
c.data.SetIfAbsent(item.Host, item)
|
||||
c.data.SetIfAbsent(item.Domain, item)
|
||||
}
|
||||
|
||||
type BasicAuth struct {
|
||||
@ -329,6 +340,7 @@ type HTTPRequest struct {
|
||||
isBasicAuth bool
|
||||
basicAuth *BasicAuth
|
||||
log *logger.Logger
|
||||
IsSNI bool
|
||||
}
|
||||
|
||||
func NewHTTPRequest(inConn *net.Conn, bufSize int, isBasicAuth bool, basicAuth *BasicAuth, log *logger.Logger, header ...[]byte) (req HTTPRequest, err error) {
|
||||
@ -360,6 +372,7 @@ func NewHTTPRequest(inConn *net.Conn, bufSize int, isBasicAuth bool, basicAuth *
|
||||
//sni success
|
||||
req.Method = "SNI"
|
||||
req.hostOrURL = "https://" + serverName + ":443"
|
||||
req.IsSNI = true
|
||||
} else {
|
||||
//sni fail , try http
|
||||
index := bytes.IndexByte(req.HeadBuf, '\n')
|
||||
|
||||
Reference in New Issue
Block a user