Compare commits
60 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
58eb591044 | ||
|
|
426d711d0b | ||
|
|
b336b9ce03 | ||
|
|
c3262fc0cb | ||
|
|
2fef2c0eaa | ||
|
|
3d33cdc9f1 | ||
|
|
c14a3b2773 | ||
|
|
e6e61b3cdb | ||
|
|
303587f91b | ||
|
|
5c3fd53fab | ||
|
|
0c675e6ff6 | ||
|
|
942b026a05 | ||
|
|
0b347b7f8d | ||
|
|
87322c335e | ||
|
|
1bf4b38268 | ||
|
|
60b1742088 | ||
|
|
266fa6f6fa | ||
|
|
02c3c9b374 | ||
|
|
8f7da3ed94 | ||
|
|
a5a6e8645a | ||
|
|
83022d3efc | ||
|
|
78143ce638 | ||
|
|
cee38766c5 | ||
|
|
c66147c686 | ||
|
|
08e149b180 | ||
|
|
e3f8b652f4 | ||
|
|
6a4a45c96b | ||
|
|
e5bf95bdc8 | ||
|
|
ed1e7253f3 | ||
|
|
db43daea0b | ||
|
|
0359ef40e1 | ||
|
|
89b5744e27 | ||
|
|
18f293a7aa | ||
|
|
acf70602ff | ||
|
|
ebba94b9d1 | ||
|
|
23c379faf9 | ||
|
|
124852b3a2 | ||
|
|
e6d557f61e | ||
|
|
0a2ed2e498 | ||
|
|
4ce5fd463d | ||
|
|
367cfb36dd | ||
|
|
57555ffc1e | ||
|
|
8a86a53bd2 | ||
|
|
4a7b1af383 | ||
|
|
78e631f551 | ||
|
|
0af83540d3 | ||
|
|
9004913483 | ||
|
|
44909ea6c6 | ||
|
|
a0cd66e319 | ||
|
|
8c4e5025ed | ||
|
|
442e7b7c01 | ||
|
|
05dfbe6f8a | ||
|
|
c64324227b | ||
|
|
1388f2e008 | ||
|
|
2752d79248 | ||
|
|
7aa24afcf2 | ||
|
|
b3622e709c | ||
|
|
02a58189ad | ||
|
|
f42184daaf | ||
|
|
69f20e1d7a |
@ -1,13 +1,13 @@
|
||||
# GoProxy特殊授权
|
||||
# GoProxy special authorization
|
||||
|
||||
1.goproxy采用GPLv3源代码开放协议,未经许可,基于本项目开发的软件,衍生软件,相关软件,必须严格遵守GPLv3,否则一经发现,
|
||||
将严厉追责.
|
||||
1. gproxy uses GPLv3 source code open agreement, without permission, based on the project development software, derivative software, related software, must strictly abide by GPLv3, otherwise once found,
|
||||
Will be harshly punished.
|
||||
|
||||
2.如果公司或个人使用本项目代码开发相关软件,衍生软件,又不想遵守GPLv3协议,需要取得作者的"GoProxy特殊授权"书面授权.
|
||||
2. If the company or individual uses the project code to develop related software, derivative software, and does not want to comply with the GPLv3 agreement, need to obtain the author's "GoProxy special authorization" written authorization.
|
||||
|
||||
3.如果本页面查询不到"GoProxy特殊授权"书面授权信息,则"GoProxy特殊授权"书面授权无效.
|
||||
3. If "GoPro special authorization"is not available on this page,the" GoPro special authorization"is invalid.
|
||||
|
||||
4.下面列出了有效的授权编号和有效期.
|
||||
4. A valid authorization number and expiration date are listed below.
|
||||
|
||||
授权编号 | 授权有效期
|
||||
Authorization number | Authorization validity period
|
||||
:--- | :---
|
||||
|
||||
13
AUTHORIZATION_ZH.md
Normal file
13
AUTHORIZATION_ZH.md
Normal file
@ -0,0 +1,13 @@
|
||||
# GoProxy特殊授权
|
||||
|
||||
1.goproxy采用GPLv3源代码开放协议,未经许可,基于本项目开发的软件,衍生软件,相关软件,必须严格遵守GPLv3,否则一经发现,
|
||||
将严厉追责.
|
||||
|
||||
2.如果公司或个人使用本项目代码开发相关软件,衍生软件,又不想遵守GPLv3协议,需要取得作者的"GoProxy特殊授权"书面授权.
|
||||
|
||||
3.如果本页面查询不到"GoProxy特殊授权"书面授权信息,则"GoProxy特殊授权"书面授权无效.
|
||||
|
||||
4.下面列出了有效的授权编号和有效期.
|
||||
|
||||
授权编号 | 授权有效期
|
||||
:--- | :---
|
||||
28
CHANGELOG
28
CHANGELOG
@ -1,5 +1,33 @@
|
||||
proxy更新日志
|
||||
|
||||
v6.9
|
||||
1.修复了sps的start潜在的crash问题.
|
||||
2.sps代理增加了--parent-tls-single参数用来支持单向tls上级。
|
||||
3.sps代理增加了对单个上级认证信息的支持,如果没有单独设置,就使用全局-A设置.
|
||||
现在上级格式: -P YTpi#2.2.2.2:33080@1
|
||||
说明:
|
||||
YTpi 是经过base64编码的认证信息,比如是http(s)/socks原始认证信息a:b,用户是a密码是b,base64编码之后是:YTpi
|
||||
如果是ss,那么a就是加密方法,b是密码,比如:aes-192-cfb:your_pass,base64编码之后是:YWVzLTE5Mi1jZmI6eW91cl9wYXNz
|
||||
# 是间隔符号,如果有认证信息,必须有#,没有认证信息可以省略#.
|
||||
2.2.2.2:33080 是上级地址
|
||||
@1 是设置权重,可以参考手册权重部分.
|
||||
4.修复了socks5代理错误处理超时的问题.
|
||||
5.修复了http(s)代理错误处理-Z的问题.
|
||||
|
||||
v6.8
|
||||
1.HTTP(S)\SOCKS5代理,API认证功能,发送给认证接口的参数增加了本地IP,local_ip字段,
|
||||
代表用户访问的是本地服务器的哪个IP.
|
||||
2.fix #194 , fix #134 , 代理更稳定.
|
||||
3.增加了一波英文文档.
|
||||
|
||||
v6.6
|
||||
1.优化了limitconn的关闭逻辑,释放更多资源.
|
||||
2.http(s)\socks代理增加了--intelligent,智能模式设置,可以是intelligent|direct|parent三者之一,
|
||||
默认是:intelligent.每个值的含义如下.
|
||||
--intelligent=direct,不在blocked里面的目标都直连.
|
||||
--intelligent=parent,不在direct里面的目标都走上级.
|
||||
--intelligent=intelligent,blocked和direct里面都没有的目标,智能判断是否使用上级访问目标.
|
||||
|
||||
v6.5
|
||||
1.修复了合并企业版遗留的一些bug.
|
||||
|
||||
|
||||
82
Dockerfile
82
Dockerfile
@ -1,82 +0,0 @@
|
||||
FROM alpine:3.7 AS builder
|
||||
|
||||
RUN apk add --no-cache \
|
||||
ca-certificates
|
||||
|
||||
# set up nsswitch.conf for Go's "netgo" implementation
|
||||
# - https://github.com/golang/go/blob/go1.9.1/src/net/conf.go#L194-L275
|
||||
# - docker run --rm debian:stretch grep '^hosts:' /etc/nsswitch.conf
|
||||
RUN [ ! -e /etc/nsswitch.conf ] && echo 'hosts: files dns' > /etc/nsswitch.conf
|
||||
|
||||
ENV GOLANG_VERSION 1.10.3
|
||||
|
||||
# make-sure-R0-is-zero-before-main-on-ppc64le.patch: https://github.com/golang/go/commit/9aea0e89b6df032c29d0add8d69ba2c95f1106d9 (Go 1.9)
|
||||
#COPY *.patch /go-alpine-patches/
|
||||
|
||||
RUN set -eux; \
|
||||
apk add --no-cache --virtual .build-deps \
|
||||
bash \
|
||||
gcc \
|
||||
musl-dev \
|
||||
openssl \
|
||||
go \
|
||||
; \
|
||||
export \
|
||||
# set GOROOT_BOOTSTRAP such that we can actually build Go
|
||||
GOROOT_BOOTSTRAP="$(go env GOROOT)" \
|
||||
# ... and set "cross-building" related vars to the installed system's values so that we create a build targeting the proper arch
|
||||
# (for example, if our build host is GOARCH=amd64, but our build env/image is GOARCH=386, our build needs GOARCH=386)
|
||||
GOOS="$(go env GOOS)" \
|
||||
GOARCH="$(go env GOARCH)" \
|
||||
GOHOSTOS="$(go env GOHOSTOS)" \
|
||||
GOHOSTARCH="$(go env GOHOSTARCH)" \
|
||||
; \
|
||||
# also explicitly set GO386 and GOARM if appropriate
|
||||
# https://github.com/docker-library/golang/issues/184
|
||||
apkArch="$(apk --print-arch)"; \
|
||||
case "$apkArch" in \
|
||||
armhf) export GOARM='6' ;; \
|
||||
x86) export GO386='387' ;; \
|
||||
esac; \
|
||||
\
|
||||
wget -O go.tgz "https://golang.org/dl/go$GOLANG_VERSION.src.tar.gz"; \
|
||||
echo '567b1cc66c9704d1c019c50bef946272e911ec6baf244310f87f4e678be155f2 *go.tgz' | sha256sum -c -; \
|
||||
tar -C /usr/local -xzf go.tgz; \
|
||||
rm go.tgz; \
|
||||
\
|
||||
cd /usr/local/go/src; \
|
||||
for p in /go-alpine-patches/*.patch; do \
|
||||
[ -f "$p" ] || continue; \
|
||||
patch -p2 -i "$p"; \
|
||||
done; \
|
||||
./make.bash; \
|
||||
\
|
||||
rm -rf /go-alpine-patches; \
|
||||
apk del .build-deps; \
|
||||
\
|
||||
export PATH="/usr/local/go/bin:$PATH"; \
|
||||
go version
|
||||
|
||||
ENV GOPATH /go
|
||||
ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH
|
||||
|
||||
RUN mkdir -p "$GOPATH/src" "$GOPATH/bin" && chmod -R 777 "$GOPATH"
|
||||
WORKDIR $GOPATH
|
||||
|
||||
ARG GOPROXY_VERSION=master
|
||||
RUN apk update; apk upgrade; \
|
||||
apk add --no-cache git; \
|
||||
cd /go/src/; \
|
||||
mkdir github.com; \
|
||||
mkdir github.com/snail007; \
|
||||
cd github.com/snail007; \
|
||||
git clone https://github.com/snail007/goproxy.git; \
|
||||
cd goproxy; \
|
||||
git checkout ${GOPROXY_VERSION}; \
|
||||
CGO_ENABLED=0 GOOS=linux go build -ldflags "-s -w" -a -installsuffix cgo -o proxy; \
|
||||
chmod 0777 proxy
|
||||
|
||||
FROM 1.10.3-stretch
|
||||
RUN mkdir /proxy && chmod 0777 /proxy
|
||||
COPY --from=builder builder /go/src/github.com/snail007/goproxy/proxy /proxy/
|
||||
CMD cd /proxy && /proxy ${OPTS}
|
||||
141
README.md
141
README.md
@ -1,18 +1,19 @@
|
||||
<img src="https://github.com/snail007/goproxy/blob/master/docs/images/logo.jpg?raw=true" width="200"/>
|
||||
Proxy is a high performance HTTP, HTTPS, HTTPS, websocket, TCP, UDP, Socks5, ss proxy server implemented by golang. It supports parent proxy,nat forward,TCP/UDP port forwarding, SSH transfer, TLS encrypted transmission, protocol conversion. you can expose a local server behind a NAT or firewall to the internet, secure DNS proxy.
|
||||
|
||||
|
||||
[Download](https://github.com/snail007/goproxy/releases)
|
||||
|
||||
---
|
||||
|
||||
[](https://github.com/snail007/goproxy/) []() [](https://github.com/snail007/goproxy/releases) [](https://github.com/snail007/goproxy/releases)
|
||||
|
||||
**[中文手册](/README_ZH.md)**
|
||||
|
||||
**[全平台图形界面版本](/gui/README.md)**
|
||||
**[Full-platform graphical interface version](/gui/README.md)**
|
||||
|
||||
**[全平台SDK](/sdk/README.md)**
|
||||
**[Full platform SDK](https://github.com/snail007/goproxy-sdk/blob/master/README.md)**
|
||||
|
||||
**[GoProxy特殊授权](/AUTHORIZATION.md)**
|
||||
**[GoProxy special authorization](/AUTHORIZATION.md)**
|
||||
|
||||
### How to contribute to the code (Pull Request)?
|
||||
|
||||
@ -100,7 +101,8 @@ This page is the v6.0 manual, and the other version of the manual can be checked
|
||||
- [1.15 speed limit](#115-speed-limit)
|
||||
- [1.16 Designated exporting IP](#116-designated-export-ip)
|
||||
- [1.17 Certificate parameters using Base64 data](#117-certificate-parameters-using-Base64-data)
|
||||
- [1.18 View help](#118view-help)
|
||||
- [1.18 Intelligent mode](#118-intelligent-mode)
|
||||
- [1.19 View help](#119view-help)
|
||||
- [2.TCP proxy](#2tcp-proxy)
|
||||
- [2.1 Common TCP first level proxy](#21common-tcp-first-level-proxy)
|
||||
- [2.2 Common TCP second level proxy](#22common-tcp-second-level-proxy)
|
||||
@ -145,7 +147,8 @@ This page is the v6.0 manual, and the other version of the manual can be checked
|
||||
- [5.14 Designated exporting IP](#514-designated-exporting-ip)
|
||||
- [5.15 Cascade authentication](#515-cascade-authentication)
|
||||
- [5.16 Certificate parameters using Base64 data](#516-certificate-parameters-using-base64-data)
|
||||
- [5.17 View help](#517view-help)
|
||||
- [5.17 Intelligent mode](#517-intelligent-mode)
|
||||
- [5.18 View help](#518view-help)
|
||||
- [6.Proxy protocol conversion](#6proxy-protocol-conversion)
|
||||
- [6.1 Functional introduction](#61functional-introduction)
|
||||
- [6.2 HTTP(S) to HTTP(S) + SOCKS5](#62http-to-http-socks5)
|
||||
@ -199,6 +202,8 @@ chmod +x install.sh
|
||||
|
||||
#### Docker installation
|
||||
|
||||
[docker](https://hub.docker.com/r/snail007/goproxy)
|
||||
|
||||
Dockerfile root of project uses multistage build and alpine project to comply with best practices. Uses golang 1.10.3 for building as noted in the project README.md and will be pretty small image. total extracted size will be 17.3MB for goproxy latest version.
|
||||
|
||||
The default build process builds the master branch (latest commits/ cutting edge), and it can be configured to build specific version, just edit Dockerfile before build, following builds release version 6.0:
|
||||
@ -323,7 +328,7 @@ accessing the local 8080 port is accessing the proxy port 38080 above VPS.
|
||||
|
||||
HTTP second level proxy(local windows)
|
||||
`./proxy.exe http -t tcp -p ":8080" -T tls -P "22.22.22.22:38080" -C proxy.crt -K proxy.key`
|
||||
In your windos system, the mode of the program that needs to surf the Internet by proxy is setted up as HTTP mode, the address is 127.0.0.1, the port is: 8080, the program can go through the encrypted channel through VPS to surf on the internet.
|
||||
In your windows system, the mode of the program that needs to surf the Internet by proxy is setted up as HTTP mode, the address is 127.0.0.1, the port is: 8080, the program can go through the encrypted channel through VPS to surf on the internet.
|
||||
|
||||
#### **1.4.HTTP third level encrypted proxy**
|
||||

|
||||
@ -509,18 +514,26 @@ HTTP (S) proxy supports superior load balance, and multiple -P parameters can be
|
||||
`proxy http --lb-hashtarget --lb-method=leasttime -T tcp -P 1.1.1.1:33080 -P 2.1.1.1:33080 -P 3.1.1.1:33080 -t tcp -p :33080`
|
||||
|
||||
### **1.15 Speed limit**
|
||||
The speed limit is 100K, which can be specified through the `-l` parameter, for example: 100K 1.5M. 0 means unlimited.
|
||||
The speed limit is 100K, which can be specified through the `-l` parameter, for example: 100K 2000K 1M . 0 means unlimited.
|
||||
`proxy http -t tcp -p 2.2.2.2:33080 -l 100K`
|
||||
|
||||
### **1.16 Designated exporting IP**
|
||||
The `- bind-listen` parameter opens the client's ability to access the target site with an entry IP connection, using the entry IP as the exporting IP. If the entry IP is the intranet IP, the exporting IP will not use the entry IP..
|
||||
The `--bind-listen` parameter open the client's ability to access the target site with an entry IP connection, using the entry IP as the exporting IP. If the entry IP is the intranet IP, the exporting IP will not use the entry IP..
|
||||
`proxy http -t tcp -p 2.2.2.2:33080 --bind-listen`
|
||||
|
||||
### **1.17 Certificate parameters using Base64 data**
|
||||
By default, the -C and -K parameters are the paths of CRT certificates and key files,
|
||||
If it is the beginning of base64://, then it is considered that the data behind is Base64 encoded and will be used after decoding.
|
||||
|
||||
#### **1.18.view help**
|
||||
#### **1.18 Intelligent mode**
|
||||
Intelligent mode setting which can be one of intelligent|direct|parent.
|
||||
default:intelligent.
|
||||
The meaning of each value is as follows:
|
||||
`--intelligent=direct`, Targets that are not in blocked directly connected.
|
||||
`--intelligent=parent`, Targets that are not in direct connect to parent proxy.
|
||||
`--intelligent=intelligent`, Targets that are not in direct and blocked Neither can intelligently judge on whether to connetc parent proxy.
|
||||
|
||||
#### **1.19.view help**
|
||||
`./proxy help http`
|
||||
|
||||
### **2.TCP proxy**
|
||||
@ -943,7 +956,7 @@ SOCKS proxy supports the load balancing of superior authorities, and the -P para
|
||||
`proxy socks --lb-hashtarget --lb-method=leasttime -T tcp -P 1.1.1.1:33080 -P 2.1.1.1:33080 -P 3.1.1.1:33080 -p :33080 -t tcp`
|
||||
|
||||
#### **5.13 Speed limit**
|
||||
The speed limit is 100K, which can be specified through the -l parameter, for example: 100K 1.5M. 0 means unlimited.
|
||||
The speed limit is 100K, which can be specified through the -l parameter, for example: 100K 2000K 1M . 0 means unlimited.
|
||||
`proxy socks -t tcp -p 2.2.2.2:33080 -l 100K`
|
||||
|
||||
#### **5.14 Designated exporting IP**
|
||||
@ -959,9 +972,17 @@ localhost:
|
||||
|
||||
#### **5.16 Certificate parameters using Base64 data**
|
||||
By default, the -C and -K parameters are the paths of CRT certificates and key files,
|
||||
If it is the beginning of base64://, then it is considered that the data behind is Base64 encoded and will be used after decoding..
|
||||
If it is the beginning of base64://, then it is considered that the data behind is Base64 encoded and will be used after decoding.
|
||||
|
||||
#### **5.17.view help**
|
||||
#### **5.17 Intelligent mode**
|
||||
Intelligent mode setting which can be one of intelligent|direct|parent.
|
||||
default:intelligent.
|
||||
The meaning of each value is as follows:
|
||||
`--intelligent=direct`, Targets that are not in blocked directly connected.
|
||||
`--intelligent=parent`, Targets that are not in direct connect to parent proxy.
|
||||
`--intelligent=intelligent`, Targets that are not in direct and blocked Neither can intelligently judge on whether to connetc parent proxy.
|
||||
|
||||
#### **5.18.view help**
|
||||
`./proxy help socks`
|
||||
|
||||
### **6.Proxy protocol conversion**
|
||||
@ -1068,6 +1089,19 @@ target: if the client is the HTTP (s) proxy request, this represents the complet
|
||||
If there is no -a or -F or --auth-url parameters, local authentication is closed.
|
||||
If there is no -A parameter, the connection to the father proxy does not use authentication.
|
||||
|
||||
**Setting up separate authentication information**
|
||||
|
||||
If there are many different parent proxys and their passwords are the same or different, then authentication information can be set for each parent proxy.
|
||||
At the same time, a global authentication information can be set with the - A parameter. If a parent proxy does not set the authentication information separately, the global authentication information can be used.
|
||||
Authentication information is written together with parent proxy.
|
||||
format: YTpi#2.2.2.2:33080@1
|
||||
Explain:
|
||||
YTpi is the Authentication information encoded by Base64, For example, http (s)/socks original authentication information, a:b,the user is a and the password is b, which is YTpi after Base64 encoding.
|
||||
if it is ss, A is the encryption method and B is the password, for example, aes-192-cfb:your_pass, which is YWVzLTE5Mi1jZmI6eW91cl9wYXNz after Base64 encoding.
|
||||
\# is an interval symbol. If there is authentication information, there must be #. No authentication information can be omitted #
|
||||
2.2.2.2:33080 is parent proxy's address
|
||||
@1 is weights, Nothing can be omitted. Detailed instructions can be referred to in the manual.***weights***
|
||||
|
||||
#### **6.8 Custom encryption**
|
||||
HTTP(s) proxy can encrypt TCP data by TLS standard encryption and KCP protocol encryption, in addition to supporting custom encryption after TLS and KCP, That is to say, custom encryption and tls|kcp can be combined to use. The internal AES256 encryption is used, and it only needs to define one password by yourself. Encryption is divided into two parts, the one is whether the local (-z) is encrypted and decrypted, the other is whether the parents (-Z) is encrypted and decrypted.
|
||||
Custom encryption requires both ends are proxy. Next, we use two level example and three level example as examples:
|
||||
@ -1090,8 +1124,8 @@ Local third level execution:
|
||||
through this way, When you visits the website by local proxy 8080, it visits the target website by encryption transmission with the parents proxy.
|
||||
|
||||
#### **6.9 Compressed transmission**
|
||||
HTTP(s) proxy can encrypt TCP data through TCP standard encryption and KCP protocol encryption, and can also compress data before custom encryption.
|
||||
That is to say, compression and custom encryption and tls|kcp can be used together, compression is divided into two parts, the one is whether the local (-z) is compressed transmission, the other is whether the parents (-Z) is compressed transmission.
|
||||
HTTP(s) proxy can encrypt TCP data through TCP standard encryption and KCP protocol encryption, and can also compress data before custom encryption.
|
||||
That is to say, compression and custom encryption and tls|kcp can be used together, compression is divided into two parts, the one is whether the local (-z) is compressed transmission, the other is whether the parents (-Z) is compressed transmission.
|
||||
The compression requires both ends are proxy. Compression also protects the (encryption) data in certain extent. we use two level example and three level example as examples:
|
||||
|
||||
**two level example**
|
||||
@ -1104,7 +1138,7 @@ through this way, When you visits the website by local proxy 8080, it visits the
|
||||
**three level example**
|
||||
First level VPS (ip:2.2.2.2) execution:
|
||||
`proxy sps -t tcp -m -p :7777`
|
||||
Second level VPS (ip:3.3.3.3) execution::
|
||||
Second level VPS (ip:3.3.3.3) execution:
|
||||
`proxy sps -T tcp -P 2.2.2.2:7777 -M -t tcp -m -p :8888`
|
||||
Local third level execution:
|
||||
`proxy sps -T tcp -P 3.3.3.3:8888 -M -t tcp -p :8080`
|
||||
@ -1113,25 +1147,25 @@ through this way, When you visits the website by local proxy 8080, it visits the
|
||||
#### **6.10 Disable protocol**
|
||||
By default, SPS's port supports two proxy protocols, http (s) and socks5, and we can disable a protocol with parameters.
|
||||
for example:
|
||||
1.Disable the HTTP (S) proxy, retaining only the SOCKS5 proxy,parameter:`--disable-http`.
|
||||
`proxy sps -T tcp -P 3.3.3.3:8888 -M -t tcp -p :8080 --disable-http`
|
||||
1.Disable the SOCKS5 proxy, retaining only the HTTP (S) proxy,parameter:`--disable-socks`.
|
||||
1.Disable the HTTP (S) proxy, retaining only the SOCKS5 proxy,parameter:`--disable-http`.
|
||||
`proxy sps -T tcp -P 3.3.3.3:8888 -M -t tcp -p :8080 --disable-http`
|
||||
1.Disable the SOCKS5 proxy, retaining only the HTTP (S) proxy,parameter:`--disable-socks`.
|
||||
`proxy sps -T tcp -P 3.3.3.3:8888 -M -t tcp -p :8080 --disable-http`
|
||||
|
||||
#### **6.11 Speed limit**
|
||||
Suppose there has a SOCKS5 parent proxy:
|
||||
`proxy socks -p 2.2.2.2:33080 -z password -t tcp`
|
||||
SPS lower speed limit 100K
|
||||
`proxy sps -S socks -P 2.2.2.2:33080 -T tcp -Z password -l 100K -t tcp -p :33080`
|
||||
It can be specified through the `-l` parameter, for example: 100K 1.5M. 0 means unlimited..
|
||||
Suppose there has a SOCKS5 parent proxy:
|
||||
`proxy socks -p 2.2.2.2:33080 -z password -t tcp`
|
||||
SPS lower speed limit 100K
|
||||
`proxy sps -S socks -P 2.2.2.2:33080 -T tcp -Z password -l 100K -t tcp -p :33080`
|
||||
It can be specified through the `-l` parameter, for example: 100K 2000K 1M . 0 means unlimited.
|
||||
|
||||
#### **6.12 Designated exporting IP**
|
||||
The `- bind-listen` parameter opens the client's ability to access the target site with an entry IP connection, using the entry IP as the exporting IP. If the entry IP is the intranet IP, the exporting IP will not use the entry IP.
|
||||
The `- bind-listen` parameter opens the client's ability to access the target site with an entry IP connection, using the entry IP as the exporting IP. If the entry IP is the intranet IP, the exporting IP will not use the entry IP.
|
||||
`proxy sps -S socks -P 2.2.2.2:33080 -T tcp -Z password -l 100K -t tcp --bind-listen -p :33080`
|
||||
|
||||
#### **6.13 Certificate parameters using Base64 data**
|
||||
By default, the -C and -K parameters are the paths of CRT certificates and key files,
|
||||
If it is the beginning of base64://, then it is considered that the data behind is Base64 encoded and will be used after decoding.
|
||||
By default, the -C and -K parameters are the paths of CRT certificates and key files,
|
||||
If it is the beginning of base64://, then it is considered that the data behind is Base64 encoded and will be used after decoding.
|
||||
|
||||
#### **6.14.view help**
|
||||
`./proxy help sps`
|
||||
@ -1170,7 +1204,7 @@ If you want to get a more detailed configuration and explanation of the KCP para
|
||||
### **8.DNS anti pollution server**
|
||||
|
||||
#### **8.1.Introduction**
|
||||
It is well known that DNS is a service which use UDP protocol and 53 port,But with the development of network, some well-known DNS servers also support TCP protocol's DNS query,such as google's 8.8.8.8,Proxy's DNS anti pollution server theory is starting a local DNS proxy server,It uses TCP to conduct DNS queries through father proxy. If it encrypted communicate with father proxy,Then you can make a safe and pollution-free DNS analysis.
|
||||
It is well known that DNS is a service which use UDP protocol and 53 port,But with the development of network, some well-known DNS servers also support TCP protocol's DNS query,such as google's 8.8.8.8,Proxy's DNS anti pollution server theory is starting a local DNS proxy server,It uses TCP to conduct DNS queries through father proxy. If it encrypted communicate with father proxy,Then you can make a safe and pollution-free DNS analysis.
|
||||
|
||||
#### **8.2.Use examples**
|
||||
|
||||
@ -1188,24 +1222,24 @@ Then the local UDP port 53 provides the DNS analysis.
|
||||
|
||||
***8.2.3 TLS encrypted HTTP(S) father proxy***
|
||||
Suppose there is a father proxy:2.2.2.2:33080
|
||||
The orders executed by father proxy:
|
||||
`proxy http -t tls -C proxy.crt -K proxy.key -p :33080`
|
||||
The orders executed by father proxy:
|
||||
`proxy http -t tls -C proxy.crt -K proxy.key -p :33080`
|
||||
local execution:
|
||||
`proxy dns -S http -T tls -P 2.2.2.2:33080 -C proxy.crt -K proxy.key -p :53`
|
||||
Then the local UDP port 53 provides a security and anti pollution DNS analysis.
|
||||
Then the local UDP port 53 provides a security and anti pollution DNS analysis.
|
||||
|
||||
***8.2.4 TLS encrypted SOCKS5 father proxy***
|
||||
Suppose there is a father proxy:2.2.2.2:33080
|
||||
The orders executed by father proxy:
|
||||
`proxy socks -t tls -C proxy.crt -K proxy.key -p :33080`
|
||||
Suppose there is a father proxy:2.2.2.2:33080
|
||||
The orders executed by father proxy:
|
||||
`proxy socks -t tls -C proxy.crt -K proxy.key -p :33080`
|
||||
local execution:
|
||||
`proxy dns -S socks -T tls -P 2.2.2.2:33080 -C proxy.crt -K proxy.key -p :53`
|
||||
`proxy dns -S socks -T tls -P 2.2.2.2:33080 -C proxy.crt -K proxy.key -p :53`
|
||||
Then the local UDP port 53 provides a security and anti pollution DNS analysis.
|
||||
|
||||
***8.2.5 KCP encrypted HTTP(S) father proxy***
|
||||
Suppose there is a father proxy:2.2.2.2:33080
|
||||
The orders executed by father proxy:
|
||||
`proxy http -t kcp -p :33080`
|
||||
`proxy http -t kcp -p :33080`
|
||||
local execution:
|
||||
`proxy dns -S http -T kcp -P 2.2.2.2:33080 -p :53`
|
||||
Then the local UDP port 53 provides a security and anti pollution DNS analysis.
|
||||
@ -1213,33 +1247,33 @@ Then the local UDP port 53 provides a security and anti pollution DNS analysis.
|
||||
***8.2.6 KCP encrypted SOCKS5 father proxy***
|
||||
Suppose there is a father proxy:2.2.2.2:33080
|
||||
The orders executed by father proxy:
|
||||
`proxy socks -t kcp -p :33080`
|
||||
`proxy socks -t kcp -p :33080`
|
||||
local execution:
|
||||
`proxy dns -S socks -T kcp -P 2.2.2.2:33080 -p :53`
|
||||
`proxy dns -S socks -T kcp -P 2.2.2.2:33080 -p :53`
|
||||
Then the local UDP port 53 provides a security and anti pollution DNS analysis.
|
||||
|
||||
***8.2.7 Custom encrypted HTTP(S) father proxy***
|
||||
Suppose there is a father proxy:2.2.2.2:33080
|
||||
The orders executed by father proxy:
|
||||
`proxy http -t tcp -p :33080 -z password`
|
||||
`proxy http -t tcp -p :33080 -z password`
|
||||
local execution:
|
||||
`proxy dns -S http -T tcp -Z password -P 2.2.2.2:33080 -p :53`
|
||||
`proxy dns -S http -T tcp -Z password -P 2.2.2.2:33080 -p :53`
|
||||
Then the local UDP port 53 provides a security and anti pollution DNS analysis.
|
||||
|
||||
***8.2.8 Custom encrypted SOCKS5 father proxy***
|
||||
Suppose there is a father proxy:2.2.2.2:33080
|
||||
The orders executed by father proxy:
|
||||
`proxy socks -t kcp -p :33080 -z password`
|
||||
`proxy socks -t kcp -p :33080 -z password`
|
||||
local execution:
|
||||
`proxy dns -S socks -T tcp -Z password -P 2.2.2.2:33080 -p :53`
|
||||
Then the local UDP port 53 provides a security and anti pollution DNS analysis.
|
||||
|
||||
### TODO
|
||||
### TODO
|
||||
- HTTP, socks proxy which has multi parents proxy load balancing?
|
||||
- HTTP (s) proxy support PAC?
|
||||
- Welcome joining group feedback...
|
||||
- Welcome joining group feedback...
|
||||
|
||||
### How to use the source code?
|
||||
### How to use the source code?
|
||||
|
||||
Recommend go1.10.1.
|
||||
`go get github.com/snail007/goproxy`
|
||||
@ -1247,20 +1281,19 @@ 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.
|
||||
Proxy is licensed under GPLv3 license.
|
||||
|
||||
### Contact
|
||||
proxy QQ group:189618940
|
||||
proxy QQ group: 793015219 , 189618940 (full)
|
||||
|
||||
### Donation
|
||||
if proxy help you a lot,you can support us by:
|
||||
### AliPay
|
||||
<img src="https://github.com/snail007/goproxy/blob/master/docs/images/alipay.jpg?raw=true" width="200"/>
|
||||
|
||||
### Wechat Pay
|
||||
<img src="https://github.com/snail007/goproxy/blob/master/docs/images/wxpay.jpg?raw=true" width="200"/>
|
||||
if proxy help you a lot,you can support us by:
|
||||
|
||||
### AliPay
|
||||
<img src="https://github.com/snail007/goproxy/blob/master/docs/images/alipay.jpg?raw=true" width="200"/>
|
||||
|
||||
|
||||
### Wechat Pay
|
||||
<img src="https://github.com/snail007/goproxy/blob/master/docs/images/wxpay.jpg?raw=true" width="200"/>
|
||||
|
||||
71
README_ZH.md
71
README_ZH.md
@ -1,7 +1,7 @@
|
||||
<img src="https://github.com/snail007/goproxy/blob/master/docs/images/logo.jpg?raw=true" width="200"/>
|
||||
Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5,ss代理服务器,支持正向代理、反向代理、透明代理、内网穿透、TCP/UDP端口映射、SSH中转、TLS加密传输、协议转换、防污染DNS代理。
|
||||
|
||||
[点击下载](https://github.com/snail007/goproxy/releases) 官方QQ交流群:189618940
|
||||
[点击下载](https://github.com/snail007/goproxy/releases) 官方QQ交流群: 793015219 (2群), 189618940 (1群满)
|
||||
|
||||
---
|
||||
|
||||
@ -9,11 +9,11 @@ Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5,ss代理服
|
||||
|
||||
**[English Manual](/README.md)**
|
||||
|
||||
**[全平台图形界面版本](/gui/README.md)**
|
||||
**[全平台图形界面版本](/gui/README_ZH.md)**
|
||||
|
||||
**[全平台SDK](/sdk/README.md)**
|
||||
**[全平台SDK](https://github.com/snail007/goproxy-sdk/blob/master/README_ZH.md)**
|
||||
|
||||
**[GoProxy特殊授权](/AUTHORIZATION.md)**
|
||||
**[GoProxy特殊授权](/AUTHORIZATION_ZH.md)**
|
||||
|
||||
### 如何贡献代码(Pull Request)?
|
||||
|
||||
@ -56,7 +56,7 @@ Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5,ss代理服
|
||||
- ...
|
||||
|
||||
|
||||
本页是v5.4手册,其他版本手册请点击[这里](docs/old-release.md)查看.
|
||||
本页是v5.4手册,其他版本手册请点击[这里](docs/old-release-zh.md)查看.
|
||||
|
||||
|
||||
### 怎么找到组织?
|
||||
@ -99,7 +99,8 @@ Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5,ss代理服
|
||||
- [1.15 限速](#115-限速)
|
||||
- [1.16 指定出口IP](#116-指定出口ip)
|
||||
- [1.17 证书参数使用base64数据](#117-证书参数使用base64数据)
|
||||
- [1.18 查看帮助](#118-查看帮助)
|
||||
- [1.18 智能模式](#118-智能模式)
|
||||
- [1.19 查看帮助](#119-查看帮助)
|
||||
- [2. TCP代理(端口映射)](#2tcp代理)
|
||||
- [2.1 普通一级TCP代理](#21普通一级tcp代理)
|
||||
- [2.2 普通二级TCP代理](#22普通二级tcp代理)
|
||||
@ -144,7 +145,8 @@ Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5,ss代理服
|
||||
- [5.14 指定出口IP](#514-指定出口ip)
|
||||
- [5.15 级联认证](#515-级联认证)
|
||||
- [5.16 证书参数使用base64数据](#516-证书参数使用base64数据)
|
||||
- [5.17 查看帮助](#517查看帮助)
|
||||
- [5.17 智能模式](#517-智能模式)
|
||||
- [5.18 查看帮助](#518-查看帮助)
|
||||
- [6. 代理协议转换](#6代理协议转换)
|
||||
- [6.1 功能介绍](#61-功能介绍)
|
||||
- [6.2 HTTP(S)转HTTP(S)+SOCKS5+SS](#62-https转httpssocks5ss)
|
||||
@ -200,6 +202,9 @@ chmod +x install.sh
|
||||
```
|
||||
|
||||
#### Docker安装
|
||||
|
||||
[docker](https://hub.docker.com/r/snail007/goproxy)
|
||||
|
||||
项目根目录的Dockerfile文件用来构建,使用golang 1.10.3,构建基于goproxy的master分支最新版本,
|
||||
全部大小17.3MB,默认情况下使用master分支,不过可以通过修改配置文件Dockerfile
|
||||
或者使用参数GOPROXY_VERSION指定构建的goproxy版本.
|
||||
@ -364,11 +369,12 @@ weight 根据每个上级的权重和连接数情况,选择出一个上级
|
||||
比如:
|
||||
`./proxy http -t tcp -p ":33080" --auth-url "http://test.com/auth.php"`
|
||||
用户连接的时候,proxy会GET方式请求这url("http://test.com/auth.php"),
|
||||
带上user,pass,ip,target四个参数:
|
||||
http://test.com/auth.php?user={USER}&pass={PASS}&ip={IP}&target={TARGET}
|
||||
带上user,pass,ip,local_ip,target五个参数:
|
||||
http://test.com/auth.php?user={USER}&pass={PASS}&ip={IP}&local_ip={LOCAL_IP}&target={TARGET}
|
||||
user:用户名
|
||||
pass:密码
|
||||
ip:用户的IP,比如:192.168.1.200
|
||||
local_ip:用户访问的服务器的IP,比如:3.3.3.3
|
||||
target:用户访问的URL,比如:http://demo.com:80/1.html或https://www.baidu.com:80
|
||||
|
||||
如果没有-a或-F或--auth-url参数,就是关闭Basic认证.
|
||||
@ -376,7 +382,7 @@ target:用户访问的URL,比如:http://demo.com:80/1.html或https://www.baidu.c
|
||||
#### **1.6.HTTP代理流量强制走上级HTTP代理**
|
||||
默认情况下,proxy会智能判断一个网站域名是否无法访问,如果无法访问才走上级HTTP代理.通过--always可以使全部HTTP代理流量强制走上级HTTP代理.
|
||||
`./proxy http --always -t tls -p ":28080" -T tls -P "22.22.22.22:38080" -C proxy.crt -K proxy.key`
|
||||
|
||||
|
||||
#### **1.7.HTTP(S)通过SSH中转**
|
||||

|
||||
说明:ssh中转的原理是利用了ssh的转发功能,就是你连接上ssh之后,可以通过ssh代理访问目标地址.
|
||||
@ -535,7 +541,7 @@ HTTP(S)代理支持上级负载均衡,多个上级重复-P参数即可.
|
||||
|
||||
### **1.15 限速**
|
||||
|
||||
限速100K,通过`-l`参数即可指定,比如:100K 1.5M . 0意味着无限制.
|
||||
限速100K,通过`-l`参数即可指定,比如:100K 2000K 1M . 0意味着无限制.
|
||||
|
||||
`proxy http -t tcp -p 2.2.2.2:33080 -l 100K`
|
||||
|
||||
@ -551,7 +557,15 @@ HTTP(S)代理支持上级负载均衡,多个上级重复-P参数即可.
|
||||
|
||||
如果是base64://开头,那么就认为后面的数据是base64编码的,会解码后使用.
|
||||
|
||||
#### **1.18 查看帮助**
|
||||
#### **1.18 智能模式**
|
||||
智能模式设置,可以是intelligent|direct|parent三者之一.
|
||||
默认是:intelligent.
|
||||
每个值的含义如下:
|
||||
`--intelligent=direct`,不在blocked里面的目标都直连.
|
||||
`--intelligent=parent`,不在direct里面的目标都走上级.
|
||||
`--intelligent=intelligent`,blocked和direct里面都没有的目标,智能判断是否使用上级访问目标.
|
||||
|
||||
#### **1.19 查看帮助**
|
||||
`./proxy help http`
|
||||
|
||||
### **2.TCP代理**
|
||||
@ -905,11 +919,12 @@ SOCKS5代理,支持CONNECT,UDP协议,不支持BIND,支持用户名密码认证.
|
||||
比如:
|
||||
`./proxy socks -t tcp -p ":33080" --auth-url "http://test.com/auth.php"`
|
||||
用户连接的时候,proxy会GET方式请求这url("http://test.com/auth.php"),
|
||||
带上user,pass,ip,三个参数:
|
||||
http://test.com/auth.php?user={USER}&pass={PASS}&ip={IP}
|
||||
带上user,pass,ip,local_ip四个参数:
|
||||
http://test.com/auth.php?user={USER}&pass={PASS}&ip={IP}&local_ip={LOCAL_IP}
|
||||
user:用户名
|
||||
pass:密码
|
||||
ip:用户的IP,比如:192.168.1.200
|
||||
local_ip:用户访问的服务器的IP,比如:3.3.3.3
|
||||
|
||||
如果没有-a或-F或--auth-url参数,就是关闭认证.
|
||||
|
||||
@ -1001,7 +1016,7 @@ SOCKS代理支持上级负载均衡,多个上级重复-P参数即可.
|
||||
|
||||
#### **5.13 限速**
|
||||
|
||||
限速100K,通过`-l`参数即可指定,比如:100K 1.5M . 0意味着无限制.
|
||||
限速100K,通过`-l`参数即可指定,比如:100K 2000K 1M . 0意味着无限制.
|
||||
|
||||
`proxy socks -t tcp -p 2.2.2.2:33080 -l 100K`
|
||||
|
||||
@ -1030,7 +1045,15 @@ SOCKS5支持级联认证,-A可以设置上级认证信息.
|
||||
如果是base64://开头,那么就认为后面的数据是base64编码的,会解码后使用.
|
||||
|
||||
|
||||
#### **5.17.查看帮助**
|
||||
#### **5.17 智能模式**
|
||||
智能模式设置,可以是intelligent|direct|parent三者之一.
|
||||
默认是:intelligent.
|
||||
每个值的含义如下:
|
||||
`--intelligent=direct`,不在blocked里面的目标都直连.
|
||||
`--intelligent=parent`,不在direct里面的目标都走上级.
|
||||
`--intelligent=intelligent`,blocked和direct里面都没有的目标,智能判断是否使用上级访问目标.
|
||||
|
||||
#### **5.18.查看帮助**
|
||||
`./proxy help socks`
|
||||
|
||||
### **6.代理协议转换**
|
||||
@ -1137,6 +1160,18 @@ target:如果客户端是http(s)代理请求,这里代表的是请求的完整ur
|
||||
如果没有-a或-F或--auth-url参数,就是关闭本地认证.
|
||||
如果没有-A参数,连接上级不使用认证.
|
||||
|
||||
**设置单独认证信息**
|
||||
|
||||
如果存在多个不同上级,而且他们的密码有的一样有的不一样,那么可以针对每个上级设置认证信息,
|
||||
同时还可以用-A参数设置一个全局认证信息,如果某个上级没有单独设置认证信息就使用全局设置的认证信息.
|
||||
认证信息和上级写在一起.
|
||||
格式是: YTpi#2.2.2.2:33080@1
|
||||
说明:
|
||||
YTpi 是经过base64编码的认证信息,比如是http(s)/socks原始认证信息a:b,用户是a密码是b,base64编码之后是:YTpi
|
||||
如果是ss,那么a就是加密方法,b是密码,比如:aes-192-cfb:your_pass,base64编码之后是:YWVzLTE5Mi1jZmI6eW91cl9wYXNz
|
||||
# 是间隔符号,如果有认证信息,必须有#,没有认证信息可以省略#
|
||||
2.2.2.2:33080 是上级地址
|
||||
@1 是设置权重,没有可以省略,详细说明可以参考手册***权重部分***
|
||||
|
||||
#### **6.8 自定义加密**
|
||||
proxy的sps代理在tcp之上可以通过tls标准加密以及kcp协议加密tcp数据,除此之外还支持在tls和kcp之后进行
|
||||
@ -1211,7 +1246,7 @@ sps下级,限速100K
|
||||
|
||||
`proxy sps -S socks -P 2.2.2.2:33080 -T tcp -Z password -l 100K -t tcp -p :33080`
|
||||
|
||||
通过`-l`参数即可指定,比如:100K 1.5M . 0意味着无限制.
|
||||
通过`-l`参数即可指定,比如:100K 2000K 1M . 0意味着无限制.
|
||||
|
||||
#### **6.12 指定出口IP**
|
||||
|
||||
@ -1350,7 +1385,7 @@ utils是工具包,service是具体的每个服务类.
|
||||
### License
|
||||
Proxy is licensed under GPLv3 license.
|
||||
### Contact
|
||||
QQ交流群:189618940
|
||||
官方QQ交流群: 793015219 (2群), 189618940 (1群满)
|
||||
|
||||
|
||||
### Donation
|
||||
|
||||
@ -117,6 +117,7 @@ func initConfig() (err error) {
|
||||
httpArgs.ParentKey = http.Flag("parent-key", "the password for auto encrypt/decrypt parent connection data").Short('Z').Default("").String()
|
||||
httpArgs.LocalCompress = http.Flag("local-compress", "auto compress/decompress data on local connection").Short('m').Default("false").Bool()
|
||||
httpArgs.ParentCompress = http.Flag("parent-compress", "auto compress/decompress data on parent connection").Short('M').Default("false").Bool()
|
||||
httpArgs.Intelligent = http.Flag("intelligent", "settting intelligent HTTP, SOCKS5 proxy mode, can be <intelligent|direct|parent>").Default("intelligent").Enum("intelligent", "direct", "parent")
|
||||
httpArgs.LoadBalanceMethod = http.Flag("lb-method", "load balance method when use multiple parent,can be <roundrobin|leastconn|leasttime|hash|weight>").Default("roundrobin").Enum("roundrobin", "weight", "leastconn", "leasttime", "hash")
|
||||
httpArgs.LoadBalanceTimeout = http.Flag("lb-timeout", "tcp milliseconds timeout of connecting to parent").Default("500").Int()
|
||||
httpArgs.LoadBalanceRetryTime = http.Flag("lb-retrytime", "sleep time milliseconds after checking").Default("1000").Int()
|
||||
@ -221,7 +222,7 @@ func initConfig() (err error) {
|
||||
tunnelBridgeArgs.Timeout = tunnelBridge.Flag("timeout", "tcp timeout with milliseconds").Short('t').Default("2000").Int()
|
||||
tunnelBridgeArgs.Local = tunnelBridge.Flag("local", "local ip:port to listen").Short('p').Default(":33080").String()
|
||||
|
||||
//########ssh#########
|
||||
//########socks#########
|
||||
socks := app.Command("socks", "proxy on ssh mode")
|
||||
socksArgs.Parent = socks.Flag("parent", "parent ssh address, such as: \"23.32.32.19:22\"").Default("").Short('P').Strings()
|
||||
socksArgs.ParentType = socks.Flag("parent-type", "parent protocol type <tls|tcp|kcp|ssh>").Default("tcp").Short('T').Enum("tls", "tcp", "kcp", "ssh")
|
||||
@ -253,6 +254,7 @@ func initConfig() (err error) {
|
||||
socksArgs.ParentKey = socks.Flag("parent-key", "the password for auto encrypt/decrypt parent connection data").Short('Z').Default("").String()
|
||||
socksArgs.LocalCompress = socks.Flag("local-compress", "auto compress/decompress data on local connection").Short('m').Default("false").Bool()
|
||||
socksArgs.ParentCompress = socks.Flag("parent-compress", "auto compress/decompress data on parent connection").Short('M').Default("false").Bool()
|
||||
socksArgs.Intelligent = socks.Flag("intelligent", "settting intelligent HTTP, SOCKS5 proxy mode, can be <intelligent|direct|parent>").Default("intelligent").Enum("intelligent", "direct", "parent")
|
||||
socksArgs.LoadBalanceMethod = socks.Flag("lb-method", "load balance method when use multiple parent,can be <roundrobin|leastconn|leasttime|hash|weight>").Default("roundrobin").Enum("roundrobin", "weight", "leastconn", "leasttime", "hash")
|
||||
socksArgs.LoadBalanceTimeout = socks.Flag("lb-timeout", "tcp milliseconds timeout of connecting to parent").Default("500").Int()
|
||||
socksArgs.LoadBalanceRetryTime = socks.Flag("lb-retrytime", "sleep time milliseconds after checking").Default("1000").Int()
|
||||
@ -262,7 +264,7 @@ func initConfig() (err error) {
|
||||
socksArgs.BindListen = socks.Flag("bind-listen", "using listener binding IP when connect to target").Short('B').Default("false").Bool()
|
||||
socksArgs.Debug = isDebug
|
||||
|
||||
//########socks+http(s)#########
|
||||
//########sps#########
|
||||
sps := app.Command("sps", "proxy on socks+http(s) mode")
|
||||
spsArgs.Parent = sps.Flag("parent", "parent address, such as: \"23.32.32.19:28008\"").Default("").Short('P').Strings()
|
||||
spsArgs.CertFile = sps.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String()
|
||||
@ -301,6 +303,7 @@ func initConfig() (err error) {
|
||||
spsArgs.LoadBalanceOnlyHA = sps.Flag("lb-onlyha", "use only `high availability mode` to choose parent for LB").Default("false").Bool()
|
||||
spsArgs.RateLimit = sps.Flag("rate-limit", "rate limit (bytes/second) of each connection, such as: 100K 1.5M . 0 means no limitation").Short('l').Default("0").String()
|
||||
spsArgs.Jumper = sps.Flag("jumper", "https or socks5 proxies used when connecting to parent, only worked of -T is tls or tcp, format is https://username:password@host:port https://host:port or socks5://username:password@host:port socks5://host:port").Default("").String()
|
||||
spsArgs.ParentTLSSingle = sps.Flag("parent-tls-single", "conntect to parent insecure skip verify").Default("false").Bool()
|
||||
spsArgs.Debug = isDebug
|
||||
|
||||
//########dns#########
|
||||
|
||||
@ -14,7 +14,7 @@ import (
|
||||
)
|
||||
|
||||
type BasicAuther interface {
|
||||
CheckUserPass(username, password, fromIP, ToTarget string) bool
|
||||
CheckUserPass(username, password, userIP, localIP, toTarget string) bool
|
||||
}
|
||||
type Request struct {
|
||||
ver uint8
|
||||
@ -239,15 +239,16 @@ func (s *ServerConn) Target() string {
|
||||
}
|
||||
func (s *ServerConn) Handshake() (err error) {
|
||||
remoteAddr := (*s.conn).RemoteAddr()
|
||||
localAddr := (*s.conn).LocalAddr()
|
||||
//协商开始
|
||||
//method select request
|
||||
var methodReq MethodsRequest
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(time.Second * s.timeout))
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(s.timeout))
|
||||
|
||||
methodReq, e := NewMethodsRequest((*s.conn), s.header)
|
||||
(*s.conn).SetReadDeadline(time.Time{})
|
||||
if e != nil {
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(time.Second * s.timeout))
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(s.timeout))
|
||||
methodReq.Reply(socks5c.Method_NONE_ACCEPTABLE)
|
||||
(*s.conn).SetReadDeadline(time.Time{})
|
||||
err = fmt.Errorf("new methods request fail,ERR: %s", e)
|
||||
@ -264,7 +265,7 @@ func (s *ServerConn) Handshake() (err error) {
|
||||
// }
|
||||
s.method = socks5c.Method_NO_AUTH
|
||||
//method select reply
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(time.Second * s.timeout))
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(s.timeout))
|
||||
err = methodReq.Reply(socks5c.Method_NO_AUTH)
|
||||
(*s.conn).SetReadDeadline(time.Time{})
|
||||
if err != nil {
|
||||
@ -275,7 +276,7 @@ func (s *ServerConn) Handshake() (err error) {
|
||||
} else {
|
||||
//auth
|
||||
if !methodReq.Select(socks5c.Method_USER_PASS) {
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(time.Second * s.timeout))
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(s.timeout))
|
||||
methodReq.Reply(socks5c.Method_NONE_ACCEPTABLE)
|
||||
(*s.conn).SetReadDeadline(time.Time{})
|
||||
err = fmt.Errorf("none method found : Method_USER_PASS")
|
||||
@ -283,7 +284,7 @@ func (s *ServerConn) Handshake() (err error) {
|
||||
}
|
||||
s.method = socks5c.Method_USER_PASS
|
||||
//method reply need auth
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(time.Second * s.timeout))
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(s.timeout))
|
||||
err = methodReq.Reply(socks5c.Method_USER_PASS)
|
||||
(*s.conn).SetReadDeadline(time.Time{})
|
||||
if err != nil {
|
||||
@ -293,7 +294,7 @@ func (s *ServerConn) Handshake() (err error) {
|
||||
//read auth
|
||||
buf := make([]byte, 500)
|
||||
var n int
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(time.Second * s.timeout))
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(s.timeout))
|
||||
n, err = (*s.conn).Read(buf)
|
||||
(*s.conn).SetReadDeadline(time.Time{})
|
||||
if err != nil {
|
||||
@ -305,9 +306,10 @@ func (s *ServerConn) Handshake() (err error) {
|
||||
s.password = string(r[2+r[1]+1:])
|
||||
//err = fmt.Errorf("user:%s,pass:%s", user, pass)
|
||||
//auth
|
||||
_addr := strings.Split(remoteAddr.String(), ":")
|
||||
if s.auth == nil || (*s.auth).CheckUserPass(s.user, s.password, _addr[0], "") {
|
||||
(*s.conn).SetDeadline(time.Now().Add(time.Millisecond * time.Duration(s.timeout)))
|
||||
_userAddr := strings.Split(remoteAddr.String(), ":")
|
||||
_localAddr := strings.Split(localAddr.String(), ":")
|
||||
if s.auth == nil || (*s.auth).CheckUserPass(s.user, s.password, _userAddr[0], _localAddr[0], "") {
|
||||
(*s.conn).SetDeadline(time.Now().Add(s.timeout))
|
||||
_, err = (*s.conn).Write([]byte{0x01, 0x00})
|
||||
(*s.conn).SetDeadline(time.Time{})
|
||||
if err != nil {
|
||||
@ -315,7 +317,7 @@ func (s *ServerConn) Handshake() (err error) {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
(*s.conn).SetDeadline(time.Now().Add(time.Millisecond * time.Duration(s.timeout)))
|
||||
(*s.conn).SetDeadline(time.Now().Add(s.timeout))
|
||||
_, err = (*s.conn).Write([]byte{0x01, 0x01})
|
||||
(*s.conn).SetDeadline(time.Time{})
|
||||
if err != nil {
|
||||
@ -327,7 +329,7 @@ func (s *ServerConn) Handshake() (err error) {
|
||||
}
|
||||
}
|
||||
//request detail
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(time.Second * s.timeout))
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(s.timeout))
|
||||
request, e := NewRequest(*s.conn)
|
||||
(*s.conn).SetReadDeadline(time.Time{})
|
||||
if e != nil {
|
||||
|
||||
@ -1,35 +1,35 @@
|
||||
# 透传用户IP手册
|
||||
# Pass-through user IP manual
|
||||
|
||||
说明:
|
||||
## Description:
|
||||
|
||||
通过Linux的TPROXY功能,可以实现源站服务程序可以看见客户端真实IP,实现该功能需要linux操作系统和程序都要满足一定的条件.
|
||||
By Linux TPROXY function,you can achieve the source Station service program can see the client's real IP, to achieve this feature requires linux operating systems and programs must meet certain conditions.
|
||||
|
||||
环境要求:
|
||||
## Environmental requirements:
|
||||
|
||||
源站必须是运行在Linux上面的服务程序,同时Linux需要满足下面条件:
|
||||
The source station must be a service program running on Linux, and Linux needs to meet the following conditions:
|
||||
|
||||
1.Linux内核版本 >= 2.6.28
|
||||
1. Linux kernel version >= 2.6.28
|
||||
|
||||
2.判断系统是否支持TPROXY,执行:
|
||||
2. Determine whether the system supports TPROXY, execute:
|
||||
|
||||
grep TPROXY /boot/config-`uname -r`
|
||||
|
||||
如果输出有下面的结果说明支持.
|
||||
If the output has the following result description is supported.
|
||||
|
||||
CONFIG_NETFILTER_XT_TARGET_TPROXY=m
|
||||
|
||||
部署步骤:
|
||||
## Deployment steps:
|
||||
|
||||
1.在源站的linux系统里面每次开机启动都要用root权限执行tproxy环境设置脚本:tproxy_setup.sh
|
||||
1. The tproxy environment setup script should be executed with root privileges every time the boot from the source Linux system: tproxy_setup.sh
|
||||
|
||||
2.在源站的linux系统里面使用root权限执行代理proxy
|
||||
2. Execute proxy proxy with root access on the source Linux system
|
||||
|
||||
参数 -tproxy 是开启代理的tproxy功能.
|
||||
## Parameter-tproxy is the tproxy function that turns on the proxy.
|
||||
|
||||
./proxy -tproxy
|
||||
|
||||
2.源站的程序监听的地址IP需要使用:127.0.1.1
|
||||
2. The IP address of the source station to listen to the program requires the use of: `127.0.1.1`
|
||||
|
||||
比如源站以前监听的地址是: 0.0.0.0:8800 , 现在需要修改为:127.0.1.1:8800
|
||||
For example, the address of the source station before listening is: `0.0.0.0:8800`, now need to be modified to: `127.0.1.1:8800`
|
||||
|
||||
3.转发规则里面源站地址必须是对应的,比如上面的:127.0.1.1:8800
|
||||
3. Forwarding rules inside the source address must be the corresponding, such as the above: `127.0.1.1:8800`
|
||||
|
||||
35
core/tproxy/README_ZH.md
Normal file
35
core/tproxy/README_ZH.md
Normal file
@ -0,0 +1,35 @@
|
||||
# 透传用户IP手册
|
||||
|
||||
## 说明:
|
||||
|
||||
通过Linux的TPROXY功能,可以实现源站服务程序可以看见客户端真实IP,实现该功能需要linux操作系统和程序都要满足一定的条件.
|
||||
|
||||
## 环境要求:
|
||||
|
||||
源站必须是运行在Linux上面的服务程序,同时Linux需要满足下面条件:
|
||||
|
||||
1. Linux内核版本 >= 2.6.28
|
||||
|
||||
2. 判断系统是否支持TPROXY,执行:
|
||||
|
||||
grep TPROXY /boot/config-`uname -r`
|
||||
|
||||
如果输出有下面的结果说明支持.
|
||||
|
||||
CONFIG_NETFILTER_XT_TARGET_TPROXY=m
|
||||
|
||||
## 部署步骤:
|
||||
|
||||
1. 在源站的linux系统里面每次开机启动都要用root权限执行tproxy环境设置脚本:tproxy_setup.sh
|
||||
|
||||
2. 在源站的linux系统里面使用root权限执行代理proxy
|
||||
|
||||
## 参数 -tproxy 是开启代理的tproxy功能.
|
||||
|
||||
./proxy -tproxy
|
||||
|
||||
2. 源站的程序监听的地址IP需要使用:127.0.1.1
|
||||
|
||||
比如源站以前监听的地址是: 0.0.0.0:8800 , 现在需要修改为:127.0.1.1:8800
|
||||
|
||||
3. 转发规则里面源站地址必须是对应的,比如上面的:127.0.1.1:8800
|
||||
19
docker/Dockerfile
Normal file
19
docker/Dockerfile
Normal file
@ -0,0 +1,19 @@
|
||||
FROM golang:alpine AS builder
|
||||
WORKDIR $GOPATH
|
||||
ARG GOPROXY_VERSION=master
|
||||
RUN apk update; apk upgrade; \
|
||||
apk add --no-cache ca-certificates git; \
|
||||
cd /go/src/; \
|
||||
mkdir -p github.com/snail007; \
|
||||
cd github.com/snail007; \
|
||||
git clone --depth=1 https://github.com/snail007/goproxy.git; \
|
||||
cd goproxy; \
|
||||
git checkout ${GOPROXY_VERSION}; \
|
||||
CGO_ENABLED=0 GOOS=linux go build -ldflags "-s -w" -a -installsuffix cgo -o proxy; \
|
||||
chmod 0777 proxy
|
||||
|
||||
FROM debian:stable-slim
|
||||
COPY --from=builder /go/src/github.com/snail007/goproxy/proxy /usr/local/bin/
|
||||
# RUN chmod 0777 /usr/local/bin/proxy
|
||||
EXPOSE 80 443
|
||||
CMD /usr/local/bin/proxy http -t tcp -p :80,:443
|
||||
25
docs/old-release-zh.md
Normal file
25
docs/old-release-zh.md
Normal file
@ -0,0 +1,25 @@
|
||||
# Old Versions of Proxy
|
||||
|
||||
- [v5.3手册](https://github.com/snail007/goproxy/tree/v5.3)
|
||||
- [v5.2手册](https://github.com/snail007/goproxy/tree/v5.2)
|
||||
- [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)
|
||||
- [v4.7手册](https://github.com/snail007/goproxy/tree/v4.7)
|
||||
- [v4.6手册](https://github.com/snail007/goproxy/tree/v4.6)
|
||||
- [v4.5手册](https://github.com/snail007/goproxy/tree/v4.5)
|
||||
- [v4.4手册](https://github.com/snail007/goproxy/tree/v4.4)
|
||||
- [v4.3手册](https://github.com/snail007/goproxy/tree/v4.3)
|
||||
- [v4.2手册](https://github.com/snail007/goproxy/tree/v4.2)
|
||||
- [v4.0-v4.1手册](https://github.com/snail007/goproxy/tree/v4.1)
|
||||
- [v3.9手册](https://github.com/snail007/goproxy/tree/v3.9)
|
||||
- [v3.8手册](https://github.com/snail007/goproxy/tree/v3.8)
|
||||
- [v3.6-v3.7手册](https://github.com/snail007/goproxy/tree/v3.6)
|
||||
- [v3.5手册](https://github.com/snail007/goproxy/tree/v3.5)
|
||||
- [v3.4手册](https://github.com/snail007/goproxy/tree/v3.4)
|
||||
- [v3.3手册](https://github.com/snail007/goproxy/tree/v3.3)
|
||||
- [v3.2手册](https://github.com/snail007/goproxy/tree/v3.2)
|
||||
- [v3.1手册](https://github.com/snail007/goproxy/tree/v3.1)
|
||||
- [v3.0手册](https://github.com/snail007/goproxy/tree/v3.0)
|
||||
- [v2.x手册](https://github.com/snail007/goproxy/tree/v2.2)
|
||||
@ -1,25 +1,25 @@
|
||||
# Old Versions of Proxy
|
||||
|
||||
- [v5.3手册](https://github.com/snail007/goproxy/tree/v5.3)
|
||||
- [v5.2手册](https://github.com/snail007/goproxy/tree/v5.2)
|
||||
- [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)
|
||||
- [v4.7手册](https://github.com/snail007/goproxy/tree/v4.7)
|
||||
- [v4.6手册](https://github.com/snail007/goproxy/tree/v4.6)
|
||||
- [v4.5手册](https://github.com/snail007/goproxy/tree/v4.5)
|
||||
- [v4.4手册](https://github.com/snail007/goproxy/tree/v4.4)
|
||||
- [v4.3手册](https://github.com/snail007/goproxy/tree/v4.3)
|
||||
- [v4.2手册](https://github.com/snail007/goproxy/tree/v4.2)
|
||||
- [v4.0-v4.1手册](https://github.com/snail007/goproxy/tree/v4.1)
|
||||
- [v3.9手册](https://github.com/snail007/goproxy/tree/v3.9)
|
||||
- [v3.8手册](https://github.com/snail007/goproxy/tree/v3.8)
|
||||
- [v3.6-v3.7手册](https://github.com/snail007/goproxy/tree/v3.6)
|
||||
- [v3.5手册](https://github.com/snail007/goproxy/tree/v3.5)
|
||||
- [v3.4手册](https://github.com/snail007/goproxy/tree/v3.4)
|
||||
- [v3.3手册](https://github.com/snail007/goproxy/tree/v3.3)
|
||||
- [v3.2手册](https://github.com/snail007/goproxy/tree/v3.2)
|
||||
- [v3.1手册](https://github.com/snail007/goproxy/tree/v3.1)
|
||||
- [v3.0手册](https://github.com/snail007/goproxy/tree/v3.0)
|
||||
- [v2.x手册](https://github.com/snail007/goproxy/tree/v2.2)
|
||||
- [v5.3 Manual](https://github.com/snail007/goproxy/tree/v5.3)
|
||||
- [v5.2 Manual](https://github.com/snail007/goproxy/tree/v5.2)
|
||||
- [v5.1 Manual](https://github.com/snail007/goproxy/tree/v5.1)
|
||||
- [v5.0 Manual](https://github.com/snail007/goproxy/tree/v5.0)
|
||||
- [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-v4.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)
|
||||
@ -1,13 +1,13 @@
|
||||
# Proxy-GUI
|
||||
基于proxy的各平台SDK,作者和众多热心人士开发了各平台的GUI版本的proxy,下面分平台介绍.
|
||||
Based on the proxy platform SDK, the author and many enthusiasts have developed the GUI version of the proxy for each platform.
|
||||
|
||||
## Windows
|
||||
|
||||
- 官方java版本,项目主页:[goproxy-jui](https://github.com/snail007/goproxy-jui)
|
||||
- Official java version, Project Homepage:[goproxy-jui](https://github.com/snail007/goproxy-jui)
|
||||
|
||||
## Linux
|
||||
|
||||
- 官方java版本,项目主页:[goproxy-jui](https://github.com/snail007/goproxy-jui)
|
||||
- Official java version, Project Homepage:[goproxy-jui](https://github.com/snail007/goproxy-jui)
|
||||
|
||||
## MacOS
|
||||
|
||||
@ -15,13 +15,13 @@
|
||||
|
||||
## Android
|
||||
|
||||
- proxy-go,一个非官方实现版本,界面比较简陋,但是够用.下载地址:[proxy-go](https://github.com/snail007/goproxy-gui-stuff/releases/tag/proxy-go-release)
|
||||
- proxy-go,An unofficial implementation version, the interface is relatively simple, but enough.Download address:[proxy-go](https://github.com/snail007/goproxy-gui-stuff/releases/tag/proxy-go-release)
|
||||
|
||||
|
||||
## IOS
|
||||
|
||||
- Coming Soon ...
|
||||
|
||||
## 跨平台
|
||||
## Cross-platform
|
||||
|
||||
- proxy-web,一个跨平台的web UI版本,项目主页:[proxy-web](https://github.com/yincongcyincong/proxy-web)
|
||||
- proxy-web,A cross-platform web UI version,project home page:[proxy-web](https://github.com/yincongcyincong/proxy-web)
|
||||
27
gui/README_ZH.md
Normal file
27
gui/README_ZH.md
Normal file
@ -0,0 +1,27 @@
|
||||
# Proxy-GUI
|
||||
基于proxy的各平台SDK,作者和众多热心人士开发了各平台的GUI版本的proxy,下面分平台介绍.
|
||||
|
||||
## Windows
|
||||
|
||||
- 官方java版本,项目主页:[goproxy-jui](https://github.com/snail007/goproxy-jui)
|
||||
|
||||
## Linux
|
||||
|
||||
- 官方java版本,项目主页:[goproxy-jui](https://github.com/snail007/goproxy-jui)
|
||||
|
||||
## MacOS
|
||||
|
||||
- Coming Soon ...
|
||||
|
||||
## Android
|
||||
|
||||
- proxy-go,一个非官方实现版本,界面比较简陋,但是够用.下载地址:[proxy-go](https://github.com/snail007/goproxy-gui-stuff/releases/tag/proxy-go-release)
|
||||
|
||||
|
||||
## IOS
|
||||
|
||||
- Coming Soon ...
|
||||
|
||||
## 跨平台
|
||||
|
||||
- proxy-web,一个跨平台的web UI版本,项目主页:[proxy-web](https://github.com/yincongcyincong/proxy-web)
|
||||
3
main.go
3
main.go
@ -39,7 +39,7 @@ func Clean(s *services.Service) {
|
||||
fmt.Printf("crashed, err: %s\nstack:\n%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
for _ = range signalChan {
|
||||
for range signalChan {
|
||||
log.Println("Received an interrupt, stopping services...")
|
||||
if s != nil && *s != nil {
|
||||
(*s).Clean()
|
||||
@ -55,4 +55,5 @@ func Clean(s *services.Service) {
|
||||
}
|
||||
}()
|
||||
<-cleanupDone
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
v4.8
|
||||
1.修复了多个服务同时开启日志,只会输出到最后一个日志文件的bug.
|
||||
2.增加了获取sdk版本的Version()方法.
|
||||
259
sdk/README.md
259
sdk/README.md
@ -1,259 +0,0 @@
|
||||
|
||||
# Proxy SDK 使用说明
|
||||
|
||||
支持以下平台:
|
||||
- Android,`.arr`库
|
||||
- IOS,`.framework`库
|
||||
- Windows,`.dll`库
|
||||
- Linux,`.so`库
|
||||
- MacOS,`.dylib`库
|
||||
|
||||
proxy使用gombile实现了一份go代码编译为android和ios平台下面可以直接调用的sdk类库,
|
||||
另外还为linux和windows,MacOS提供sdk支持,基于这些类库,APP开发者可以轻松的开发出各种形式的代理工具。
|
||||
|
||||
# 下面分平台介绍SDK的用法
|
||||
|
||||
## Android SDK
|
||||
|
||||
[](https://github.com/snail007/goproxy-sdk-android/) []() [](https://github.com/snail007/goproxy-sdk-android/releases) [](https://github.com/snail007/goproxy-sdk-android/releases)
|
||||
|
||||
[点击下载Android-SDK](https://github.com/snail007/goproxy-sdk-android/releases)
|
||||
在Android系统提供的sdk形式是一个后缀为.aar的类库文件,开发的时候只需要把arr类库文件引入android项目即可.
|
||||
|
||||
### Android-SDK使用实例
|
||||
|
||||
#### 1.导入包
|
||||
|
||||
```java
|
||||
import snail007.proxy.Porxy
|
||||
```
|
||||
|
||||
#### 2.启动一个服务
|
||||
|
||||
```java
|
||||
String serviceID="http01";//这里serviceID是自定义的唯一标识字符串,保证每个启动的服务不一样即可
|
||||
String serviceArgs="http -p :8080";
|
||||
String err=Proxy.start(serviceID,serviceArgs);
|
||||
if (!err.isEmpty()){
|
||||
//启动失败
|
||||
System.out.println("start fail,error:"+err);
|
||||
}else{
|
||||
//启动成功
|
||||
}
|
||||
```
|
||||
|
||||
#### 3.停止一个服务
|
||||
|
||||
```java
|
||||
String serviceID="http01";
|
||||
Proxy.stop(serviceID);
|
||||
//停止完毕
|
||||
|
||||
```
|
||||
|
||||
## IOS SDK
|
||||
|
||||
[](https://github.com/snail007/goproxy-sdk-ios/) []() [](https://github.com/snail007/goproxy-sdk-ios/releases) [](https://github.com/snail007/goproxy-sdk-ios/releases)
|
||||
|
||||
[点击下载IOS-SDK](https://github.com/snail007/goproxy-sdk-ios/releases)
|
||||
在IOS系统提供的sdk形式是一个后缀为.framework的类库文件夹,开发的时候只需要把类库文件引入项目,然后调用方法即可.
|
||||
|
||||
### IOS-SDK使用实例
|
||||
|
||||
#### 导入包
|
||||
|
||||
```objc
|
||||
#import <Proxy/Proxy.objc.h>
|
||||
```
|
||||
|
||||
#### 2.启动一个服务
|
||||
|
||||
```objc
|
||||
-(IBAction)doStart:(id)sender
|
||||
{
|
||||
//这里serviceID是自定义的唯一标识字符串,保证每个启动的服务不一样
|
||||
NSString *serviceID = @"http01";
|
||||
NSString *serviceArgs = @"http -p :8080";
|
||||
NSString *error = ProxyStart(serviceID,serviceArgs);
|
||||
|
||||
if (error != nil && error.length > 0)
|
||||
{
|
||||
NSLog(@"start error %@",error);
|
||||
}else{
|
||||
NSLog(@"启动成功");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 3.停止一个服务
|
||||
|
||||
```objc
|
||||
-(IBAction)doStop:(id)sender
|
||||
{
|
||||
NSString *serviceID = @"http01";
|
||||
ProxyStop(serviceID);
|
||||
//停止完毕
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Windows SDK
|
||||
[](https://github.com/snail007/goproxy-sdk-windows/) []() [](https://github.com/snail007/goproxy-sdk-windows/releases) [](https://github.com/snail007/goproxy-sdk-windows/releases)
|
||||
|
||||
[点击下载Windows-SDK](https://github.com/snail007/goproxy-sdk-windows/releases)
|
||||
在Windows系统提供的sdk形式是一个后缀为.dll的类库文件,开发的时候只需要把dll类库文件加载,然后调用方法即可.
|
||||
|
||||
### Windows-SDK使用实例
|
||||
C++示例,不需要包含头文件,只需要加载proxy-sdk.dll即可,ieshims.dll需要和proxy-sdk.dll在一起。
|
||||
作者:[yjbdsky](https://github.com/yjbdsky)
|
||||
|
||||
```cpp
|
||||
#include <stdio.h>
|
||||
#include<stdlib.h>
|
||||
#include <string.h>
|
||||
#include<pthread.h>
|
||||
#include<Windows.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef char *(*GOSTART)(char *s);
|
||||
typedef char *(*GOSTOP)(char *s);
|
||||
typedef int(*GOISRUN)(char *s);
|
||||
HMODULE GODLL = LoadLibrary("proxy-sdk.dll");
|
||||
|
||||
char * Start(char * p0,char * p1)
|
||||
{
|
||||
if (GODLL != NULL)
|
||||
{
|
||||
GOSTART gostart = *(GOSTART)(GetProcAddress(GODLL, "Start"));
|
||||
if (gostart != NULL){
|
||||
printf("%s:%s\n",p0, p1);
|
||||
char *ret = gostart(p0,p1);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return "Cannot Find dll";
|
||||
}
|
||||
char * Stop(char * p)
|
||||
{
|
||||
if (GODLL != NULL)
|
||||
{
|
||||
GOSTOP gostop = *(GOSTOP)(GetProcAddress(GODLL, "Stop"));
|
||||
if (gostop != NULL){
|
||||
printf("%s\n", p);
|
||||
char *ret = gostop(p);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return "Cannot Find dll";
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
//这里p0是自定义的唯一标识字符串,保证每个启动的服务不一样
|
||||
char *p0 = "http01";
|
||||
char *p1 = "http -t tcp -p :38080";
|
||||
printf("This is demo application.\n");
|
||||
//启动服务,返回空字符串说明启动成功;返回非空字符串说明启动失败,返回的字符串是错误原因
|
||||
printf("start result %s\n", Start(p0,p1));
|
||||
//停止服务,没有返回值
|
||||
Stop(p0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
C++示例2,请移步:[GoProxyForC](https://github.com/SuperPowerLF2/GoProxyForC)
|
||||
|
||||
## Linux SDK
|
||||
[](https://github.com/snail007/goproxy-sdk-linux/) []() [](https://github.com/snail007/goproxy-sdk-linux/releases) [](https://github.com/snail007/goproxy-sdk-linux/releases)
|
||||
|
||||
[点击下载Linux-SDK](https://github.com/snail007/goproxy-sdk-linux/releases)
|
||||
在Linux系统提供的sdk形式是一个后缀为.so的类库文件,开发的时候只需要把so类库加载,调用方法即可.
|
||||
|
||||
### Linux-SDK使用实例
|
||||
Linux下面使用的sdk是so文件即libproxy-sdk.so,下面写一个简单的C程序示例,调用so库里面的方法.
|
||||
|
||||
`vi test-proxy.c`
|
||||
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include "libproxy-sdk.h"
|
||||
|
||||
int main() {
|
||||
printf("This is demo application.\n");
|
||||
//这里p0是自定义的唯一标识字符串,保证每个启动的服务不一样
|
||||
char *p0 = "http01";
|
||||
char *p1 = "http -t tcp -p :38080";
|
||||
//启动服务,返回空字符串说明启动成功;返回非空字符串说明启动失败,返回的字符串是错误原因
|
||||
printf("start result %s\n",Start(p0,p1));
|
||||
//停止服务,没有返回值
|
||||
Stop(p0);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
#### 编译test-proxy.c ####
|
||||
`export LD_LIBRARY_PATH=./ && gcc -o test-proxy test-proxy.c libproxy-sdk.so`
|
||||
|
||||
#### 执行 ####
|
||||
`./test-proxy`
|
||||
|
||||
## MacOS SDK
|
||||
[](https://github.com/snail007/goproxy-sdk-mac/) []() [](https://github.com/snail007/goproxy-sdk-mac/releases) [](https://github.com/snail007/goproxy-sdk-mac/releases)
|
||||
|
||||
[点击下载MacOS-SDK](https://github.com/snail007/goproxy-sdk-mac/releases)
|
||||
在MacOS系统提供的sdk形式是一个后缀为.dylib的类库文件,开发的时候只需要把so类库加载,调用方法即可.
|
||||
|
||||
### MacOS-SDK使用实例
|
||||
MacOS下面使用的sdk是dylib文件即libproxy-sdk.dylib,下面写一个简单的Obj-C程序示例,调用dylib库里面的方法.
|
||||
|
||||
```objc
|
||||
#import "libproxy-sdk.h"
|
||||
-(IBAction)doStart:(id)sender
|
||||
{
|
||||
char *result = Start("http01", "http -t tcp -p :38080");
|
||||
|
||||
if (result)
|
||||
{
|
||||
printf("started");
|
||||
}else{
|
||||
printf("not started");
|
||||
}
|
||||
|
||||
}
|
||||
-(IBAction)doStop:(id)sender
|
||||
{
|
||||
Stop("http01");
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
### 关于服务
|
||||
proxy的服务有11种,分别是:
|
||||
|
||||
```shell
|
||||
http
|
||||
socks
|
||||
sps
|
||||
tcp
|
||||
udp
|
||||
bridge
|
||||
server
|
||||
client
|
||||
tbridge
|
||||
tserver
|
||||
tclient
|
||||
```
|
||||
服务启动时,如果存在正在运行的相同ID的服务,那么之前的服务会被停掉,后面启动的服务覆盖之前的服务.
|
||||
所以要保证每次启动服务的时候,第一个ID参数唯一.
|
||||
上面这些服务的具体使用方式和具体参数,可以参考[proxy手册](https://github.com/snail007/goproxy/blob/master/README_ZH.md)
|
||||
sdk里面的服务不支持手册里面的:--daemon和--forever参数.
|
||||
|
||||
|
||||
@ -8,7 +8,9 @@ import (
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"runtime/pprof"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/snail007/goproxy/core/lib/kcpcfg"
|
||||
encryptconn "github.com/snail007/goproxy/core/lib/transport/encrypt"
|
||||
@ -31,6 +33,10 @@ var SDK_VERSION = "No Version Provided"
|
||||
|
||||
var (
|
||||
app *kingpin.Application
|
||||
cpuProfilingFile, memProfilingFile, blockProfilingFile,
|
||||
goroutineProfilingFile, threadcreateProfilingFile *os.File
|
||||
isProfiling bool
|
||||
profilingLock = &sync.Mutex{}
|
||||
)
|
||||
|
||||
type LogCallback interface {
|
||||
@ -134,6 +140,7 @@ func StartWithLog(serviceID, serviceArgsStr string, loggerCallback LogCallback)
|
||||
httpArgs.ParentKey = http.Flag("parent-key", "the password for auto encrypt/decrypt parent connection data").Short('Z').Default("").String()
|
||||
httpArgs.LocalCompress = http.Flag("local-compress", "auto compress/decompress data on local connection").Short('m').Default("false").Bool()
|
||||
httpArgs.ParentCompress = http.Flag("parent-compress", "auto compress/decompress data on parent connection").Short('M').Default("false").Bool()
|
||||
httpArgs.Intelligent = http.Flag("intelligent", "settting intelligent HTTP, SOCKS5 proxy mode, can be <intelligent|direct|parent>").Default("intelligent").Enum("intelligent", "direct", "parent")
|
||||
httpArgs.LoadBalanceMethod = http.Flag("lb-method", "load balance method when use multiple parent,can be <roundrobin|leastconn|leasttime|hash|weight>").Default("roundrobin").Enum("roundrobin", "weight", "leastconn", "leasttime", "hash")
|
||||
httpArgs.LoadBalanceTimeout = http.Flag("lb-timeout", "tcp milliseconds timeout of connecting to parent").Default("500").Int()
|
||||
httpArgs.LoadBalanceRetryTime = http.Flag("lb-retrytime", "sleep time milliseconds after checking").Default("1000").Int()
|
||||
@ -270,6 +277,7 @@ func StartWithLog(serviceID, serviceArgsStr string, loggerCallback LogCallback)
|
||||
socksArgs.ParentKey = socks.Flag("parent-key", "the password for auto encrypt/decrypt parent connection data").Short('Z').Default("").String()
|
||||
socksArgs.LocalCompress = socks.Flag("local-compress", "auto compress/decompress data on local connection").Short('m').Default("false").Bool()
|
||||
socksArgs.ParentCompress = socks.Flag("parent-compress", "auto compress/decompress data on parent connection").Short('M').Default("false").Bool()
|
||||
socksArgs.Intelligent = socks.Flag("intelligent", "settting intelligent HTTP, SOCKS5 proxy mode, can be <intelligent|direct|parent>").Default("intelligent").Enum("intelligent", "direct", "parent")
|
||||
socksArgs.LoadBalanceMethod = socks.Flag("lb-method", "load balance method when use multiple parent,can be <roundrobin|leastconn|leasttime|hash|weight>").Default("roundrobin").Enum("roundrobin", "weight", "leastconn", "leasttime", "hash")
|
||||
socksArgs.LoadBalanceTimeout = socks.Flag("lb-timeout", "tcp milliseconds timeout of connecting to parent").Default("500").Int()
|
||||
socksArgs.LoadBalanceRetryTime = socks.Flag("lb-retrytime", "sleep time milliseconds after checking").Default("1000").Int()
|
||||
@ -318,6 +326,7 @@ func StartWithLog(serviceID, serviceArgsStr string, loggerCallback LogCallback)
|
||||
spsArgs.LoadBalanceOnlyHA = sps.Flag("lb-onlyha", "use only `high availability mode` to choose parent for LB").Default("false").Bool()
|
||||
spsArgs.RateLimit = sps.Flag("rate-limit", "rate limit (bytes/second) of each connection, such as: 100K 1.5M . 0 means no limitation").Short('l').Default("0").String()
|
||||
spsArgs.Jumper = sps.Flag("jumper", "https or socks5 proxies used when connecting to parent, only worked of -T is tls or tcp, format is https://username:password@host:port https://host:port or socks5://username:password@host:port socks5://host:port").Default("").String()
|
||||
spsArgs.ParentTLSSingle = sps.Flag("parent-tls-single", "conntect to parent insecure skip verify").Default("false").Bool()
|
||||
spsArgs.Debug = debug
|
||||
|
||||
//########dns#########
|
||||
@ -409,7 +418,7 @@ func StartWithLog(serviceID, serviceArgsStr string, loggerCallback LogCallback)
|
||||
muxClientArgs.KCP = kcpArgs
|
||||
dnsArgs.KCP = kcpArgs
|
||||
|
||||
log := logger.New(os.Stderr, "", logger.Ldate|logger.Ltime)
|
||||
log := logger.New(os.Stdout, "", logger.Ldate|logger.Ltime)
|
||||
flags := logger.Ldate
|
||||
if *debug {
|
||||
flags |= logger.Lshortfile | logger.Lmicroseconds
|
||||
@ -475,3 +484,41 @@ func Stop(serviceID string) {
|
||||
func Version() string {
|
||||
return SDK_VERSION
|
||||
}
|
||||
func StartProfiling(storePath string) {
|
||||
profilingLock.Lock()
|
||||
defer profilingLock.Unlock()
|
||||
if !isProfiling {
|
||||
isProfiling = true
|
||||
if storePath == "" {
|
||||
storePath = "."
|
||||
}
|
||||
cpuProfilingFile, _ = os.Create(filepath.Join(storePath, "cpu.prof"))
|
||||
memProfilingFile, _ = os.Create(filepath.Join(storePath, "memory.prof"))
|
||||
blockProfilingFile, _ = os.Create(filepath.Join(storePath, "block.prof"))
|
||||
goroutineProfilingFile, _ = os.Create(filepath.Join(storePath, "goroutine.prof"))
|
||||
threadcreateProfilingFile, _ = os.Create(filepath.Join(storePath, "threadcreate.prof"))
|
||||
pprof.StartCPUProfile(cpuProfilingFile)
|
||||
}
|
||||
}
|
||||
func StopProfiling() {
|
||||
profilingLock.Lock()
|
||||
defer profilingLock.Unlock()
|
||||
if isProfiling {
|
||||
isProfiling = false
|
||||
pprof.StopCPUProfile()
|
||||
goroutine := pprof.Lookup("goroutine")
|
||||
goroutine.WriteTo(goroutineProfilingFile, 1)
|
||||
heap := pprof.Lookup("heap")
|
||||
heap.WriteTo(memProfilingFile, 1)
|
||||
block := pprof.Lookup("block")
|
||||
block.WriteTo(blockProfilingFile, 1)
|
||||
threadcreate := pprof.Lookup("threadcreate")
|
||||
threadcreate.WriteTo(threadcreateProfilingFile, 1)
|
||||
//close
|
||||
goroutineProfilingFile.Close()
|
||||
memProfilingFile.Close()
|
||||
blockProfilingFile.Close()
|
||||
threadcreateProfilingFile.Close()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -21,5 +21,15 @@ func Version() (ver *C.char) {
|
||||
return C.CString(sdk.Version())
|
||||
}
|
||||
|
||||
//export StartProfiling
|
||||
func StartProfiling(storePath *C.char) {
|
||||
sdk.StartProfiling(C.GoString(storePath))
|
||||
}
|
||||
|
||||
//export StopProfiling
|
||||
func StopProfiling() {
|
||||
sdk.StopProfiling()
|
||||
}
|
||||
|
||||
func main() {
|
||||
}
|
||||
|
||||
@ -66,6 +66,7 @@ type HTTPArgs struct {
|
||||
ParentKey *string
|
||||
LocalCompress *bool
|
||||
ParentCompress *bool
|
||||
Intelligent *string
|
||||
LoadBalanceMethod *string
|
||||
LoadBalanceTimeout *int
|
||||
LoadBalanceRetryTime *int
|
||||
@ -185,7 +186,7 @@ func (s *HTTP) InitService() (err error) {
|
||||
s.InitBasicAuth()
|
||||
//init lb
|
||||
if len(*s.cfg.Parent) > 0 {
|
||||
s.checker = utils.NewChecker(*s.cfg.HTTPTimeout, int64(*s.cfg.Interval), *s.cfg.Blocked, *s.cfg.Direct, s.log)
|
||||
s.checker = utils.NewChecker(*s.cfg.HTTPTimeout, int64(*s.cfg.Interval), *s.cfg.Blocked, *s.cfg.Direct, s.log, *s.cfg.Intelligent)
|
||||
s.InitLB()
|
||||
}
|
||||
if *s.cfg.DNSAddress != "" {
|
||||
@ -209,7 +210,7 @@ func (s *HTTP) InitService() (err error) {
|
||||
return
|
||||
}
|
||||
conn, err := utils.ConnectHost(s.Resolve(s.lb.Select("", *s.cfg.LoadBalanceOnlyHA)), *s.cfg.Timeout*2)
|
||||
if err == nil {
|
||||
if err == nil && conn != nil {
|
||||
conn.SetDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout)))
|
||||
_, err = conn.Write([]byte{0})
|
||||
conn.SetDeadline(time.Time{})
|
||||
@ -385,12 +386,17 @@ func (s *HTTP) OutToTCP(useProxy bool, address string, inConn *net.Conn, req *ut
|
||||
}
|
||||
if useProxy {
|
||||
// s.log.Printf("%v", s.outPool)
|
||||
selectAddr := (*inConn).RemoteAddr().String()
|
||||
if utils.LBMethod(*s.cfg.LoadBalanceMethod) == lb.SELECT_HASH && *s.cfg.LoadBalanceHashTarget {
|
||||
selectAddr = address
|
||||
if *s.cfg.ParentType == "ssh" {
|
||||
outConn, err = s.getSSHConn(address)
|
||||
} else {
|
||||
selectAddr := (*inConn).RemoteAddr().String()
|
||||
if utils.LBMethod(*s.cfg.LoadBalanceMethod) == lb.SELECT_HASH && *s.cfg.LoadBalanceHashTarget {
|
||||
selectAddr = address
|
||||
}
|
||||
lbAddr = s.lb.Select(selectAddr, *s.cfg.LoadBalanceOnlyHA)
|
||||
outConn, err = s.GetParentConn(lbAddr)
|
||||
}
|
||||
lbAddr = s.lb.Select(selectAddr, *s.cfg.LoadBalanceOnlyHA)
|
||||
outConn, err = s.GetParentConn(lbAddr)
|
||||
|
||||
} else {
|
||||
outConn, err = s.GetDirectConn(s.Resolve(address), inLocalAddr)
|
||||
}
|
||||
@ -410,7 +416,7 @@ func (s *HTTP) OutToTCP(useProxy bool, address string, inConn *net.Conn, req *ut
|
||||
if *s.cfg.ParentCompress {
|
||||
outConn = utils.NewCompConn(outConn)
|
||||
}
|
||||
if *s.cfg.ParentKey != "" {
|
||||
if useProxy && *s.cfg.ParentKey != "" {
|
||||
outConn = conncrypt.New(outConn, &conncrypt.Config{
|
||||
Password: *s.cfg.ParentKey,
|
||||
})
|
||||
@ -514,6 +520,9 @@ func (s *HTTP) ConnectSSH() (err error) {
|
||||
s.sshClient.Close()
|
||||
}
|
||||
s.sshClient, err = ssh.Dial("tcp", s.Resolve(s.lb.Select("", *s.cfg.LoadBalanceOnlyHA)), &config)
|
||||
if err != nil {
|
||||
s.log.Printf("connect to ssh %s fail", s.cfg.Parent)
|
||||
}
|
||||
<-s.lockChn
|
||||
return
|
||||
}
|
||||
|
||||
@ -39,6 +39,9 @@ func GetService(name string) *ServiceItem {
|
||||
func Stop(name string) {
|
||||
if s, ok := servicesMap.Load(name); ok && s.(*ServiceItem).S != nil {
|
||||
s.(*ServiceItem).S.Clean()
|
||||
*s.(*ServiceItem) = ServiceItem{}
|
||||
s = nil
|
||||
servicesMap.Store(name, nil)
|
||||
servicesMap.Delete(name)
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,6 +64,7 @@ type SocksArgs struct {
|
||||
ParentKey *string
|
||||
LocalCompress *bool
|
||||
ParentCompress *bool
|
||||
Intelligent *string
|
||||
LoadBalanceMethod *string
|
||||
LoadBalanceTimeout *int
|
||||
LoadBalanceRetryTime *int
|
||||
@ -180,7 +181,7 @@ func (s *Socks) InitService() (err error) {
|
||||
(*s).domainResolver = dnsx.NewDomainResolver(*s.cfg.DNSAddress, *s.cfg.DNSTTL, s.log)
|
||||
}
|
||||
if len(*s.cfg.Parent) > 0 {
|
||||
s.checker = utils.NewChecker(*s.cfg.Timeout, int64(*s.cfg.Interval), *s.cfg.Blocked, *s.cfg.Direct, s.log)
|
||||
s.checker = utils.NewChecker(*s.cfg.Timeout, int64(*s.cfg.Interval), *s.cfg.Blocked, *s.cfg.Direct, s.log, *s.cfg.Intelligent)
|
||||
s.InitLB()
|
||||
}
|
||||
if *s.cfg.ParentType == "ssh" {
|
||||
|
||||
@ -101,7 +101,7 @@ func (s *SPS) proxyUDP(inConn *net.Conn, serverConn *socks.ServerConn) {
|
||||
s.log.Printf("connect %s for udp", serverConn.Target())
|
||||
//socks client
|
||||
|
||||
client, err := s.HandshakeSocksParent(&outconn, "udp", serverConn.Target(), serverConn.AuthData(), false)
|
||||
client, err := s.HandshakeSocksParent(s.getParentAuth(lbAddr), &outconn, "udp", serverConn.Target(), serverConn.AuthData(), false)
|
||||
if err != nil {
|
||||
clean("handshake fail", fmt.Sprintf("%s", err))
|
||||
return
|
||||
|
||||
@ -13,6 +13,7 @@ import (
|
||||
"runtime/debug"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/snail007/goproxy/core/cs/server"
|
||||
@ -20,6 +21,7 @@ import (
|
||||
"github.com/snail007/goproxy/services"
|
||||
"github.com/snail007/goproxy/utils"
|
||||
"github.com/snail007/goproxy/utils/conncrypt"
|
||||
cryptool "github.com/snail007/goproxy/utils/crypt"
|
||||
"github.com/snail007/goproxy/utils/datasize"
|
||||
"github.com/snail007/goproxy/utils/dnsx"
|
||||
"github.com/snail007/goproxy/utils/iolimiter"
|
||||
@ -71,6 +73,7 @@ type SPSArgs struct {
|
||||
LoadBalanceRetryTime *int
|
||||
LoadBalanceHashTarget *bool
|
||||
LoadBalanceOnlyHA *bool
|
||||
ParentTLSSingle *bool
|
||||
|
||||
RateLimit *string
|
||||
RateLimitBytes float64
|
||||
@ -91,6 +94,8 @@ type SPS struct {
|
||||
udpLocalKey []byte
|
||||
udpParentKey []byte
|
||||
jumper *jumper.Jumper
|
||||
parentAuthData *sync.Map
|
||||
parentCipherData *sync.Map
|
||||
}
|
||||
|
||||
func NewSPS() services.Service {
|
||||
@ -100,6 +105,8 @@ func NewSPS() services.Service {
|
||||
serverChannels: []*server.ServerChannel{},
|
||||
userConns: mapx.NewConcurrentMap(),
|
||||
udpRelatedPacketConns: mapx.NewConcurrentMap(),
|
||||
parentAuthData: &sync.Map{},
|
||||
parentCipherData: &sync.Map{},
|
||||
}
|
||||
}
|
||||
func (s *SPS) CheckArgs() (err error) {
|
||||
@ -121,9 +128,11 @@ func (s *SPS) CheckArgs() (err error) {
|
||||
return
|
||||
}
|
||||
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
|
||||
if !*s.cfg.ParentTLSSingle {
|
||||
s.cfg.CertBytes, s.cfg.KeyBytes, err = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
if *s.cfg.CaCertFile != "" {
|
||||
s.cfg.CaCertBytes, err = ioutil.ReadFile(*s.cfg.CaCertFile)
|
||||
@ -166,7 +175,10 @@ func (s *SPS) InitService() (err error) {
|
||||
}
|
||||
|
||||
if len(*s.cfg.Parent) > 0 {
|
||||
s.InitLB()
|
||||
err = s.InitLB()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
err = s.InitBasicAuth()
|
||||
@ -208,6 +220,8 @@ func (s *SPS) StopService() {
|
||||
s.udpParentKey = nil
|
||||
s.udpRelatedPacketConns = nil
|
||||
s.userConns = nil
|
||||
s.parentAuthData = nil
|
||||
s.parentCipherData = nil
|
||||
s = nil
|
||||
}()
|
||||
for _, sc := range s.serverChannels {
|
||||
@ -257,6 +271,9 @@ func (s *SPS) Start(args interface{}, log *logger.Logger) (err error) {
|
||||
} else if *s.cfg.LocalType == "kcp" {
|
||||
err = sc.ListenKCP(s.cfg.KCP, s.callback, s.log)
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if *s.cfg.ParentServiceType == "socks" {
|
||||
err = s.RunSSUDP(addr)
|
||||
} else {
|
||||
@ -431,8 +448,8 @@ func (s *SPS) OutToTCP(inConn *net.Conn) (lbAddr string, err error) {
|
||||
utils.CloseConn(inConn)
|
||||
return
|
||||
}
|
||||
|
||||
if *s.cfg.ParentAuth != "" || *s.cfg.ParentSSKey != "" || s.IsBasicAuth() {
|
||||
ParentAuth := s.getParentAuth(lbAddr)
|
||||
if ParentAuth != "" || *s.cfg.ParentSSKey != "" || s.IsBasicAuth() {
|
||||
forwardBytes = utils.RemoveProxyHeaders(forwardBytes)
|
||||
}
|
||||
|
||||
@ -452,8 +469,8 @@ func (s *SPS) OutToTCP(inConn *net.Conn) (lbAddr string, err error) {
|
||||
pb.WriteString("Connection: Keep-Alive\r\n")
|
||||
|
||||
u := ""
|
||||
if *s.cfg.ParentAuth != "" {
|
||||
a := strings.Split(*s.cfg.ParentAuth, ":")
|
||||
if ParentAuth != "" {
|
||||
a := strings.Split(ParentAuth, ":")
|
||||
if len(a) != 2 {
|
||||
err = fmt.Errorf("parent auth data format error")
|
||||
return
|
||||
@ -504,7 +521,7 @@ func (s *SPS) OutToTCP(inConn *net.Conn) (lbAddr string, err error) {
|
||||
s.log.Printf("connect %s", address)
|
||||
|
||||
//socks client
|
||||
_, err = s.HandshakeSocksParent(&outConn, "tcp", address, auth, false)
|
||||
_, err = s.HandshakeSocksParent(ParentAuth, &outConn, "tcp", address, auth, false)
|
||||
if err != nil {
|
||||
s.log.Printf("handshake fail, %s", err)
|
||||
return
|
||||
@ -517,7 +534,7 @@ func (s *SPS) OutToTCP(inConn *net.Conn) (lbAddr string, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
outConn, err = ss.DialWithRawAddr(&outConn, ra, "", s.parentCipher.Copy())
|
||||
outConn, err = ss.DialWithRawAddr(&outConn, ra, "", s.getParentCipher(lbAddr))
|
||||
if err != nil {
|
||||
err = fmt.Errorf("dial ss parent fail, err : %s", err)
|
||||
return
|
||||
@ -577,10 +594,41 @@ func (s *SPS) InitBasicAuth() (err error) {
|
||||
}
|
||||
return
|
||||
}
|
||||
func (s *SPS) InitLB() {
|
||||
func (s *SPS) InitLB() (err error) {
|
||||
configs := lb.BackendsConfig{}
|
||||
for _, addr := range *s.cfg.Parent {
|
||||
_addrInfo := strings.Split(addr, "@")
|
||||
var _addrInfo []string
|
||||
if strings.Contains(addr, "#") {
|
||||
_s := addr[:strings.Index(addr, "#")]
|
||||
_auth, err := cryptool.CryptTools.Base64Decode(_s)
|
||||
if err != nil {
|
||||
s.log.Printf("decoding parent auth data [ %s ] fail , error : %s", _s, err)
|
||||
return err
|
||||
}
|
||||
_addrInfo = strings.Split(addr[strings.Index(addr, "#")+1:], "@")
|
||||
if *s.cfg.ParentServiceType == "ss" {
|
||||
_s := strings.Split(_auth, ":")
|
||||
m := _s[0]
|
||||
k := _s[1]
|
||||
if m == "" {
|
||||
m = *s.cfg.ParentSSMethod
|
||||
}
|
||||
if k == "" {
|
||||
k = *s.cfg.ParentSSKey
|
||||
}
|
||||
cipher, err := ss.NewCipher(m, k)
|
||||
if err != nil {
|
||||
s.log.Printf("error generating cipher, ssMethod: %s, ssKey: %s, error : %s", m, k, err)
|
||||
return err
|
||||
}
|
||||
s.parentCipherData.Store(_addrInfo[0], cipher)
|
||||
} else {
|
||||
s.parentAuthData.Store(_addrInfo[0], _auth)
|
||||
}
|
||||
|
||||
} else {
|
||||
_addrInfo = strings.Split(addr, "@")
|
||||
}
|
||||
_addr := _addrInfo[0]
|
||||
weight := 1
|
||||
if len(_addrInfo) == 2 {
|
||||
@ -597,6 +645,19 @@ func (s *SPS) InitLB() {
|
||||
}
|
||||
LB := lb.NewGroup(utils.LBMethod(*s.cfg.LoadBalanceMethod), configs, &s.domainResolver, s.log, *s.cfg.Debug)
|
||||
s.lb = &LB
|
||||
return
|
||||
}
|
||||
func (s *SPS) getParentAuth(lbAddr string) string {
|
||||
if v, ok := s.parentAuthData.Load(lbAddr); ok {
|
||||
return v.(string)
|
||||
}
|
||||
return *s.cfg.ParentAuth
|
||||
}
|
||||
func (s *SPS) getParentCipher(lbAddr string) *ss.Cipher {
|
||||
if v, ok := s.parentCipherData.Load(lbAddr); ok {
|
||||
return v.(*ss.Cipher).Copy()
|
||||
}
|
||||
return s.parentCipher.Copy()
|
||||
}
|
||||
func (s *SPS) IsBasicAuth() bool {
|
||||
return *s.cfg.AuthFile != "" || len(*s.cfg.Auth) > 0 || *s.cfg.AuthURL != ""
|
||||
@ -654,12 +715,21 @@ func (s *SPS) GetParentConn(address string) (conn net.Conn, err error) {
|
||||
if *s.cfg.ParentType == "tls" {
|
||||
if s.jumper == nil {
|
||||
var _conn tls.Conn
|
||||
_conn, err = utils.TlsConnectHost(address, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes, s.cfg.CaCertBytes)
|
||||
if *s.cfg.ParentTLSSingle {
|
||||
_conn, err = utils.SingleTlsConnectHost(address, *s.cfg.Timeout, s.cfg.CaCertBytes)
|
||||
} else {
|
||||
_conn, err = utils.TlsConnectHost(address, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes, s.cfg.CaCertBytes)
|
||||
}
|
||||
if err == nil {
|
||||
conn = net.Conn(&_conn)
|
||||
}
|
||||
} else {
|
||||
conf, err := utils.TlsConfig(s.cfg.CertBytes, s.cfg.KeyBytes, s.cfg.CaCertBytes)
|
||||
var conf *tls.Config
|
||||
if *s.cfg.ParentTLSSingle {
|
||||
conf, err = utils.SingleTlsConfig(s.cfg.CaCertBytes)
|
||||
} else {
|
||||
conf, err = utils.TlsConfig(s.cfg.CertBytes, s.cfg.KeyBytes, s.cfg.CaCertBytes)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -691,9 +761,9 @@ func (s *SPS) GetParentConn(address string) (conn net.Conn, err error) {
|
||||
}
|
||||
return
|
||||
}
|
||||
func (s *SPS) HandshakeSocksParent(outconn *net.Conn, network, dstAddr string, auth socks.Auth, fromSS bool) (client *socks.ClientConn, err error) {
|
||||
if *s.cfg.ParentAuth != "" {
|
||||
a := strings.Split(*s.cfg.ParentAuth, ":")
|
||||
func (s *SPS) HandshakeSocksParent(parentAuth string, outconn *net.Conn, network, dstAddr string, auth socks.Auth, fromSS bool) (client *socks.ClientConn, err error) {
|
||||
if parentAuth != "" {
|
||||
a := strings.Split(parentAuth, ":")
|
||||
if len(a) != 2 {
|
||||
err = fmt.Errorf("parent auth data format error")
|
||||
return
|
||||
@ -717,7 +787,9 @@ func (s *SPS) ParentUDPKey() (key []byte) {
|
||||
return []byte(v)[:24]
|
||||
}
|
||||
case "tls":
|
||||
return s.cfg.KeyBytes[:24]
|
||||
if s.cfg.KeyBytes != nil {
|
||||
return s.cfg.KeyBytes[:24]
|
||||
}
|
||||
case "kcp":
|
||||
v := fmt.Sprintf("%x", md5.Sum([]byte(*s.cfg.KCP.Key)))
|
||||
return []byte(v)[:24]
|
||||
|
||||
@ -88,7 +88,7 @@ func (s *SPS) RunSSUDP(addr string) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
client, err := s.HandshakeSocksParent(&outconn, "udp", socksPacket.Addr(), socks.Auth{}, true)
|
||||
client, err := s.HandshakeSocksParent(s.getParentAuth(lbAddr), &outconn, "udp", socksPacket.Addr(), socks.Auth{}, true)
|
||||
if err != nil {
|
||||
clean("handshake fail", fmt.Sprintf("%s", err))
|
||||
return
|
||||
|
||||
38
utils/crypt/misc.go
Normal file
38
utils/crypt/misc.go
Normal file
@ -0,0 +1,38 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
)
|
||||
|
||||
type CryptTool struct{}
|
||||
|
||||
var CryptTools = NewCryptTool()
|
||||
|
||||
func NewCryptTool() *CryptTool {
|
||||
return &CryptTool{}
|
||||
}
|
||||
|
||||
func (encrypt *CryptTool) Base64Encode(str string) string {
|
||||
return string([]byte(base64.StdEncoding.EncodeToString([]byte(str))))
|
||||
}
|
||||
|
||||
func (encrypt *CryptTool) Base64EncodeBytes(bytes []byte) []byte {
|
||||
return []byte(base64.StdEncoding.EncodeToString(bytes))
|
||||
}
|
||||
|
||||
func (encrypt *CryptTool) Base64Decode(str string) (string, error) {
|
||||
by, err := base64.StdEncoding.DecodeString(str)
|
||||
return string(by), err
|
||||
}
|
||||
|
||||
func (encrypt *CryptTool) Base64DecodeBytes(str string) ([]byte, error) {
|
||||
return base64.StdEncoding.DecodeString(str)
|
||||
}
|
||||
|
||||
func (encrypt *CryptTool) MD5(str string) string {
|
||||
hash := md5.New()
|
||||
hash.Write([]byte(str))
|
||||
return hex.EncodeToString(hash.Sum(nil))
|
||||
}
|
||||
@ -122,12 +122,55 @@ func ioCopy(dst io.ReadWriter, src io.ReadWriter) (err error) {
|
||||
}
|
||||
}
|
||||
}
|
||||
func SingleTlsConnectHost(host string, timeout int, caCertBytes []byte) (conn tls.Conn, err error) {
|
||||
h := strings.Split(host, ":")
|
||||
port, _ := strconv.Atoi(h[1])
|
||||
return SingleTlsConnect(h[0], port, timeout, caCertBytes)
|
||||
}
|
||||
func SingleTlsConnect(host string, port, timeout int, caCertBytes []byte) (conn tls.Conn, err error) {
|
||||
conf, err := getRequestSingleTlsConfig(caCertBytes)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
_conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", host, port), time.Duration(timeout)*time.Millisecond)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return *tls.Client(_conn, conf), err
|
||||
}
|
||||
func SingleTlsConfig(caCertBytes []byte) (conf *tls.Config, err error) {
|
||||
return getRequestSingleTlsConfig(caCertBytes)
|
||||
}
|
||||
func getRequestSingleTlsConfig(caCertBytes []byte) (conf *tls.Config, err error) {
|
||||
conf = &tls.Config{InsecureSkipVerify: true}
|
||||
serverCertPool := x509.NewCertPool()
|
||||
if caCertBytes != nil {
|
||||
ok := serverCertPool.AppendCertsFromPEM(caCertBytes)
|
||||
if !ok {
|
||||
err = errors.New("failed to parse root certificate")
|
||||
}
|
||||
conf.RootCAs = serverCertPool
|
||||
conf.VerifyPeerCertificate = func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
|
||||
opts := x509.VerifyOptions{
|
||||
Roots: serverCertPool,
|
||||
}
|
||||
for _, rawCert := range rawCerts {
|
||||
cert, _ := x509.ParseCertificate(rawCert)
|
||||
_, err := cert.Verify(opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
func TlsConnectHost(host string, timeout int, certBytes, keyBytes, caCertBytes []byte) (conn tls.Conn, err error) {
|
||||
h := strings.Split(host, ":")
|
||||
port, _ := strconv.Atoi(h[1])
|
||||
return TlsConnect(h[0], port, timeout, certBytes, keyBytes, caCertBytes)
|
||||
}
|
||||
|
||||
func TlsConnect(host string, port, timeout int, certBytes, keyBytes, caCertBytes []byte) (conn tls.Conn, err error) {
|
||||
conf, err := getRequestTlsConfig(certBytes, keyBytes, caCertBytes)
|
||||
if err != nil {
|
||||
|
||||
@ -102,6 +102,19 @@ func (s *conn) Write(p []byte) (int, error) {
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
func (s *conn) Close() error {
|
||||
if s.Conn != nil {
|
||||
e := s.Conn.Close()
|
||||
s.Conn = nil
|
||||
s.r = nil
|
||||
s.w = nil
|
||||
s.readLimiter = nil
|
||||
s.writeLimiter = nil
|
||||
s.ctx = nil
|
||||
return e
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewReader returns a reader that implements io.Reader with rate limiting.
|
||||
func NewReader(r io.Reader) *Reader {
|
||||
|
||||
@ -72,9 +72,15 @@ func NewGroup(selectType int, configs BackendsConfig, dr *dnsx.DomainResolver, l
|
||||
bks: bks,
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Group) Select(srcAddr string, onlyHa bool) (addr string) {
|
||||
_, addr = g.Select2(srcAddr, onlyHa)
|
||||
return
|
||||
}
|
||||
func (g *Group) Select2(srcAddr string, onlyHa bool) (isEmpty bool, addr string) {
|
||||
addr = ""
|
||||
if len(g.bks) == 1 {
|
||||
return g.bks[0].Address
|
||||
return false, g.bks[0].Address
|
||||
}
|
||||
if onlyHa {
|
||||
g.lock.Lock()
|
||||
@ -84,16 +90,20 @@ func (g *Group) Select(srcAddr string, onlyHa bool) (addr string) {
|
||||
g.log.Printf("############ choosed %s from lastest ############", g.last.Address)
|
||||
printDebug(true, g.log, nil, srcAddr, (*g.selector).Backends())
|
||||
}
|
||||
return g.last.Address
|
||||
return false, g.last.Address
|
||||
}
|
||||
g.last = (*g.selector).SelectBackend(srcAddr)
|
||||
if !g.last.Active && g.last.ConnectUsedMillisecond > 0 {
|
||||
g.log.Printf("###warn### lb selected empty , return default , for : %s", srcAddr)
|
||||
}
|
||||
return g.last.Address
|
||||
return true, g.last.Address
|
||||
}
|
||||
b := (*g.selector).SelectBackend(srcAddr)
|
||||
return b.Address
|
||||
if !b.Active && b.ConnectUsedMillisecond > 0 {
|
||||
g.log.Printf("###warn### lb selected empty , return default , for : %s", srcAddr)
|
||||
return true, b.Address
|
||||
}
|
||||
return false, b.Address
|
||||
|
||||
}
|
||||
func (g *Group) IncreasConns(addr string) {
|
||||
|
||||
@ -106,15 +106,16 @@ func (s *ServerConn) Port() string {
|
||||
}
|
||||
func (s *ServerConn) Handshake() (err error) {
|
||||
remoteAddr := (*s.conn).RemoteAddr()
|
||||
localAddr := (*s.conn).LocalAddr()
|
||||
//协商开始
|
||||
//method select request
|
||||
var methodReq MethodsRequest
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(time.Second * s.timeout))
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(s.timeout))
|
||||
|
||||
methodReq, e := NewMethodsRequest((*s.conn), s.header)
|
||||
(*s.conn).SetReadDeadline(time.Time{})
|
||||
if e != nil {
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(time.Second * s.timeout))
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(s.timeout))
|
||||
methodReq.Reply(Method_NONE_ACCEPTABLE)
|
||||
(*s.conn).SetReadDeadline(time.Time{})
|
||||
err = fmt.Errorf("new methods request fail,ERR: %s", e)
|
||||
@ -123,7 +124,7 @@ func (s *ServerConn) Handshake() (err error) {
|
||||
//log.Printf("%v,s.auth == %v && methodReq.Select(Method_NO_AUTH) %v", methodReq.methods, s.auth, methodReq.Select(Method_NO_AUTH))
|
||||
if s.auth == nil && methodReq.Select(Method_NO_AUTH) && !methodReq.Select(Method_USER_PASS) {
|
||||
// if !methodReq.Select(Method_NO_AUTH) {
|
||||
// (*s.conn).SetReadDeadline(time.Now().Add(time.Second * s.timeout))
|
||||
// (*s.conn).SetReadDeadline(time.Now().Add(s.timeout))
|
||||
// methodReq.Reply(Method_NONE_ACCEPTABLE)
|
||||
// (*s.conn).SetReadDeadline(time.Time{})
|
||||
// err = fmt.Errorf("none method found : Method_NO_AUTH")
|
||||
@ -131,7 +132,7 @@ func (s *ServerConn) Handshake() (err error) {
|
||||
// }
|
||||
s.method = Method_NO_AUTH
|
||||
//method select reply
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(time.Second * s.timeout))
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(s.timeout))
|
||||
err = methodReq.Reply(Method_NO_AUTH)
|
||||
(*s.conn).SetReadDeadline(time.Time{})
|
||||
if err != nil {
|
||||
@ -142,7 +143,7 @@ func (s *ServerConn) Handshake() (err error) {
|
||||
} else {
|
||||
//auth
|
||||
if !methodReq.Select(Method_USER_PASS) {
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(time.Second * s.timeout))
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(s.timeout))
|
||||
methodReq.Reply(Method_NONE_ACCEPTABLE)
|
||||
(*s.conn).SetReadDeadline(time.Time{})
|
||||
err = fmt.Errorf("none method found : Method_USER_PASS")
|
||||
@ -150,7 +151,7 @@ func (s *ServerConn) Handshake() (err error) {
|
||||
}
|
||||
s.method = Method_USER_PASS
|
||||
//method reply need auth
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(time.Second * s.timeout))
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(s.timeout))
|
||||
err = methodReq.Reply(Method_USER_PASS)
|
||||
(*s.conn).SetReadDeadline(time.Time{})
|
||||
if err != nil {
|
||||
@ -160,7 +161,7 @@ func (s *ServerConn) Handshake() (err error) {
|
||||
//read auth
|
||||
buf := make([]byte, 500)
|
||||
var n int
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(time.Second * s.timeout))
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(s.timeout))
|
||||
n, err = (*s.conn).Read(buf)
|
||||
(*s.conn).SetReadDeadline(time.Time{})
|
||||
if err != nil {
|
||||
@ -172,9 +173,10 @@ func (s *ServerConn) Handshake() (err error) {
|
||||
s.password = string(r[2+r[1]+1:])
|
||||
//err = fmt.Errorf("user:%s,pass:%s", user, pass)
|
||||
//auth
|
||||
_addr := strings.Split(remoteAddr.String(), ":")
|
||||
if s.auth == nil || s.auth.CheckUserPass(s.user, s.password, _addr[0], "") {
|
||||
(*s.conn).SetDeadline(time.Now().Add(time.Millisecond * time.Duration(s.timeout)))
|
||||
_userAddr := strings.Split(remoteAddr.String(), ":")
|
||||
_localAddr := strings.Split(localAddr.String(), ":")
|
||||
if s.auth == nil || s.auth.CheckUserPass(s.user, s.password, _userAddr[0], _localAddr[0], "") {
|
||||
(*s.conn).SetDeadline(time.Now().Add(s.timeout))
|
||||
_, err = (*s.conn).Write([]byte{0x01, 0x00})
|
||||
(*s.conn).SetDeadline(time.Time{})
|
||||
if err != nil {
|
||||
@ -182,7 +184,7 @@ func (s *ServerConn) Handshake() (err error) {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
(*s.conn).SetDeadline(time.Now().Add(time.Millisecond * time.Duration(s.timeout)))
|
||||
(*s.conn).SetDeadline(time.Now().Add(s.timeout))
|
||||
_, err = (*s.conn).Write([]byte{0x01, 0x01})
|
||||
(*s.conn).SetDeadline(time.Time{})
|
||||
if err != nil {
|
||||
@ -194,7 +196,7 @@ func (s *ServerConn) Handshake() (err error) {
|
||||
}
|
||||
}
|
||||
//request detail
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(time.Second * s.timeout))
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(s.timeout))
|
||||
request, e := NewRequest(*s.conn)
|
||||
(*s.conn).SetReadDeadline(time.Time{})
|
||||
if e != nil {
|
||||
|
||||
@ -24,13 +24,14 @@ import (
|
||||
)
|
||||
|
||||
type Checker struct {
|
||||
data mapx.ConcurrentMap
|
||||
blockedMap mapx.ConcurrentMap
|
||||
directMap mapx.ConcurrentMap
|
||||
interval int64
|
||||
timeout int
|
||||
isStop bool
|
||||
log *logger.Logger
|
||||
data mapx.ConcurrentMap
|
||||
blockedMap mapx.ConcurrentMap
|
||||
directMap mapx.ConcurrentMap
|
||||
interval int64
|
||||
timeout int
|
||||
isStop bool
|
||||
intelligent string
|
||||
log *logger.Logger
|
||||
}
|
||||
type CheckerItem struct {
|
||||
Domain string
|
||||
@ -43,13 +44,14 @@ type CheckerItem struct {
|
||||
//NewChecker args:
|
||||
//timeout : tcp timeout milliseconds ,connect to host
|
||||
//interval: recheck domain interval seconds
|
||||
func NewChecker(timeout int, interval int64, blockedFile, directFile string, log *logger.Logger) Checker {
|
||||
func NewChecker(timeout int, interval int64, blockedFile, directFile string, log *logger.Logger, intelligent string) Checker {
|
||||
ch := Checker{
|
||||
data: mapx.NewConcurrentMap(),
|
||||
interval: interval,
|
||||
timeout: timeout,
|
||||
isStop: false,
|
||||
log: log,
|
||||
data: mapx.NewConcurrentMap(),
|
||||
interval: interval,
|
||||
timeout: timeout,
|
||||
isStop: false,
|
||||
intelligent: intelligent,
|
||||
log: log,
|
||||
}
|
||||
ch.blockedMap = ch.loadMap(blockedFile)
|
||||
ch.directMap = ch.loadMap(directFile)
|
||||
@ -164,10 +166,19 @@ func (c *Checker) IsBlocked(domain string) (blocked, isInMap bool, failN, succes
|
||||
//log.Printf("%s not in map, blocked true", address)
|
||||
return true, false, 0, 0
|
||||
}
|
||||
item := _item.(CheckerItem)
|
||||
|
||||
return (item.FailCount >= item.SuccessCount) && (time.Now().Unix()-item.Lasttime < 1800), true, item.FailCount, item.SuccessCount
|
||||
switch c.intelligent {
|
||||
case "direct":
|
||||
return false, true, 0, 0
|
||||
case "parent":
|
||||
return true, true, 0, 0
|
||||
case "intelligent":
|
||||
fallthrough
|
||||
default:
|
||||
item := _item.(CheckerItem)
|
||||
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)
|
||||
if err != nil {
|
||||
@ -257,18 +268,23 @@ func (ba *BasicAuth) Add(userpassArr []string) (n int) {
|
||||
}
|
||||
return
|
||||
}
|
||||
func (ba *BasicAuth) CheckUserPass(user, pass, ip, target string) (ok bool) {
|
||||
|
||||
return ba.Check(user+":"+pass, ip, target)
|
||||
func (ba *BasicAuth) Delete(userArr []string) {
|
||||
for _, u := range userArr {
|
||||
ba.data.Remove(u)
|
||||
}
|
||||
}
|
||||
func (ba *BasicAuth) Check(userpass string, ip, target string) (ok bool) {
|
||||
func (ba *BasicAuth) CheckUserPass(user, pass, userIP, localIP, target string) (ok bool) {
|
||||
|
||||
return ba.Check(user+":"+pass, userIP, localIP, target)
|
||||
}
|
||||
func (ba *BasicAuth) Check(userpass string, userIP, localIP, target string) (ok bool) {
|
||||
u := strings.Split(strings.Trim(userpass, " "), ":")
|
||||
if len(u) == 2 {
|
||||
if p, _ok := ba.data.Get(u[0]); _ok {
|
||||
return p.(string) == u[1]
|
||||
}
|
||||
if ba.authURL != "" {
|
||||
err := ba.checkFromURL(userpass, ip, target)
|
||||
err := ba.checkFromURL(userpass, userIP, localIP, target)
|
||||
if err == nil {
|
||||
return true
|
||||
}
|
||||
@ -278,7 +294,7 @@ func (ba *BasicAuth) Check(userpass string, ip, target string) (ok bool) {
|
||||
}
|
||||
return
|
||||
}
|
||||
func (ba *BasicAuth) checkFromURL(userpass, ip, target string) (err error) {
|
||||
func (ba *BasicAuth) checkFromURL(userpass, userIP, localIP, target string) (err error) {
|
||||
u := strings.Split(strings.Trim(userpass, " "), ":")
|
||||
if len(u) != 2 {
|
||||
return
|
||||
@ -290,7 +306,7 @@ func (ba *BasicAuth) checkFromURL(userpass, ip, target string) (err error) {
|
||||
} else {
|
||||
URL += "?"
|
||||
}
|
||||
URL += fmt.Sprintf("user=%s&pass=%s&ip=%s&target=%s", u[0], u[1], ip, url.QueryEscape(target))
|
||||
URL += fmt.Sprintf("user=%s&pass=%s&ip=%s&local_ip=%s&target=%s", u[0], u[1], userIP, localIP, url.QueryEscape(target))
|
||||
getURL := URL
|
||||
var domain string
|
||||
if ba.dns != nil {
|
||||
@ -307,7 +323,7 @@ func (ba *BasicAuth) checkFromURL(userpass, ip, target string) (err error) {
|
||||
if err == nil && code == ba.authOkCode {
|
||||
break
|
||||
} else if err != nil {
|
||||
err = fmt.Errorf("auth fail from url %s,resonse err:%s , %s", URL, err, ip)
|
||||
err = fmt.Errorf("auth fail from url %s,resonse err:%s , %s -> %s", URL, err, userIP, localIP)
|
||||
} else {
|
||||
if len(body) > 0 {
|
||||
err = fmt.Errorf(string(body[0:100]))
|
||||
@ -318,7 +334,7 @@ func (ba *BasicAuth) checkFromURL(userpass, ip, target string) (err error) {
|
||||
if len(b) > 50 {
|
||||
b = b[:50]
|
||||
}
|
||||
err = fmt.Errorf("auth fail from url %s,resonse code: %d, except: %d , %s , %s", URL, code, ba.authOkCode, ip, b)
|
||||
err = fmt.Errorf("auth fail from url %s,resonse code: %d, except: %d , %s -> %s, %s", URL, code, ba.authOkCode, userIP, localIP, b)
|
||||
}
|
||||
if err != nil && tryCount < ba.authRetry {
|
||||
ba.log.Print(err)
|
||||
@ -472,7 +488,8 @@ func (req *HTTPRequest) GetAuthDataStr() (basicInfo string, err error) {
|
||||
return
|
||||
}
|
||||
func (req *HTTPRequest) BasicAuth() (err error) {
|
||||
addr := strings.Split((*req.conn).RemoteAddr().String(), ":")
|
||||
userIP := strings.Split((*req.conn).RemoteAddr().String(), ":")
|
||||
localIP := strings.Split((*req.conn).LocalAddr().String(), ":")
|
||||
URL := ""
|
||||
if req.IsHTTPS() {
|
||||
URL = "https://" + req.Host
|
||||
@ -483,7 +500,7 @@ func (req *HTTPRequest) BasicAuth() (err error) {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
authOk := (*req.basicAuth).Check(string(user), addr[0], URL)
|
||||
authOk := (*req.basicAuth).Check(string(user), userIP[0], localIP[0], URL)
|
||||
//log.Printf("auth %s,%v", string(user), authOk)
|
||||
if !authOk {
|
||||
fmt.Fprintf((*req.conn), "HTTP/1.1 %s Proxy Authentication Required\r\n\r\nProxy Authentication Required", "407")
|
||||
|
||||
Reference in New Issue
Block a user