32 Commits
v5.3 ... v5.4

Author SHA1 Message Date
arraykeys@gmail.com
a3eb0bfde9 Merge branch 'dev' 2018-08-30 16:10:28 +08:00
arraykeys@gmail.com
33e665631d v5.4 2018-08-30 16:09:58 +08:00
arraykeys@gmail.com
375eb9aa66 v5.4 2018-08-30 15:34:13 +08:00
arraykeys@gmail.com
889ce76676 优化sdk,支持并发启动/关闭操作 2018-08-24 11:41:15 +08:00
arraykeys@gmail.com
abdcae31c9 优化sdk,支持并发启动/关闭操作 2018-08-24 11:40:36 +08:00
arraykeys@gmail.com
c9f8f6c6fb fix GetAllInterfaceAddr cpu high 2018-08-21 10:52:18 +08:00
arraykeys@gmail.com
aab899397e fix GetAllInterfaceAddr cpu high 2018-08-21 10:29:51 +08:00
arraykeys@gmail.com
a933322ef7 Merge branch 'dev' 2018-08-06 16:07:24 +08:00
arraykeys@gmail.com
b9f054c495 v5.3 2018-08-06 16:06:43 +08:00
arraykeys@gmail.com
5c2e6fd109 a 2018-07-24 17:25:04 +08:00
arraykeys@gmail.com
e427263ccf a 2018-07-24 12:10:24 +08:00
arraykeys@gmail.com
a1a2c3f985 sdk5.3 2018-07-24 11:31:16 +08:00
arraykeys@gmail.com
84458a10e4 Merge remote-tracking branch 'origin/dev' into dev 2018-07-18 11:01:46 +08:00
snail007
9dd7bf80c5 Merge pull request #114 from schmich/fix-typo
Fix typo
2018-07-18 09:09:59 +08:00
Chris Schmich
317d0113fb Fix typo: 'stoped' -> 'stopped'. 2018-07-17 14:02:38 -07:00
arraykeys@gmail.com
53153da2e6 a 2018-07-17 17:55:54 +08:00
arraykeys@gmail.com
747a94a1c8 fix #113 2018-07-17 16:00:48 +08:00
arraykeys@gmail.com
df94ca5601 a 2018-07-16 18:32:53 +08:00
arraykeys@gmail.com
3cf7788f34 a 2018-07-16 18:10:21 +08:00
arraykeys@gmail.com
af91921070 a 2018-07-16 16:18:34 +08:00
arraykeys@gmail.com
7fc5c30f60 fix docker file 2018-07-16 15:54:55 +08:00
arraykeys@gmail.com
c4a7f0fbb0 Merge remote-tracking branch 'origin/dev' into dev 2018-07-12 13:34:18 +08:00
arraykeys@gmail.com
f656773858 优化智能检查的初始化时机 2018-07-12 13:32:46 +08:00
snail007
e208ccee18 Merge pull request #110 from boboanvip/dev
net.LookupIP may cause  deadlock in windows
2018-07-12 12:38:20 +08:00
boboan
5980fee788 net.LookupIP may cause deadlock in windows 2018-07-12 10:31:54 +08:00
boboanvip
61f791e77d Merge branch 'dev' into dev 2018-07-12 10:28:32 +08:00
boboan
907dec42e0 net.LookupIP may cause deadlock in windows
https://github.com/golang/go/issues/24178
2018-07-12 10:21:28 +08:00
arraykeys
8dce99fec6 a 2018-07-11 21:35:02 +08:00
snail007
db13b83f44 Merge pull request #109 from boboanvip/master
fix net.LookupIP may cause  deadlock in windows
2018-07-11 20:50:58 +08:00
boboan
dd8d7dd0d4 net.LookupIP may cause deadlock in windows
https://github.com/golang/go/issues/24178
2018-07-11 17:45:35 +08:00
arraykeys@gmail.com
dd355b5d98 fix socks client check port range 2018-07-10 16:26:26 +08:00
arraykeys@gmail.com
1e1999dede a 2018-07-10 13:37:00 +08:00
34 changed files with 623 additions and 162 deletions

View File

@ -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解析.

View File

@ -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}

View File

@ -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:
```

View File

@ -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`

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -9,7 +9,7 @@ import (
"github.com/snail007/goproxy/services"
)
const APP_VERSION = "5.2"
const APP_VERSION = "5.4"
func main() {
err := initConfig()

View File

@ -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"

View File

@ -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代理返回不合适的头部,导致浏览器不会弹框,个别代理插件无法认证的问题.

View File

@ -25,7 +25,7 @@ proxy使用gombile实现了一份go代码编译为android和ios平台下面可
#### 1.导入包
```java
import snail007.proxy.Porxy
import snail007.proxy.Proxy
```
#### 2.启动一个服务

View File

@ -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)

View File

@ -1,5 +1,5 @@
#/bin/bash
VER="v5.0"
VER="v5.3"
rm -rf sdk-android-*.tar.gz
rm -rf android
mkdir android

View File

@ -1,5 +1,5 @@
#/bin/bash
VER="v5.0"
VER="v5.3"
rm -rf sdk-ios-*.tar.gz
rm -rf ios
mkdir ios

View File

@ -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 {

View File

@ -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

View File

@ -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

View File

@ -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."

View File

@ -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 {

View File

@ -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

View File

@ -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
}

View File

@ -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
}

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

View File

@ -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
}

View File

@ -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

View File

@ -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,

View File

@ -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
}

View File

@ -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

View File

@ -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
View 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)
}

View File

@ -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)
}