Compare commits
32 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a3eb0bfde9 | ||
|
|
33e665631d | ||
|
|
375eb9aa66 | ||
|
|
889ce76676 | ||
|
|
abdcae31c9 | ||
|
|
c9f8f6c6fb | ||
|
|
aab899397e | ||
|
|
a933322ef7 | ||
|
|
b9f054c495 | ||
|
|
5c2e6fd109 | ||
|
|
e427263ccf | ||
|
|
a1a2c3f985 | ||
|
|
84458a10e4 | ||
|
|
9dd7bf80c5 | ||
|
|
317d0113fb | ||
|
|
53153da2e6 | ||
|
|
747a94a1c8 | ||
|
|
df94ca5601 | ||
|
|
3cf7788f34 | ||
|
|
af91921070 | ||
|
|
7fc5c30f60 | ||
|
|
c4a7f0fbb0 | ||
|
|
f656773858 | ||
|
|
e208ccee18 | ||
|
|
5980fee788 | ||
|
|
61f791e77d | ||
|
|
907dec42e0 | ||
|
|
8dce99fec6 | ||
|
|
db13b83f44 | ||
|
|
dd8d7dd0d4 | ||
|
|
dd355b5d98 | ||
|
|
1e1999dede |
11
CHANGELOG
11
CHANGELOG
@ -1,4 +1,15 @@
|
||||
proxy更新日志
|
||||
v5.4
|
||||
1.优化了获取本地IP信息导致CPU过高的问题.
|
||||
2.所有服务都增加了--nolog参数,可以关闭日志输出,节省CPU.
|
||||
3.优化sdk,支持并发启动/关闭操作.
|
||||
4.修复了多连接版本的内网穿透,tserver连接不能正确释放的bug.
|
||||
5.内网穿透增加了client/tclient和server/tserver使用代理连接bridge/tbridge的功能,详细内容参考手册.
|
||||
6.TCP端口映射(TCP代理)增加了使用代理连接上级的功能,详细内容参考手册.
|
||||
|
||||
v5.3
|
||||
1.优化了socks_client握手端口判断,避免了sstap测试UDP失败的问题.
|
||||
|
||||
v5.2
|
||||
1.修复了HTTP(S)\SPS反向代理无法正常工作的问题.
|
||||
2.优化了智能判断,减少不必要的DNS解析.
|
||||
|
||||
89
Dockerfile
89
Dockerfile
@ -1,9 +1,82 @@
|
||||
FROM golang:1.10.3-alpine as builder
|
||||
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/ && git clone https://github.com/snail007/goproxy && \
|
||||
cd goproxy && git checkout ${GOPROXY_VERSION} && \
|
||||
go get && CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o proxy
|
||||
FROM alpine:3.7
|
||||
COPY --from=builder /go/src/goproxy/proxy /
|
||||
CMD /proxy ${OPTS}
|
||||
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}
|
||||
14
README.md
14
README.md
@ -48,7 +48,7 @@ PR needs to explain what changes have been made and why you change them.
|
||||
- ...
|
||||
|
||||
|
||||
This page is the v5.2 manual, and the other version of the manual can be checked by the following [link](docs/old-release.md).
|
||||
This page is the v5.3 manual, and the other version of the manual can be checked by the following [link](docs/old-release.md).
|
||||
|
||||
### How to find the organization?
|
||||
[Click to join the proxy group of gitter](https://gitter.im/go-proxy/Lobby?utm_source=share-link&utm_medium=link&utm_campaign=share-link)
|
||||
@ -161,7 +161,7 @@ If the installation fails or your VPS is not a linux64 system, please follow the
|
||||
Download address: https://github.com/snail007/goproxy/releases
|
||||
```shell
|
||||
cd /root/proxy/
|
||||
wget https://github.com/snail007/goproxy/releases/download/v5.0/proxy-linux-amd64.tar.gz
|
||||
wget https://github.com/snail007/goproxy/releases/download/v5.3/proxy-linux-amd64.tar.gz
|
||||
```
|
||||
#### **2.Download the automatic installation script**
|
||||
```shell
|
||||
@ -173,12 +173,12 @@ chmod +x install.sh
|
||||
|
||||
#### Docker installation
|
||||
|
||||
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 version 5.0.
|
||||
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 4.7:
|
||||
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 5.3:
|
||||
|
||||
```
|
||||
ARG GOPROXY_VERSION=v5.0
|
||||
ARG GOPROXY_VERSION=v5.3
|
||||
```
|
||||
|
||||
To Run:
|
||||
@ -188,12 +188,12 @@ sudo docker build .
|
||||
```
|
||||
2. Tag the image:
|
||||
```
|
||||
sudo docker tag <id from previous step> goproxy/goproxy:latest
|
||||
sudo docker tag <id from previous step> snail007/goproxy:latest
|
||||
```
|
||||
3. Run!
|
||||
Just put your arguments to proxy binary in the OPTS environmental variable (this is just a sample http proxy):
|
||||
```
|
||||
sudo docker run -d --restart=always --name goproxy -e OPTS="http -p :33080" -p 33080:33080 goproxy/goproxy:latest
|
||||
sudo docker run -d --restart=always --name goproxy -e OPTS="http -p :33080" -p 33080:33080 snail007/goproxy:latest
|
||||
```
|
||||
4. View logs:
|
||||
```
|
||||
|
||||
66
README_ZH.md
66
README_ZH.md
@ -48,7 +48,7 @@ Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5代理服务
|
||||
- ...
|
||||
|
||||
|
||||
本页是v5.2手册,其他版本手册请点击[这里](docs/old-release.md)查看.
|
||||
本页是v5.4手册,其他版本手册请点击[这里](docs/old-release.md)查看.
|
||||
|
||||
|
||||
### 怎么找到组织?
|
||||
@ -87,14 +87,15 @@ Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5代理服务
|
||||
- [1.12 自定义加密](#112-自定义加密)
|
||||
- [1.13 压缩传输](#113-压缩传输)
|
||||
- [1.14 查看帮助](#114-查看帮助)
|
||||
- [2. TCP代理](#2tcp代理)
|
||||
- [2. TCP代理(端口映射)](#2tcp代理)
|
||||
- [2.1 普通一级TCP代理](#21普通一级tcp代理)
|
||||
- [2.2 普通二级TCP代理](#22普通二级tcp代理)
|
||||
- [2.3 普通三级TCP代理](#23普通三级tcp代理)
|
||||
- [2.4 加密二级TCP代理](#24加密二级tcp代理)
|
||||
- [2.5 加密三级TCP代理](#25加密三级tcp代理)
|
||||
- [2.6 查看帮助](#26查看帮助)
|
||||
- [3. UDP代理](#3udp代理)
|
||||
- [2.6 通过代理连接上级](#26通过代理连接上级)
|
||||
- [2.7 查看帮助](#27查看帮助)
|
||||
- [3. UDP代理(端口映射)](#3udp代理)
|
||||
- [3.1 普通一级UDP代理](#31普通一级udp代理)
|
||||
- [3.2 普通二级UDP代理](#32普通二级udp代理)
|
||||
- [3.3 普通三级UDP代理](#33普通三级udp代理)
|
||||
@ -109,7 +110,8 @@ Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5代理服务
|
||||
- [4.5 高级用法一](#45高级用法一)
|
||||
- [4.6 高级用法一](#46高级用法二)
|
||||
- [4.7 server的-r参数](#47server的-r参数)
|
||||
- [4.8 查看帮助](#48查看帮助)
|
||||
- [4.8 server和client通过代理连接bridge](#48server和client通过代理连接bridge)
|
||||
- [4.9 查看帮助](#49查看帮助)
|
||||
- [5. SOCKS5代理](#5socks5代理)
|
||||
- [5.1 普通SOCKS5代理](#51普通socks5代理)
|
||||
- [5.2 普通二级SOCKS5代理](#52普通二级socks5代理)
|
||||
@ -159,7 +161,7 @@ curl -L https://raw.githubusercontent.com/snail007/goproxy/master/install_auto.s
|
||||
下载地址:https://github.com/snail007/goproxy/releases
|
||||
```shell
|
||||
cd /root/proxy/
|
||||
wget https://github.com/snail007/goproxy/releases/download/v5.1/proxy-linux-amd64.tar.gz
|
||||
wget https://github.com/snail007/goproxy/releases/download/v5.4/proxy-linux-amd64.tar.gz
|
||||
```
|
||||
#### **2.下载自动安装脚本**
|
||||
```shell
|
||||
@ -170,12 +172,12 @@ chmod +x install.sh
|
||||
```
|
||||
|
||||
#### Docker安装
|
||||
项目根目录的Dockerfile文件用来构建,使用golang 1.10.3,构建基于goproxy v5.1,
|
||||
项目根目录的Dockerfile文件用来构建,使用golang 1.10.3,构建基于goproxy的master分支最新版本,
|
||||
全部大小17.3MB,默认情况下使用master分支,不过可以通过修改配置文件Dockerfile
|
||||
或者使用参数GOPROXY_VERSION指定构建的goproxy版本.
|
||||
|
||||
```
|
||||
ARG GOPROXY_VERSION=v5.1
|
||||
ARG GOPROXY_VERSION=v5.3
|
||||
```
|
||||
|
||||
步骤:
|
||||
@ -185,14 +187,14 @@ sudo docker build .
|
||||
```
|
||||
2. 镜像打标签:
|
||||
```
|
||||
sudo docker tag <上一步的结果ID> goproxy/goproxy:latest
|
||||
sudo docker tag <上一步的结果ID> snail007/goproxy:latest
|
||||
```
|
||||
3. 运行
|
||||
参数OPTS的值就是传递给proxy的所有参数
|
||||
比如下面的例子启动了一个http服务:
|
||||
|
||||
```
|
||||
sudo docker run -d --restart=always --name goproxy -e OPTS="http -p :33080" -p 33080:33080 goproxy/goproxy:latest
|
||||
sudo docker run -d --restart=always --name goproxy -e OPTS="http -p :33080" -p 33080:33080 snail007/goproxy:latest
|
||||
```
|
||||
4. 查看日志:
|
||||
```
|
||||
@ -506,7 +508,27 @@ VPS(IP:22.22.22.33)执行:
|
||||
`./proxy tcp -p ":8080" -T tls -P "33.33.33.33:28080" -C proxy.crt -K proxy.key`
|
||||
那么访问本地8080端口就是通过加密TCP隧道访问66.66.66.66的8080端口.
|
||||
|
||||
#### **2.6.查看帮助**
|
||||
#### **2.6.通过代理连接上级**
|
||||
有时候proxy所在的网络不能直接访问外网,需要通过一个https或者socks5代理才能上网,那么这个时候
|
||||
-J参数就可以帮助你让proxy的tcp端口映射的时候通过https或者socks5代理去连接上级-P,将外部端口映射到本地.
|
||||
-J参数格式如下:
|
||||
|
||||
https代理写法:
|
||||
代理需要认证,用户名:username 密码:password
|
||||
https://username:password@host:port
|
||||
代理不需要认证
|
||||
https://host:port
|
||||
|
||||
socks5代理写法:
|
||||
代理需要认证,用户名:username 密码:password
|
||||
socks5://username:password@host:port
|
||||
代理不需要认证
|
||||
socks5://host:port
|
||||
|
||||
host:代理的IP或者域名
|
||||
port:代理的端口
|
||||
|
||||
#### **2.7.查看帮助**
|
||||
`./proxy help tcp`
|
||||
|
||||
### **3.UDP代理**
|
||||
@ -693,7 +715,27 @@ server连接到bridge的时候,如果同时有多个client连接到同一个brid
|
||||
|
||||
4.7.3.LOCAL_IP为空默认是:`0.0.0.0`,CLIENT_LOCAL_HOST为空默认是:`127.0.0.1`;
|
||||
|
||||
#### **4.8.查看帮助**
|
||||
#### **4.8.server和client通过代理连接bridge**
|
||||
有时候server或者client所在的网络不能直接访问外网,需要通过一个https或者socks5代理才能上网,那么这个时候
|
||||
-J参数就可以帮助你让server或者client通过https或者socks5代理去连接bridge.
|
||||
-J参数格式如下:
|
||||
|
||||
https代理写法:
|
||||
代理需要认证,用户名:username 密码:password
|
||||
https://username:password@host:port
|
||||
代理不需要认证
|
||||
https://host:port
|
||||
|
||||
socks5代理写法:
|
||||
代理需要认证,用户名:username 密码:password
|
||||
socks5://username:password@host:port
|
||||
代理不需要认证
|
||||
socks5://host:port
|
||||
|
||||
host:代理的IP或者域名
|
||||
port:代理的端口
|
||||
|
||||
#### **4.9.查看帮助**
|
||||
`./proxy help bridge`
|
||||
`./proxy help server`
|
||||
`./proxy help client`
|
||||
|
||||
14
config.go
14
config.go
@ -4,6 +4,7 @@ import (
|
||||
"bufio"
|
||||
"crypto/sha1"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
logger "log"
|
||||
"os"
|
||||
"os/exec"
|
||||
@ -62,6 +63,7 @@ func initConfig() (err error) {
|
||||
daemon := app.Flag("daemon", "run proxy in background").Default("false").Bool()
|
||||
forever := app.Flag("forever", "run proxy in forever,fail and retry").Default("false").Bool()
|
||||
logfile := app.Flag("log", "log file path").Default("").String()
|
||||
nolog := app.Flag("nolog", "turn off logging").Default("false").Bool()
|
||||
kcpArgs.Key = app.Flag("kcp-key", "pre-shared secret between client and server").Default("secrect").String()
|
||||
kcpArgs.Crypt = app.Flag("kcp-method", "encrypt/decrypt method, can be: aes, aes-128, aes-192, salsa20, blowfish, twofish, cast5, 3des, tea, xtea, xor, sm4, none").Default("aes").Enum("aes", "aes-128", "aes-192", "salsa20", "blowfish", "twofish", "cast5", "3des", "tea", "xtea", "xor", "sm4", "none")
|
||||
kcpArgs.Mode = app.Flag("kcp-mode", "profiles: fast3, fast2, fast, normal, manual").Default("fast").Enum("fast3", "fast2", "fast", "normal", "manual")
|
||||
@ -122,8 +124,8 @@ func initConfig() (err error) {
|
||||
tcpArgs.Timeout = tcp.Flag("timeout", "tcp timeout milliseconds when connect to real server or parent proxy").Short('e').Default("2000").Int()
|
||||
tcpArgs.ParentType = tcp.Flag("parent-type", "parent protocol type <tls|tcp|kcp|udp>").Short('T').Enum("tls", "tcp", "udp", "kcp")
|
||||
tcpArgs.LocalType = tcp.Flag("local-type", "local protocol type <tls|tcp|kcp>").Default("tcp").Short('t').Enum("tls", "tcp", "kcp")
|
||||
tcpArgs.CheckParentInterval = tcp.Flag("check-parent-interval", "check if proxy is okay every interval seconds,zero: means no check").Short('I').Default("3").Int()
|
||||
tcpArgs.Local = tcp.Flag("local", "local ip:port to listen").Short('p').Default(":33080").String()
|
||||
tcpArgs.Jumper = tcp.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").Short('J').Default("").String()
|
||||
|
||||
//########udp#########
|
||||
udp := app.Command("udp", "proxy on udp mode")
|
||||
@ -147,6 +149,7 @@ func initConfig() (err error) {
|
||||
muxServerArgs.Route = muxServer.Flag("route", "local route to client's network, such as: PROTOCOL://LOCAL_IP:LOCAL_PORT@[CLIENT_KEY]CLIENT_LOCAL_HOST:CLIENT_LOCAL_PORT").Short('r').Default("").Strings()
|
||||
muxServerArgs.IsCompress = muxServer.Flag("c", "compress data when tcp|tls mode").Default("false").Bool()
|
||||
muxServerArgs.SessionCount = muxServer.Flag("session-count", "session count which connect to bridge").Short('n').Default("10").Int()
|
||||
muxServerArgs.Jumper = muxServer.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").Short('J').Default("").String()
|
||||
|
||||
//########mux-client#########
|
||||
muxClient := app.Command("client", "proxy on mux client mode")
|
||||
@ -158,6 +161,7 @@ func initConfig() (err error) {
|
||||
muxClientArgs.Key = muxClient.Flag("k", "key same with server").Default("default").String()
|
||||
muxClientArgs.IsCompress = muxClient.Flag("c", "compress data when tcp|tls mode").Default("false").Bool()
|
||||
muxClientArgs.SessionCount = muxClient.Flag("session-count", "session count which connect to bridge").Short('n').Default("10").Int()
|
||||
muxClientArgs.Jumper = muxClient.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").Short('J').Default("").String()
|
||||
|
||||
//########mux-bridge#########
|
||||
muxBridge := app.Command("bridge", "proxy on mux bridge mode")
|
||||
@ -176,6 +180,7 @@ func initConfig() (err error) {
|
||||
tunnelServerArgs.IsUDP = tunnelServer.Flag("udp", "proxy on udp tunnel server mode").Default("false").Bool()
|
||||
tunnelServerArgs.Key = tunnelServer.Flag("k", "client key").Default("default").String()
|
||||
tunnelServerArgs.Route = tunnelServer.Flag("route", "local route to client's network, such as: PROTOCOL://LOCAL_IP:LOCAL_PORT@[CLIENT_KEY]CLIENT_LOCAL_HOST:CLIENT_LOCAL_PORT").Short('r').Default("").Strings()
|
||||
tunnelServerArgs.Jumper = tunnelServer.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").Short('J').Default("").String()
|
||||
|
||||
//########tunnel-client#########
|
||||
tunnelClient := app.Command("tclient", "proxy on tunnel client mode")
|
||||
@ -184,6 +189,7 @@ func initConfig() (err error) {
|
||||
tunnelClientArgs.KeyFile = tunnelClient.Flag("key", "key file for tls").Short('K').Default("proxy.key").String()
|
||||
tunnelClientArgs.Timeout = tunnelClient.Flag("timeout", "tcp timeout with milliseconds").Short('t').Default("2000").Int()
|
||||
tunnelClientArgs.Key = tunnelClient.Flag("k", "key same with server").Default("default").String()
|
||||
tunnelClientArgs.Jumper = tunnelClient.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").Short('J').Default("").String()
|
||||
|
||||
//########tunnel-bridge#########
|
||||
tunnelBridge := app.Command("tbridge", "proxy on tunnel bridge mode")
|
||||
@ -352,7 +358,9 @@ func initConfig() (err error) {
|
||||
}
|
||||
log.SetFlags(flags)
|
||||
|
||||
if *logfile != "" {
|
||||
if *nolog {
|
||||
log.SetOutput(ioutil.Discard)
|
||||
} else if *logfile != "" {
|
||||
f, e := os.OpenFile(*logfile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600)
|
||||
if e != nil {
|
||||
log.Fatal(e)
|
||||
@ -386,6 +394,7 @@ func initConfig() (err error) {
|
||||
for {
|
||||
if cmd != nil {
|
||||
cmd.Process.Kill()
|
||||
time.Sleep(time.Second * 5)
|
||||
}
|
||||
cmd = exec.Command(os.Args[0], args...)
|
||||
cmdReaderStderr, err := cmd.StderrPipe()
|
||||
@ -421,7 +430,6 @@ func initConfig() (err error) {
|
||||
continue
|
||||
}
|
||||
log.Printf("worker %s [PID] %d unexpected exited, restarting...\n", os.Args[0], pid)
|
||||
time.Sleep(time.Second * 5)
|
||||
}
|
||||
}()
|
||||
return
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
# 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)
|
||||
|
||||
@ -5,7 +5,7 @@ if [ -e /tmp/proxy ]; then
|
||||
fi
|
||||
mkdir /tmp/proxy
|
||||
cd /tmp/proxy
|
||||
wget https://github.com/snail007/goproxy/releases/download/v5.2/proxy-linux-amd64.tar.gz
|
||||
wget https://github.com/snail007/goproxy/releases/download/v5.4/proxy-linux-amd64.tar.gz
|
||||
|
||||
# #install proxy
|
||||
tar zxvf proxy-linux-amd64.tar.gz
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
#!/bin/bash
|
||||
openssl genrsa -out proxy.key 2048
|
||||
openssl req -new -key proxy.key -x509 -days 3650 -out proxy.crt -subj /C=CN/ST=BJ/O="Localhost Ltd"/CN=proxy
|
||||
2
main.go
2
main.go
@ -9,7 +9,7 @@ import (
|
||||
"github.com/snail007/goproxy/services"
|
||||
)
|
||||
|
||||
const APP_VERSION = "5.2"
|
||||
const APP_VERSION = "5.4"
|
||||
|
||||
func main() {
|
||||
err := initConfig()
|
||||
|
||||
12
release.sh
12
release.sh
@ -1,5 +1,5 @@
|
||||
#!/bin/bash
|
||||
VER="5.2"
|
||||
VER="5.4"
|
||||
RELEASE="release-${VER}"
|
||||
rm -rf .cert
|
||||
mkdir .cert
|
||||
@ -60,12 +60,12 @@ CGO_ENABLED=0 GOOS=plan9 GOARCH=arm go build -o proxy && tar zcfv "${RELEASE}/pr
|
||||
#solaris
|
||||
CGO_ENABLED=0 GOOS=solaris GOARCH=amd64 go build -o proxy && tar zcfv "${RELEASE}/proxy-solaris-amd64.tar.gz" proxy direct blocked
|
||||
#windows
|
||||
CGO_ENABLED=0 GOOS=windows GOARCH=386 go build -ldflags="-H=windowsgui" -o proxy-wingui.exe
|
||||
CGO_ENABLED=0 GOOS=windows GOARCH=386 go build -o proxy.exe && tar zcfv "${RELEASE}/proxy-windows-386.tar.gz" proxy.exe proxy-wingui.exe direct blocked .cert/proxy.crt .cert/proxy.key
|
||||
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags="-H=windowsgui" -o proxy-wingui.exe
|
||||
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o proxy.exe && tar zcfv "${RELEASE}/proxy-windows-amd64.tar.gz" proxy.exe proxy-wingui.exe direct blocked .cert/proxy.crt .cert/proxy.key
|
||||
CGO_ENABLED=0 GOOS=windows GOARCH=386 go build -ldflags="-H=windowsgui" -o proxy-noconsole.exe
|
||||
CGO_ENABLED=0 GOOS=windows GOARCH=386 go build -o proxy.exe && tar zcfv "${RELEASE}/proxy-windows-386.tar.gz" proxy.exe proxy-noconsole.exe direct blocked .cert/proxy.crt .cert/proxy.key
|
||||
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags="-H=windowsgui" -o proxy-noconsole.exe
|
||||
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o proxy.exe && tar zcfv "${RELEASE}/proxy-windows-amd64.tar.gz" proxy.exe proxy-noconsole.exe direct blocked .cert/proxy.crt .cert/proxy.key
|
||||
|
||||
rm -rf proxy proxy.exe proxy-wingui.exe .cert
|
||||
rm -rf proxy proxy.exe proxy-noconsole.exe .cert
|
||||
|
||||
#todo
|
||||
#1.release.sh VER="xxx"
|
||||
|
||||
@ -1,4 +1,15 @@
|
||||
SDK更新日志
|
||||
v5.4
|
||||
1.去掉了无用参数
|
||||
|
||||
|
||||
v5.3
|
||||
1.增加了支持日志输出回调的方法:
|
||||
StartWithLog(serviceID, serviceArgsStr string, loggerCallback LogCallback)
|
||||
2.优化了socks_client握手端口判断,避免了sstap测试UDP失败的问题..
|
||||
3.修复了HTTP(S)\SPS反向代理无法正常工作的问题.
|
||||
4.优化了智能判断,减少不必要的DNS解析.
|
||||
5.重构了SOCKS和SPS的UDP功能,基于UDP的游戏加速嗖嗖的.
|
||||
|
||||
v4.9
|
||||
1.修复了HTTP Basic代理返回不合适的头部,导致浏览器不会弹框,个别代理插件无法认证的问题.
|
||||
|
||||
@ -25,7 +25,7 @@ proxy使用gombile实现了一份go代码编译为android和ios平台下面可
|
||||
#### 1.导入包
|
||||
|
||||
```java
|
||||
import snail007.proxy.Porxy
|
||||
import snail007.proxy.Proxy
|
||||
```
|
||||
|
||||
#### 2.启动一个服务
|
||||
|
||||
@ -117,7 +117,7 @@ func (s *DNS) StopService() {
|
||||
if e != nil {
|
||||
s.log.Printf("stop dns service crashed,%s", e)
|
||||
} else {
|
||||
s.log.Printf("service dns stoped")
|
||||
s.log.Printf("service dns stopped")
|
||||
}
|
||||
}()
|
||||
Stop(s.serviceKey)
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#/bin/bash
|
||||
VER="v5.0"
|
||||
VER="v5.3"
|
||||
rm -rf sdk-android-*.tar.gz
|
||||
rm -rf android
|
||||
mkdir android
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#/bin/bash
|
||||
VER="v5.0"
|
||||
VER="v5.3"
|
||||
rm -rf sdk-ios-*.tar.gz
|
||||
rm -rf ios
|
||||
mkdir ios
|
||||
|
||||
@ -3,6 +3,7 @@ package proxy
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
logger "log"
|
||||
"os"
|
||||
"path"
|
||||
@ -23,12 +24,31 @@ import (
|
||||
kingpin "gopkg.in/alecthomas/kingpin.v2"
|
||||
)
|
||||
|
||||
const SDK_VERSION = "5.0"
|
||||
const SDK_VERSION = "5.3"
|
||||
|
||||
var (
|
||||
app *kingpin.Application
|
||||
)
|
||||
|
||||
type LogCallback interface {
|
||||
Write(line string)
|
||||
}
|
||||
type logCallback interface {
|
||||
Write(line string)
|
||||
}
|
||||
type logWriter struct {
|
||||
callback LogCallback
|
||||
}
|
||||
|
||||
func (s *logWriter) Write(p []byte) (n int, err error) {
|
||||
s.callback.Write(string(p))
|
||||
return
|
||||
}
|
||||
|
||||
func Start(serviceID, serviceArgsStr string) (errStr string) {
|
||||
return StartWithLog(serviceID, serviceArgsStr, nil)
|
||||
}
|
||||
|
||||
//Start
|
||||
//serviceID : is service identify id,different service's id should be difference
|
||||
//serviceArgsStr: is the whole command line args string
|
||||
@ -38,7 +58,7 @@ var (
|
||||
//and so on.
|
||||
//if an error occured , errStr will be the error reason
|
||||
//if start success, errStr is empty.
|
||||
func Start(serviceID, serviceArgsStr string) (errStr string) {
|
||||
func StartWithLog(serviceID, serviceArgsStr string, loggerCallback LogCallback) (errStr string) {
|
||||
//define args
|
||||
tcpArgs := tcpx.TCPArgs{}
|
||||
httpArgs := httpx.HTTPArgs{}
|
||||
@ -58,6 +78,7 @@ func Start(serviceID, serviceArgsStr string) (errStr string) {
|
||||
app.Author("snail").Version(SDK_VERSION)
|
||||
debug := app.Flag("debug", "debug log output").Default("false").Bool()
|
||||
logfile := app.Flag("log", "log file path").Default("").String()
|
||||
nolog := app.Flag("nolog", "turn off logging").Default("false").Bool()
|
||||
kcpArgs.Key = app.Flag("kcp-key", "pre-shared secret between client and server").Default("secrect").String()
|
||||
kcpArgs.Crypt = app.Flag("kcp-method", "encrypt/decrypt method, can be: aes, aes-128, aes-192, salsa20, blowfish, twofish, cast5, 3des, tea, xtea, xor, sm4, none").Default("aes").Enum("aes", "aes-128", "aes-192", "salsa20", "blowfish", "twofish", "cast5", "3des", "tea", "xtea", "xor", "sm4", "none")
|
||||
kcpArgs.Mode = app.Flag("kcp-mode", "profiles: fast3, fast2, fast, normal, manual").Default("fast3").Enum("fast3", "fast2", "fast", "normal", "manual")
|
||||
@ -118,8 +139,8 @@ func Start(serviceID, serviceArgsStr string) (errStr string) {
|
||||
tcpArgs.Timeout = tcp.Flag("timeout", "tcp timeout milliseconds when connect to real server or parent proxy").Short('e').Default("2000").Int()
|
||||
tcpArgs.ParentType = tcp.Flag("parent-type", "parent protocol type <tls|tcp|kcp|udp>").Short('T').Enum("tls", "tcp", "udp", "kcp")
|
||||
tcpArgs.LocalType = tcp.Flag("local-type", "local protocol type <tls|tcp|kcp>").Default("tcp").Short('t').Enum("tls", "tcp", "kcp")
|
||||
tcpArgs.CheckParentInterval = tcp.Flag("check-parent-interval", "check if proxy is okay every interval seconds,zero: means no check").Short('I').Default("3").Int()
|
||||
tcpArgs.Local = tcp.Flag("local", "local ip:port to listen").Short('p').Default(":33080").String()
|
||||
tcpArgs.Jumper = tcp.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").Short('J').Default("").String()
|
||||
|
||||
//########udp#########
|
||||
udp := app.Command("udp", "proxy on udp mode")
|
||||
@ -143,6 +164,7 @@ func Start(serviceID, serviceArgsStr string) (errStr string) {
|
||||
muxServerArgs.Route = muxServer.Flag("route", "local route to client's network, such as: PROTOCOL://LOCAL_IP:LOCAL_PORT@[CLIENT_KEY]CLIENT_LOCAL_HOST:CLIENT_LOCAL_PORT").Short('r').Default("").Strings()
|
||||
muxServerArgs.IsCompress = muxServer.Flag("c", "compress data when tcp|tls mode").Default("false").Bool()
|
||||
muxServerArgs.SessionCount = muxServer.Flag("session-count", "session count which connect to bridge").Short('n').Default("10").Int()
|
||||
muxServerArgs.Jumper = muxServer.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").Short('J').Default("").String()
|
||||
|
||||
//########mux-client#########
|
||||
muxClient := app.Command("client", "proxy on mux client mode")
|
||||
@ -154,6 +176,7 @@ func Start(serviceID, serviceArgsStr string) (errStr string) {
|
||||
muxClientArgs.Key = muxClient.Flag("k", "key same with server").Default("default").String()
|
||||
muxClientArgs.IsCompress = muxClient.Flag("c", "compress data when tcp|tls mode").Default("false").Bool()
|
||||
muxClientArgs.SessionCount = muxClient.Flag("session-count", "session count which connect to bridge").Short('n').Default("10").Int()
|
||||
muxClientArgs.Jumper = muxClient.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").Short('J').Default("").String()
|
||||
|
||||
//########mux-bridge#########
|
||||
muxBridge := app.Command("bridge", "proxy on mux bridge mode")
|
||||
@ -172,6 +195,7 @@ func Start(serviceID, serviceArgsStr string) (errStr string) {
|
||||
tunnelServerArgs.IsUDP = tunnelServer.Flag("udp", "proxy on udp tunnel server mode").Default("false").Bool()
|
||||
tunnelServerArgs.Key = tunnelServer.Flag("k", "client key").Default("default").String()
|
||||
tunnelServerArgs.Route = tunnelServer.Flag("route", "local route to client's network, such as: PROTOCOL://LOCAL_IP:LOCAL_PORT@[CLIENT_KEY]CLIENT_LOCAL_HOST:CLIENT_LOCAL_PORT").Short('r').Default("").Strings()
|
||||
tunnelServerArgs.Jumper = tunnelServer.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").Short('J').Default("").String()
|
||||
|
||||
//########tunnel-client#########
|
||||
tunnelClient := app.Command("tclient", "proxy on tunnel client mode")
|
||||
@ -180,6 +204,7 @@ func Start(serviceID, serviceArgsStr string) (errStr string) {
|
||||
tunnelClientArgs.KeyFile = tunnelClient.Flag("key", "key file for tls").Short('K').Default("proxy.key").String()
|
||||
tunnelClientArgs.Timeout = tunnelClient.Flag("timeout", "tcp timeout with milliseconds").Short('t').Default("2000").Int()
|
||||
tunnelClientArgs.Key = tunnelClient.Flag("k", "key same with server").Default("default").String()
|
||||
tunnelClientArgs.Jumper = tunnelClient.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").Short('J').Default("").String()
|
||||
|
||||
//########tunnel-bridge#########
|
||||
tunnelBridge := app.Command("tbridge", "proxy on tunnel bridge mode")
|
||||
@ -337,13 +362,21 @@ func Start(serviceID, serviceArgsStr string) (errStr string) {
|
||||
}
|
||||
log.SetFlags(flags)
|
||||
|
||||
if *logfile != "" {
|
||||
if loggerCallback == nil {
|
||||
if *nolog {
|
||||
log.SetOutput(ioutil.Discard)
|
||||
} else if *logfile != "" {
|
||||
f, e := os.OpenFile(*logfile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600)
|
||||
if e != nil {
|
||||
log.Fatal(e)
|
||||
}
|
||||
log.SetOutput(f)
|
||||
}
|
||||
} else {
|
||||
log.SetOutput(&logWriter{
|
||||
callback: loggerCallback,
|
||||
})
|
||||
}
|
||||
|
||||
//regist services and run service
|
||||
switch serviceName {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#/bin/bash
|
||||
VER="v5.0"
|
||||
VER="v5.3"
|
||||
|
||||
rm -rf sdk-linux-*.tar.gz
|
||||
rm -rf README.md libproxy-sdk.so libproxy-sdk.h libproxy-sdk.a
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#/bin/bash
|
||||
VER="v5.0"
|
||||
VER="v5.3"
|
||||
|
||||
rm -rf *.tar.gz
|
||||
rm -rf README.md libproxy-sdk.dylib libproxy-sdk.h
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
#/bin/bash
|
||||
VER="v5.0"
|
||||
VER="v5.3"
|
||||
|
||||
sudo rm /usr/local/go
|
||||
sudo ln -s /usr/local/go1.10.1 /usr/local/go
|
||||
#sudo rm /usr/local/go
|
||||
#sudo ln -s /usr/local/go1.10.1 /usr/local/go
|
||||
rm -rf sdk-windows-*.tar.gz
|
||||
rm -rf README.md proxy-sdk.h proxy-sdk.dll
|
||||
|
||||
@ -22,7 +22,7 @@ cp ../README.md .
|
||||
tar zcf sdk-windows-32bit-${VER}.tar.gz README.md proxy-sdk.dll proxy-sdk.h ieshims.dll
|
||||
rm -rf README.md proxy-sdk.h proxy-sdk.dll
|
||||
|
||||
sudo rm /usr/local/go
|
||||
sudo ln -s /usr/local/go1.8.5 /usr/local/go
|
||||
#sudo rm /usr/local/go
|
||||
#sudo ln -s /usr/local/go1.8.5 /usr/local/go
|
||||
|
||||
echo "done."
|
||||
|
||||
@ -185,11 +185,13 @@ func (s *HTTP) StopService() {
|
||||
if e != nil {
|
||||
s.log.Printf("stop http(s) service crashed,%s", e)
|
||||
} else {
|
||||
s.log.Printf("service http(s) stoped")
|
||||
s.log.Printf("service http(s) stopped")
|
||||
}
|
||||
}()
|
||||
s.isStop = true
|
||||
if *s.cfg.Parent != "" {
|
||||
s.checker.Stop()
|
||||
}
|
||||
if s.sshClient != nil {
|
||||
s.sshClient.Close()
|
||||
}
|
||||
@ -492,7 +494,7 @@ func (s *HTTP) IsDeadLoop(inLocalAddr string, host string) bool {
|
||||
if *s.cfg.DNSAddress != "" {
|
||||
outIPs = []net.IP{net.ParseIP(s.Resolve(outDomain))}
|
||||
} else {
|
||||
outIPs, err = net.LookupIP(outDomain)
|
||||
outIPs, err = utils.MyLookupIP(outDomain)
|
||||
}
|
||||
if err == nil {
|
||||
for _, ip := range outIPs {
|
||||
|
||||
@ -80,7 +80,7 @@ func (s *MuxBridge) StopService() {
|
||||
if e != nil {
|
||||
s.log.Printf("stop bridge service crashed,%s", e)
|
||||
} else {
|
||||
s.log.Printf("service bridge stoped")
|
||||
s.log.Printf("service bridge stopped")
|
||||
}
|
||||
}()
|
||||
s.isStop = true
|
||||
|
||||
@ -12,6 +12,7 @@ import (
|
||||
"github.com/snail007/goproxy/services"
|
||||
"github.com/snail007/goproxy/services/kcpcfg"
|
||||
"github.com/snail007/goproxy/utils"
|
||||
"github.com/snail007/goproxy/utils/jumper"
|
||||
//"github.com/xtaci/smux"
|
||||
smux "github.com/hashicorp/yamux"
|
||||
)
|
||||
@ -28,12 +29,14 @@ type MuxClientArgs struct {
|
||||
IsCompress *bool
|
||||
SessionCount *int
|
||||
KCP kcpcfg.KCPConfigArgs
|
||||
Jumper *string
|
||||
}
|
||||
type MuxClient struct {
|
||||
cfg MuxClientArgs
|
||||
isStop bool
|
||||
sessions utils.ConcurrentMap
|
||||
log *logger.Logger
|
||||
jumper *jumper.Jumper
|
||||
}
|
||||
|
||||
func NewMuxClient() services.Service {
|
||||
@ -65,6 +68,19 @@ func (s *MuxClient) CheckArgs() (err error) {
|
||||
return
|
||||
}
|
||||
}
|
||||
if *s.cfg.Jumper != "" {
|
||||
if *s.cfg.ParentType != "tls" && *s.cfg.ParentType != "tcp" {
|
||||
err = fmt.Errorf("jumper only worked of -T is tls or tcp")
|
||||
return
|
||||
}
|
||||
var j jumper.Jumper
|
||||
j, err = jumper.New(*s.cfg.Jumper, time.Millisecond*time.Duration(*s.cfg.Timeout))
|
||||
if err != nil {
|
||||
err = fmt.Errorf("parse jumper fail, err %s", err)
|
||||
return
|
||||
}
|
||||
s.jumper = &j
|
||||
}
|
||||
return
|
||||
}
|
||||
func (s *MuxClient) StopService() {
|
||||
@ -73,7 +89,7 @@ func (s *MuxClient) StopService() {
|
||||
if e != nil {
|
||||
s.log.Printf("stop client service crashed,%s", e)
|
||||
} else {
|
||||
s.log.Printf("service client stoped")
|
||||
s.log.Printf("service client stopped")
|
||||
}
|
||||
}()
|
||||
s.isStop = true
|
||||
@ -182,15 +198,32 @@ func (s *MuxClient) Clean() {
|
||||
}
|
||||
func (s *MuxClient) getParentConn() (conn net.Conn, err error) {
|
||||
if *s.cfg.ParentType == "tls" {
|
||||
if s.jumper == nil {
|
||||
var _conn tls.Conn
|
||||
_conn, err = utils.TlsConnectHost(*s.cfg.Parent, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes, nil)
|
||||
if err == nil {
|
||||
conn = net.Conn(&_conn)
|
||||
}
|
||||
} else {
|
||||
conf, err := utils.TlsConfig(s.cfg.CertBytes, s.cfg.KeyBytes, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var _c net.Conn
|
||||
_c, err = s.jumper.Dial(*s.cfg.Parent, time.Millisecond*time.Duration(*s.cfg.Timeout))
|
||||
if err == nil {
|
||||
conn = net.Conn(tls.Client(_c, conf))
|
||||
}
|
||||
}
|
||||
|
||||
} else if *s.cfg.ParentType == "kcp" {
|
||||
conn, err = utils.ConnectKCPHost(*s.cfg.Parent, s.cfg.KCP)
|
||||
} else {
|
||||
if s.jumper == nil {
|
||||
conn, err = utils.ConnectHost(*s.cfg.Parent, *s.cfg.Timeout)
|
||||
} else {
|
||||
conn, err = s.jumper.Dial(*s.cfg.Parent, time.Millisecond*time.Duration(*s.cfg.Timeout))
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -15,6 +15,7 @@ import (
|
||||
"github.com/snail007/goproxy/services"
|
||||
"github.com/snail007/goproxy/services/kcpcfg"
|
||||
"github.com/snail007/goproxy/utils"
|
||||
"github.com/snail007/goproxy/utils/jumper"
|
||||
|
||||
"github.com/golang/snappy"
|
||||
//"github.com/xtaci/smux"
|
||||
@ -38,6 +39,7 @@ type MuxServerArgs struct {
|
||||
IsCompress *bool
|
||||
SessionCount *int
|
||||
KCP kcpcfg.KCPConfigArgs
|
||||
Jumper *string
|
||||
}
|
||||
|
||||
type MuxUDPItem struct {
|
||||
@ -121,6 +123,7 @@ func (s *MuxServerManager) Start(args interface{}, log *logger.Logger) (err erro
|
||||
SessionCount: s.cfg.SessionCount,
|
||||
KCP: s.cfg.KCP,
|
||||
ParentType: s.cfg.ParentType,
|
||||
Jumper: s.cfg.Jumper,
|
||||
}, log)
|
||||
|
||||
if err != nil {
|
||||
@ -164,6 +167,7 @@ type MuxServer struct {
|
||||
isStop bool
|
||||
udpConn *net.Conn
|
||||
log *logger.Logger
|
||||
jumper *jumper.Jumper
|
||||
}
|
||||
|
||||
func NewMuxServer() services.Service {
|
||||
@ -182,7 +186,7 @@ func (s *MuxServer) StopService() {
|
||||
if e != nil {
|
||||
s.log.Printf("stop server service crashed,%s", e)
|
||||
} else {
|
||||
s.log.Printf("service server stoped")
|
||||
s.log.Printf("service server stopped")
|
||||
}
|
||||
}()
|
||||
s.isStop = true
|
||||
@ -208,6 +212,19 @@ func (s *MuxServer) CheckArgs() (err error) {
|
||||
err = fmt.Errorf("remote required")
|
||||
return
|
||||
}
|
||||
if *s.cfg.Jumper != "" {
|
||||
if *s.cfg.ParentType != "tls" && *s.cfg.ParentType != "tcp" {
|
||||
err = fmt.Errorf("jumper only worked of -T is tls or tcp")
|
||||
return
|
||||
}
|
||||
var j jumper.Jumper
|
||||
j, err = jumper.New(*s.cfg.Jumper, time.Millisecond*time.Duration(*s.cfg.Timeout))
|
||||
if err != nil {
|
||||
err = fmt.Errorf("parse jumper fail, err %s", err)
|
||||
return
|
||||
}
|
||||
s.jumper = &j
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -378,15 +395,32 @@ func (s *MuxServer) GetConn(index string) (conn net.Conn, err error) {
|
||||
}
|
||||
func (s *MuxServer) getParentConn() (conn net.Conn, err error) {
|
||||
if *s.cfg.ParentType == "tls" {
|
||||
if s.jumper == nil {
|
||||
var _conn tls.Conn
|
||||
_conn, err = utils.TlsConnectHost(*s.cfg.Parent, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes, nil)
|
||||
if err == nil {
|
||||
conn = net.Conn(&_conn)
|
||||
}
|
||||
} else {
|
||||
conf, err := utils.TlsConfig(s.cfg.CertBytes, s.cfg.KeyBytes, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var _c net.Conn
|
||||
_c, err = s.jumper.Dial(*s.cfg.Parent, time.Millisecond*time.Duration(*s.cfg.Timeout))
|
||||
if err == nil {
|
||||
conn = net.Conn(tls.Client(_c, conf))
|
||||
}
|
||||
}
|
||||
|
||||
} else if *s.cfg.ParentType == "kcp" {
|
||||
conn, err = utils.ConnectKCPHost(*s.cfg.Parent, s.cfg.KCP)
|
||||
} else {
|
||||
if s.jumper == nil {
|
||||
conn, err = utils.ConnectHost(*s.cfg.Parent, *s.cfg.Timeout)
|
||||
} else {
|
||||
conn, err = s.jumper.Dial(*s.cfg.Parent, time.Millisecond*time.Duration(*s.cfg.Timeout))
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
logger "log"
|
||||
"runtime/debug"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type Service interface {
|
||||
@ -17,31 +18,31 @@ type ServiceItem struct {
|
||||
Log *logger.Logger
|
||||
}
|
||||
|
||||
var servicesMap = map[string]*ServiceItem{}
|
||||
var servicesMap = sync.Map{}
|
||||
|
||||
func Regist(name string, s Service, args interface{}, log *logger.Logger) {
|
||||
Stop(name)
|
||||
servicesMap[name] = &ServiceItem{
|
||||
servicesMap.Store(name, &ServiceItem{
|
||||
S: s,
|
||||
Args: args,
|
||||
Name: name,
|
||||
Log: log,
|
||||
}
|
||||
})
|
||||
}
|
||||
func GetService(name string) *ServiceItem {
|
||||
if s, ok := servicesMap[name]; ok && s.S != nil {
|
||||
return s
|
||||
if s, ok := servicesMap.Load(name); ok && s.(*ServiceItem).S != nil {
|
||||
return s.(*ServiceItem)
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
||||
func Stop(name string) {
|
||||
if s, ok := servicesMap[name]; ok && s.S != nil {
|
||||
s.S.Clean()
|
||||
if s, ok := servicesMap.Load(name); ok && s.(*ServiceItem).S != nil {
|
||||
s.(*ServiceItem).S.Clean()
|
||||
}
|
||||
}
|
||||
func Run(name string, args interface{}) (service *ServiceItem, err error) {
|
||||
service, ok := servicesMap[name]
|
||||
_service, ok := servicesMap.Load(name)
|
||||
if ok {
|
||||
defer func() {
|
||||
e := recover()
|
||||
@ -49,6 +50,7 @@ func Run(name string, args interface{}) (service *ServiceItem, err error) {
|
||||
err = fmt.Errorf("%s servcie crashed, ERR: %s\ntrace:%s", name, e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
service = _service.(*ServiceItem)
|
||||
if args != nil {
|
||||
err = service.S.Start(args, service.Log)
|
||||
} else {
|
||||
|
||||
@ -146,7 +146,9 @@ func (s *Socks) InitService() (err error) {
|
||||
if *s.cfg.DNSAddress != "" {
|
||||
(*s).domainResolver = utils.NewDomainResolver(*s.cfg.DNSAddress, *s.cfg.DNSTTL, s.log)
|
||||
}
|
||||
if *s.cfg.Parent != "" {
|
||||
s.checker = utils.NewChecker(*s.cfg.Timeout, int64(*s.cfg.Interval), *s.cfg.Blocked, *s.cfg.Direct, s.log)
|
||||
}
|
||||
if *s.cfg.ParentType == "ssh" {
|
||||
e := s.ConnectSSH()
|
||||
if e != nil {
|
||||
@ -189,11 +191,13 @@ func (s *Socks) StopService() {
|
||||
if e != nil {
|
||||
s.log.Printf("stop socks service crashed,%s", e)
|
||||
} else {
|
||||
s.log.Printf("service socks stoped")
|
||||
s.log.Printf("service socks stopped")
|
||||
}
|
||||
}()
|
||||
s.isStop = true
|
||||
if *s.cfg.Parent != "" {
|
||||
s.checker.Stop()
|
||||
}
|
||||
if s.sshClient != nil {
|
||||
s.sshClient.Close()
|
||||
}
|
||||
@ -598,7 +602,7 @@ func (s *Socks) IsDeadLoop(inLocalAddr string, host string) bool {
|
||||
if *s.cfg.DNSAddress != "" {
|
||||
outIPs = []net.IP{net.ParseIP(s.Resolve(outDomain))}
|
||||
} else {
|
||||
outIPs, err = net.LookupIP(outDomain)
|
||||
outIPs, err = utils.MyLookupIP(outDomain)
|
||||
}
|
||||
if err == nil {
|
||||
for _, ip := range outIPs {
|
||||
|
||||
@ -130,7 +130,7 @@ func (s *SPS) StopService() {
|
||||
if e != nil {
|
||||
s.log.Printf("stop sps service crashed,%s", e)
|
||||
} else {
|
||||
s.log.Printf("service sps stoped")
|
||||
s.log.Printf("service sps stopped")
|
||||
}
|
||||
}()
|
||||
for _, sc := range s.serverChannels {
|
||||
|
||||
@ -2,6 +2,7 @@ package tcp
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"io"
|
||||
logger "log"
|
||||
@ -12,6 +13,7 @@ import (
|
||||
"github.com/snail007/goproxy/services"
|
||||
"github.com/snail007/goproxy/services/kcpcfg"
|
||||
"github.com/snail007/goproxy/utils"
|
||||
"github.com/snail007/goproxy/utils/jumper"
|
||||
|
||||
"strconv"
|
||||
)
|
||||
@ -26,22 +28,21 @@ type TCPArgs struct {
|
||||
ParentType *string
|
||||
LocalType *string
|
||||
Timeout *int
|
||||
CheckParentInterval *int
|
||||
KCP kcpcfg.KCPConfigArgs
|
||||
Jumper *string
|
||||
}
|
||||
|
||||
type TCP struct {
|
||||
outPool utils.OutConn
|
||||
cfg TCPArgs
|
||||
sc *utils.ServerChannel
|
||||
isStop bool
|
||||
userConns utils.ConcurrentMap
|
||||
log *logger.Logger
|
||||
jumper *jumper.Jumper
|
||||
}
|
||||
|
||||
func NewTCP() services.Service {
|
||||
return &TCP{
|
||||
outPool: utils.OutConn{},
|
||||
cfg: TCPArgs{},
|
||||
isStop: false,
|
||||
userConns: utils.NewConcurrentMap(),
|
||||
@ -62,10 +63,23 @@ func (s *TCP) CheckArgs() (err error) {
|
||||
return
|
||||
}
|
||||
}
|
||||
if *s.cfg.Jumper != "" {
|
||||
if *s.cfg.ParentType != "tls" && *s.cfg.ParentType != "tcp" {
|
||||
err = fmt.Errorf("jumper only worked of -T is tls or tcp")
|
||||
return
|
||||
}
|
||||
var j jumper.Jumper
|
||||
j, err = jumper.New(*s.cfg.Jumper, time.Millisecond*time.Duration(*s.cfg.Timeout))
|
||||
if err != nil {
|
||||
err = fmt.Errorf("parse jumper fail, err %s", err)
|
||||
return
|
||||
}
|
||||
s.jumper = &j
|
||||
}
|
||||
return
|
||||
}
|
||||
func (s *TCP) InitService() (err error) {
|
||||
s.InitOutConnPool()
|
||||
|
||||
return
|
||||
}
|
||||
func (s *TCP) StopService() {
|
||||
@ -74,7 +88,7 @@ func (s *TCP) StopService() {
|
||||
if e != nil {
|
||||
s.log.Printf("stop tcp service crashed,%s", e)
|
||||
} else {
|
||||
s.log.Printf("service tcp stoped")
|
||||
s.log.Printf("service tcp stopped")
|
||||
}
|
||||
}()
|
||||
s.isStop = true
|
||||
@ -146,7 +160,7 @@ func (s *TCP) callback(inConn net.Conn) {
|
||||
}
|
||||
func (s *TCP) OutToTCP(inConn *net.Conn) (err error) {
|
||||
var outConn net.Conn
|
||||
outConn, err = s.outPool.Get()
|
||||
outConn, err = s.GetParentConn()
|
||||
if err != nil {
|
||||
s.log.Printf("connect to %s , err:%s", *s.cfg.Parent, err)
|
||||
utils.CloseConn(inConn)
|
||||
@ -219,17 +233,34 @@ func (s *TCP) OutToUDP(inConn *net.Conn) (err error) {
|
||||
return
|
||||
|
||||
}
|
||||
func (s *TCP) InitOutConnPool() {
|
||||
if *s.cfg.ParentType == "tls" || *s.cfg.ParentType == "tcp" || *s.cfg.ParentType == "kcp" {
|
||||
//dur int, isTLS bool, certBytes, keyBytes []byte,
|
||||
//parent string, timeout int, InitialCap int, MaxCap int
|
||||
s.outPool = utils.NewOutConn(
|
||||
*s.cfg.CheckParentInterval,
|
||||
*s.cfg.ParentType,
|
||||
s.cfg.KCP,
|
||||
s.cfg.CertBytes, s.cfg.KeyBytes, nil,
|
||||
*s.cfg.Parent,
|
||||
*s.cfg.Timeout,
|
||||
)
|
||||
func (s *TCP) GetParentConn() (conn net.Conn, err error) {
|
||||
if *s.cfg.ParentType == "tls" {
|
||||
if s.jumper == nil {
|
||||
var _conn tls.Conn
|
||||
_conn, err = utils.TlsConnectHost(*s.cfg.Parent, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes, nil)
|
||||
if err == nil {
|
||||
conn = net.Conn(&_conn)
|
||||
}
|
||||
} else {
|
||||
conf, err := utils.TlsConfig(s.cfg.CertBytes, s.cfg.KeyBytes, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var _c net.Conn
|
||||
_c, err = s.jumper.Dial(*s.cfg.Parent, time.Millisecond*time.Duration(*s.cfg.Timeout))
|
||||
if err == nil {
|
||||
conn = net.Conn(tls.Client(_c, conf))
|
||||
}
|
||||
}
|
||||
|
||||
} else if *s.cfg.ParentType == "kcp" {
|
||||
conn, err = utils.ConnectKCPHost(*s.cfg.Parent, s.cfg.KCP)
|
||||
} else {
|
||||
if s.jumper == nil {
|
||||
conn, err = utils.ConnectHost(*s.cfg.Parent, *s.cfg.Timeout)
|
||||
} else {
|
||||
conn, err = s.jumper.Dial(*s.cfg.Parent, time.Millisecond*time.Duration(*s.cfg.Timeout))
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -30,7 +30,6 @@ type TunnelBridgeArgs struct {
|
||||
KeyBytes []byte
|
||||
Local *string
|
||||
Timeout *int
|
||||
Mux *bool
|
||||
}
|
||||
type ServerConn struct {
|
||||
//ClientLocalAddr string //tcp:2.2.22:333@ID
|
||||
@ -70,7 +69,7 @@ func (s *TunnelBridge) StopService() {
|
||||
if e != nil {
|
||||
s.log.Printf("stop tbridge service crashed,%s", e)
|
||||
} else {
|
||||
s.log.Printf("service tbridge stoped")
|
||||
s.log.Printf("service tbridge stopped")
|
||||
}
|
||||
}()
|
||||
s.isStop = true
|
||||
|
||||
@ -11,6 +11,7 @@ import (
|
||||
|
||||
"github.com/snail007/goproxy/services"
|
||||
"github.com/snail007/goproxy/utils"
|
||||
"github.com/snail007/goproxy/utils/jumper"
|
||||
//"github.com/xtaci/smux"
|
||||
smux "github.com/hashicorp/yamux"
|
||||
)
|
||||
@ -28,7 +29,7 @@ type TunnelClientArgs struct {
|
||||
KeyBytes []byte
|
||||
Key *string
|
||||
Timeout *int
|
||||
Mux *bool
|
||||
Jumper *string
|
||||
}
|
||||
type TunnelClient struct {
|
||||
cfg TunnelClientArgs
|
||||
@ -36,6 +37,7 @@ type TunnelClient struct {
|
||||
isStop bool
|
||||
userConns utils.ConcurrentMap
|
||||
log *logger.Logger
|
||||
jumper *jumper.Jumper
|
||||
}
|
||||
|
||||
func NewTunnelClient() services.Service {
|
||||
@ -62,6 +64,18 @@ func (s *TunnelClient) CheckArgs() (err error) {
|
||||
return
|
||||
}
|
||||
s.cfg.CertBytes, s.cfg.KeyBytes, err = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if *s.cfg.Jumper != "" {
|
||||
var j jumper.Jumper
|
||||
j, err = jumper.New(*s.cfg.Jumper, time.Millisecond*time.Duration(*s.cfg.Timeout))
|
||||
if err != nil {
|
||||
err = fmt.Errorf("parse jumper fail, err %s", err)
|
||||
return
|
||||
}
|
||||
s.jumper = &j
|
||||
}
|
||||
return
|
||||
}
|
||||
func (s *TunnelClient) StopService() {
|
||||
@ -70,7 +84,7 @@ func (s *TunnelClient) StopService() {
|
||||
if e != nil {
|
||||
s.log.Printf("stop tclient service crashed,%s", e)
|
||||
} else {
|
||||
s.log.Printf("service tclient stoped")
|
||||
s.log.Printf("service tclient stopped")
|
||||
}
|
||||
}()
|
||||
s.isStop = true
|
||||
@ -151,10 +165,24 @@ func (s *TunnelClient) GetInConn(typ uint8, data ...string) (outConn net.Conn, e
|
||||
return
|
||||
}
|
||||
func (s *TunnelClient) GetConn() (conn net.Conn, err error) {
|
||||
if s.jumper == nil {
|
||||
var _conn tls.Conn
|
||||
_conn, err = utils.TlsConnectHost(*s.cfg.Parent, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes, nil)
|
||||
if err == nil {
|
||||
conn = net.Conn(&_conn)
|
||||
}
|
||||
} else {
|
||||
conf, err := utils.TlsConfig(s.cfg.CertBytes, s.cfg.KeyBytes, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var _c net.Conn
|
||||
_c, err = s.jumper.Dial(*s.cfg.Parent, time.Millisecond*time.Duration(*s.cfg.Timeout))
|
||||
if err == nil {
|
||||
conn = net.Conn(tls.Client(_c, conf))
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
c, e := smux.Client(conn, &smux.Config{
|
||||
AcceptBacklog: 256,
|
||||
EnableKeepAlive: true,
|
||||
|
||||
@ -14,6 +14,7 @@ import (
|
||||
|
||||
"github.com/snail007/goproxy/services"
|
||||
"github.com/snail007/goproxy/utils"
|
||||
"github.com/snail007/goproxy/utils/jumper"
|
||||
|
||||
//"github.com/xtaci/smux"
|
||||
smux "github.com/hashicorp/yamux"
|
||||
@ -32,7 +33,7 @@ type TunnelServerArgs struct {
|
||||
Timeout *int
|
||||
Route *[]string
|
||||
Mgr *TunnelServerManager
|
||||
Mux *bool
|
||||
Jumper *string
|
||||
}
|
||||
type UDPItem struct {
|
||||
packet *[]byte
|
||||
@ -105,6 +106,7 @@ func (s *TunnelServerManager) Start(args interface{}, log *logger.Logger) (err e
|
||||
Key: &KEY,
|
||||
Timeout: s.cfg.Timeout,
|
||||
Mgr: s,
|
||||
Jumper: s.cfg.Jumper,
|
||||
}, log)
|
||||
|
||||
if err != nil {
|
||||
@ -134,30 +136,6 @@ func (s *TunnelServerManager) InitService() (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (s *TunnelServerManager) GetOutConn(typ uint8) (outConn net.Conn, ID string, err error) {
|
||||
outConn, err = s.GetConn()
|
||||
if err != nil {
|
||||
s.log.Printf("connection err: %s", err)
|
||||
return
|
||||
}
|
||||
ID = s.serverID
|
||||
_, err = outConn.Write(utils.BuildPacket(typ, s.serverID))
|
||||
if err != nil {
|
||||
s.log.Printf("write connection data err: %s ,retrying...", err)
|
||||
utils.CloseConn(&outConn)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
func (s *TunnelServerManager) GetConn() (conn net.Conn, err error) {
|
||||
var _conn tls.Conn
|
||||
_conn, err = utils.TlsConnectHost(*s.cfg.Parent, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes, nil)
|
||||
if err == nil {
|
||||
conn = net.Conn(&_conn)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type TunnelServer struct {
|
||||
cfg TunnelServerArgs
|
||||
udpChn chan UDPItem
|
||||
@ -166,6 +144,7 @@ type TunnelServer struct {
|
||||
udpConn *net.Conn
|
||||
userConns utils.ConcurrentMap
|
||||
log *logger.Logger
|
||||
jumper *jumper.Jumper
|
||||
}
|
||||
|
||||
func NewTunnelServer() services.Service {
|
||||
@ -183,7 +162,7 @@ func (s *TunnelServer) StopService() {
|
||||
if e != nil {
|
||||
s.log.Printf("stop server service crashed,%s", e)
|
||||
} else {
|
||||
s.log.Printf("service server stoped")
|
||||
s.log.Printf("service server stopped")
|
||||
}
|
||||
}()
|
||||
s.isStop = true
|
||||
@ -210,6 +189,15 @@ func (s *TunnelServer) CheckArgs() (err error) {
|
||||
err = fmt.Errorf("remote required")
|
||||
return
|
||||
}
|
||||
if *s.cfg.Jumper != "" {
|
||||
var j jumper.Jumper
|
||||
j, err = jumper.New(*s.cfg.Jumper, time.Millisecond*time.Duration(*s.cfg.Timeout))
|
||||
if err != nil {
|
||||
err = fmt.Errorf("parse jumper fail, err %s", err)
|
||||
return
|
||||
}
|
||||
s.jumper = &j
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -301,11 +289,26 @@ func (s *TunnelServer) GetOutConn(typ uint8) (outConn net.Conn, ID string, err e
|
||||
return
|
||||
}
|
||||
func (s *TunnelServer) GetConn() (conn net.Conn, err error) {
|
||||
var dconn net.Conn
|
||||
if s.jumper == nil {
|
||||
var _conn tls.Conn
|
||||
_conn, err = utils.TlsConnectHost(*s.cfg.Parent, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes, nil)
|
||||
if err == nil {
|
||||
conn = net.Conn(&_conn)
|
||||
c, e := smux.Client(conn, &smux.Config{
|
||||
dconn = net.Conn(&_conn)
|
||||
}
|
||||
} else {
|
||||
conf, err := utils.TlsConfig(s.cfg.CertBytes, s.cfg.KeyBytes, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var _c net.Conn
|
||||
_c, err = s.jumper.Dial(*s.cfg.Parent, time.Millisecond*time.Duration(*s.cfg.Timeout))
|
||||
if err == nil {
|
||||
dconn = net.Conn(tls.Client(_c, conf))
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
sess, e := smux.Client(dconn, &smux.Config{
|
||||
AcceptBacklog: 256,
|
||||
EnableKeepAlive: true,
|
||||
KeepAliveInterval: 9 * time.Second,
|
||||
@ -316,14 +319,30 @@ func (s *TunnelServer) GetConn() (conn net.Conn, err error) {
|
||||
if e != nil {
|
||||
s.log.Printf("new mux client conn error,ERR:%s", e)
|
||||
err = e
|
||||
dconn.Close()
|
||||
return
|
||||
}
|
||||
conn, e = c.OpenStream()
|
||||
conn, e = sess.OpenStream()
|
||||
if e != nil {
|
||||
s.log.Printf("mux client conn open stream error,ERR:%s", e)
|
||||
err = e
|
||||
dconn.Close()
|
||||
return
|
||||
}
|
||||
go func() {
|
||||
defer func() {
|
||||
_ = recover()
|
||||
}()
|
||||
timer := time.NewTicker(time.Second * 3)
|
||||
for {
|
||||
<-timer.C
|
||||
if sess.NumStreams() == 0 {
|
||||
sess.Close()
|
||||
timer.Stop()
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -73,7 +73,7 @@ func (s *UDP) StopService() {
|
||||
if e != nil {
|
||||
s.log.Printf("stop udp service crashed,%s", e)
|
||||
} else {
|
||||
s.log.Printf("service udp stoped")
|
||||
s.log.Printf("service udp stopped")
|
||||
}
|
||||
}()
|
||||
s.isStop = true
|
||||
|
||||
@ -22,6 +22,7 @@ import (
|
||||
|
||||
"golang.org/x/crypto/pbkdf2"
|
||||
|
||||
"context"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@ -107,6 +108,9 @@ func TlsConnect(host string, port, timeout int, certBytes, keyBytes, caCertBytes
|
||||
}
|
||||
return *tls.Client(_conn, conf), err
|
||||
}
|
||||
func TlsConfig(certBytes, keyBytes, caCertBytes []byte) (conf *tls.Config, err error) {
|
||||
return getRequestTlsConfig(certBytes, keyBytes, caCertBytes)
|
||||
}
|
||||
func getRequestTlsConfig(certBytes, keyBytes, caCertBytes []byte) (conf *tls.Config, err error) {
|
||||
|
||||
var cert tls.Certificate
|
||||
@ -208,8 +212,13 @@ func CloseConn(conn *net.Conn) {
|
||||
(*conn).Close()
|
||||
}
|
||||
}
|
||||
func GetAllInterfaceAddr() ([]net.IP, error) {
|
||||
|
||||
var allInterfaceAddrCache []net.IP
|
||||
|
||||
func GetAllInterfaceAddr() ([]net.IP, error) {
|
||||
if allInterfaceAddrCache != nil {
|
||||
return allInterfaceAddrCache, nil
|
||||
}
|
||||
ifaces, err := net.Interfaces()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -250,6 +259,7 @@ func GetAllInterfaceAddr() ([]net.IP, error) {
|
||||
return nil, fmt.Errorf("no address Found, net.InterfaceAddrs: %v", addresses)
|
||||
}
|
||||
//only need first
|
||||
allInterfaceAddrCache = addresses
|
||||
return addresses, nil
|
||||
}
|
||||
func UDPPacket(srcAddr string, packet []byte) []byte {
|
||||
@ -497,7 +507,7 @@ func IsIternalIP(domainOrIP string, always bool) bool {
|
||||
}
|
||||
|
||||
if isDomain {
|
||||
outIPs, err = net.LookupIP(domainOrIP)
|
||||
outIPs, err = MyLookupIP(domainOrIP)
|
||||
} else {
|
||||
outIPs = []net.IP{net.ParseIP(domainOrIP)}
|
||||
}
|
||||
@ -632,3 +642,25 @@ func InsertProxyHeaders(head []byte, headers string) []byte {
|
||||
// }
|
||||
// return
|
||||
// }
|
||||
|
||||
/*
|
||||
net.LookupIP may cause deadlock in windows
|
||||
https://github.com/golang/go/issues/24178
|
||||
*/
|
||||
func MyLookupIP(host string) ([]net.IP, error) {
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*time.Duration(3))
|
||||
defer func() {
|
||||
cancel()
|
||||
//ctx.Done()
|
||||
}()
|
||||
addrs, err := net.DefaultResolver.LookupIPAddr(ctx, host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ips := make([]net.IP, len(addrs))
|
||||
for i, ia := range addrs {
|
||||
ips[i] = ia.IP
|
||||
}
|
||||
return ips, nil
|
||||
}
|
||||
|
||||
100
utils/jumper/jumper.go
Normal file
100
utils/jumper/jumper.go
Normal file
@ -0,0 +1,100 @@
|
||||
package jumper
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/proxy"
|
||||
)
|
||||
|
||||
type Jumper struct {
|
||||
proxyURL *url.URL
|
||||
timeout time.Duration
|
||||
}
|
||||
type socks5Dialer struct {
|
||||
timeout time.Duration
|
||||
}
|
||||
|
||||
func (s socks5Dialer) Dial(network, addr string) (net.Conn, error) {
|
||||
return net.DialTimeout(network, addr, s.timeout)
|
||||
}
|
||||
|
||||
func New(proxyURL string, timeout time.Duration) (j Jumper, err error) {
|
||||
u, err := url.Parse(proxyURL)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
j = Jumper{
|
||||
proxyURL: u,
|
||||
timeout: timeout,
|
||||
}
|
||||
return
|
||||
}
|
||||
func (j *Jumper) Dial(address string, timeout time.Duration) (conn net.Conn, err error) {
|
||||
switch j.proxyURL.Scheme {
|
||||
case "https":
|
||||
return j.dialHTTPS(address, timeout)
|
||||
case "socks5":
|
||||
return j.dialSOCKS5(address, timeout)
|
||||
default:
|
||||
return nil, fmt.Errorf("unkown scheme of %s", j.proxyURL.String())
|
||||
}
|
||||
}
|
||||
func (j *Jumper) dialHTTPS(address string, timeout time.Duration) (conn net.Conn, err error) {
|
||||
conn, err = net.DialTimeout("tcp", j.proxyURL.Host, timeout)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
pb := new(bytes.Buffer)
|
||||
pb.Write([]byte(fmt.Sprintf("CONNECT %s HTTP/1.1\r\n", address)))
|
||||
pb.WriteString("Proxy-Connection: Keep-Alive\r\n")
|
||||
if j.proxyURL.User != nil {
|
||||
p, _ := j.proxyURL.User.Password()
|
||||
u := fmt.Sprintf("%s:%s", j.proxyURL.User.Username(), p)
|
||||
pb.Write([]byte(fmt.Sprintf("Proxy-Authorization: Basic %s\r\n", base64.StdEncoding.EncodeToString([]byte(u)))))
|
||||
}
|
||||
pb.Write([]byte("\r\n"))
|
||||
_, err = conn.Write(pb.Bytes())
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
conn = nil
|
||||
err = fmt.Errorf("error connecting to proxy: %s", err)
|
||||
return
|
||||
}
|
||||
reply := make([]byte, 1024)
|
||||
conn.SetDeadline(time.Now().Add(timeout))
|
||||
n, err := conn.Read(reply)
|
||||
conn.SetDeadline(time.Time{})
|
||||
if err != nil {
|
||||
err = fmt.Errorf("error read reply from proxy: %s", err)
|
||||
conn.Close()
|
||||
conn = nil
|
||||
return
|
||||
}
|
||||
if bytes.Index(reply[:n], []byte("200")) == -1 {
|
||||
err = fmt.Errorf("error greeting to proxy, response: %s", string(reply[:n]))
|
||||
conn.Close()
|
||||
conn = nil
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
func (j *Jumper) dialSOCKS5(address string, timeout time.Duration) (conn net.Conn, err error) {
|
||||
auth := &proxy.Auth{}
|
||||
if j.proxyURL.User != nil {
|
||||
auth.User = j.proxyURL.User.Username()
|
||||
auth.Password, _ = j.proxyURL.User.Password()
|
||||
} else {
|
||||
auth = nil
|
||||
}
|
||||
dialSocksProxy, err := proxy.SOCKS5("tcp", j.proxyURL.Host, auth, socks5Dialer{timeout: timeout})
|
||||
if err != nil {
|
||||
err = fmt.Errorf("error connecting to proxy: %s", err)
|
||||
return
|
||||
}
|
||||
return dialSocksProxy.Dial("tcp", address)
|
||||
}
|
||||
@ -72,7 +72,7 @@ func (s *ClientConn) Handshake() error {
|
||||
if err != nil {
|
||||
return errors.New("proxy: failed to parse port number: " + portStr)
|
||||
}
|
||||
if port < 1 || port > 0xffff {
|
||||
if s.network == "tcp" && (port < 1 || port > 0xffff) {
|
||||
return errors.New("proxy: port number out of range: " + portStr)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user