Compare commits
119 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c14a3b2773 | ||
|
|
e6e61b3cdb | ||
|
|
303587f91b | ||
|
|
5c3fd53fab | ||
|
|
0c675e6ff6 | ||
|
|
942b026a05 | ||
|
|
0b347b7f8d | ||
|
|
87322c335e | ||
|
|
1bf4b38268 | ||
|
|
60b1742088 | ||
|
|
266fa6f6fa | ||
|
|
02c3c9b374 | ||
|
|
8f7da3ed94 | ||
|
|
a5a6e8645a | ||
|
|
83022d3efc | ||
|
|
78143ce638 | ||
|
|
cee38766c5 | ||
|
|
c66147c686 | ||
|
|
08e149b180 | ||
|
|
e3f8b652f4 | ||
|
|
6a4a45c96b | ||
|
|
e5bf95bdc8 | ||
|
|
ed1e7253f3 | ||
|
|
db43daea0b | ||
|
|
0359ef40e1 | ||
|
|
89b5744e27 | ||
|
|
18f293a7aa | ||
|
|
acf70602ff | ||
|
|
ebba94b9d1 | ||
|
|
23c379faf9 | ||
|
|
124852b3a2 | ||
|
|
e6d557f61e | ||
|
|
0a2ed2e498 | ||
|
|
4ce5fd463d | ||
|
|
367cfb36dd | ||
|
|
57555ffc1e | ||
|
|
8a86a53bd2 | ||
|
|
4a7b1af383 | ||
|
|
78e631f551 | ||
|
|
0af83540d3 | ||
|
|
9004913483 | ||
|
|
44909ea6c6 | ||
|
|
a0cd66e319 | ||
|
|
8c4e5025ed | ||
|
|
442e7b7c01 | ||
|
|
05dfbe6f8a | ||
|
|
c64324227b | ||
|
|
1388f2e008 | ||
|
|
2752d79248 | ||
|
|
7aa24afcf2 | ||
|
|
b3622e709c | ||
|
|
02a58189ad | ||
|
|
f42184daaf | ||
|
|
7754fcc13e | ||
|
|
d421b79071 | ||
|
|
80146fbe0d | ||
|
|
e95a1f8ad5 | ||
|
|
9e496f246c | ||
|
|
f0389cdd5b | ||
|
|
bcca92affc | ||
|
|
421e72188b | ||
|
|
cc8416e6bf | ||
|
|
fb09a100e1 | ||
|
|
1b1091d75f | ||
|
|
ea30beb79b | ||
|
|
99881e2c70 | ||
|
|
325acb2942 | ||
|
|
6babe1ea10 | ||
|
|
6c586e2b78 | ||
|
|
6917ff3347 | ||
|
|
284bb83d64 | ||
|
|
1b29112a2c | ||
|
|
b9afc98230 | ||
|
|
20761d2183 | ||
|
|
1ab07c81ab | ||
|
|
07efc2c8de | ||
|
|
ef8737063b | ||
|
|
b5e0fa4895 | ||
|
|
02513a9449 | ||
|
|
0859452475 | ||
|
|
42d18ca1d3 | ||
|
|
08b3715bda | ||
|
|
253783573a | ||
|
|
56dc3fdc07 | ||
|
|
af20893551 | ||
|
|
85178223e0 | ||
|
|
e116bf8897 | ||
|
|
0fffedebd7 | ||
|
|
1e259b5c6f | ||
|
|
7bb5bb86dc | ||
|
|
18716cb3a2 | ||
|
|
1aca777c6d | ||
|
|
3a5b47b84a | ||
|
|
8bda30c4cf | ||
|
|
03ef384c48 | ||
|
|
5ace1eef1d | ||
|
|
d270b4a468 | ||
|
|
6154d4173a | ||
|
|
70067d67b9 | ||
|
|
8befdbc89c | ||
|
|
900b975c6a | ||
|
|
2ddb03a6c7 | ||
|
|
4145a31e5b | ||
|
|
96717f0c33 | ||
|
|
09348211b6 | ||
|
|
179f9d63ab | ||
|
|
7692446fd8 | ||
|
|
69f20e1d7a | ||
|
|
0bebee1537 | ||
|
|
61569c3a92 | ||
|
|
0d6e10ad33 | ||
|
|
77a6300dae | ||
|
|
8f268b8b56 | ||
|
|
efb5710727 | ||
|
|
7fc0b21764 | ||
|
|
2f524010a1 | ||
|
|
c537240d3d | ||
|
|
d3640f7519 | ||
|
|
575326bed1 |
13
AUTHORIZATION.md
Normal file
13
AUTHORIZATION.md
Normal file
@ -0,0 +1,13 @@
|
||||
# GoProxy special authorization
|
||||
|
||||
1. gproxy uses GPLv3 source code open agreement, without permission, based on the project development software, derivative software, related software, must strictly abide by GPLv3, otherwise once found,
|
||||
Will be harshly punished.
|
||||
|
||||
2. If the company or individual uses the project code to develop related software, derivative software, and does not want to comply with the GPLv3 agreement, need to obtain the author's "GoProxy special authorization" written authorization.
|
||||
|
||||
3. If "GoPro special authorization"is not available on this page,the" GoPro special authorization"is invalid.
|
||||
|
||||
4. A valid authorization number and expiration date are listed below.
|
||||
|
||||
Authorization number | Authorization validity period
|
||||
:--- | :---
|
||||
13
AUTHORIZATION_ZH.md
Normal file
13
AUTHORIZATION_ZH.md
Normal file
@ -0,0 +1,13 @@
|
||||
# GoProxy特殊授权
|
||||
|
||||
1.goproxy采用GPLv3源代码开放协议,未经许可,基于本项目开发的软件,衍生软件,相关软件,必须严格遵守GPLv3,否则一经发现,
|
||||
将严厉追责.
|
||||
|
||||
2.如果公司或个人使用本项目代码开发相关软件,衍生软件,又不想遵守GPLv3协议,需要取得作者的"GoProxy特殊授权"书面授权.
|
||||
|
||||
3.如果本页面查询不到"GoProxy特殊授权"书面授权信息,则"GoProxy特殊授权"书面授权无效.
|
||||
|
||||
4.下面列出了有效的授权编号和有效期.
|
||||
|
||||
授权编号 | 授权有效期
|
||||
:--- | :---
|
||||
59
CHANGELOG
59
CHANGELOG
@ -1,5 +1,64 @@
|
||||
proxy更新日志
|
||||
|
||||
v6.9
|
||||
1.修复了sps的start潜在的crash问题.
|
||||
2.sps代理增加了--parent-tls-single参数用来支持单向tls上级。
|
||||
3.sps代理增加了对单个上级认证信息的支持,如果没有单独设置,就使用全局-A设置.
|
||||
现在上级格式: -P YTpi#2.2.2.2:33080@1
|
||||
说明:
|
||||
YTpi 是经过base64编码的认证信息,比如是http(s)/socks原始认证信息a:b,用户是a密码是b,base64编码之后是:YTpi
|
||||
如果是ss,那么a就是加密方法,b是密码,比如:aes-192-cfb:your_pass,base64编码之后是:YWVzLTE5Mi1jZmI6eW91cl9wYXNz
|
||||
# 是间隔符号,如果有认证信息,必须有#,没有认证信息可以省略#.
|
||||
2.2.2.2:33080 是上级地址
|
||||
@1 是设置权重,可以参考手册权重部分.
|
||||
4.修复了socks5代理错误处理超时的问题.
|
||||
5.修复了http(s)代理错误处理-Z的问题.
|
||||
|
||||
v6.8
|
||||
1.HTTP(S)\SOCKS5代理,API认证功能,发送给认证接口的参数增加了本地IP,local_ip字段,
|
||||
代表用户访问的是本地服务器的哪个IP.
|
||||
2.fix #194 , fix #134 , 代理更稳定.
|
||||
3.增加了一波英文文档.
|
||||
|
||||
v6.6
|
||||
1.优化了limitconn的关闭逻辑,释放更多资源.
|
||||
2.http(s)\socks代理增加了--intelligent,智能模式设置,可以是intelligent|direct|parent三者之一,
|
||||
默认是:intelligent.每个值的含义如下.
|
||||
--intelligent=direct,不在blocked里面的目标都直连.
|
||||
--intelligent=parent,不在direct里面的目标都走上级.
|
||||
--intelligent=intelligent,blocked和direct里面都没有的目标,智能判断是否使用上级访问目标.
|
||||
|
||||
v6.5
|
||||
1.修复了合并企业版遗留的一些bug.
|
||||
|
||||
v6.4
|
||||
1.http(s)代理增加了--jumper参数,可以穿透外部代理连接上级.
|
||||
2.优化了socks5代理UDP功能可能存在的内存占用过多问题.
|
||||
3.优化了jumper,避免某些情况下不能正确返回错误的问题.
|
||||
4.sps代理增加了--jumper参数,可以穿透外部代理连接上级.
|
||||
5.修复了--debug不能正常工作的问题.
|
||||
|
||||
v6.3
|
||||
1.fixed #156
|
||||
2.修复DNS代理,没有定时保存缓存结果到文件.重启会降低查询速度.
|
||||
|
||||
|
||||
v6.2
|
||||
1.修复encrypt.Conn释放内存,导致的潜在panic问题.
|
||||
2.修复了basic认证,处理认证文件没有正确处理注释的bug.
|
||||
3.修正了ssh中转手册参数-A调整为-D.
|
||||
|
||||
v6.1
|
||||
1.黑白名单支持设置顶级域了,比如:com,匹配所有的.com域名
|
||||
2.优化TCPS内存释放.
|
||||
3.优化了域名检查.
|
||||
4.内网穿透增加了TCPS和TOU协议,
|
||||
TCPS提供了多种自定义加密TCP方式传输.
|
||||
TOU提供了TCP over UDP,多种自定义加密UDP方式传输TCP数据.
|
||||
5.优化了DST,防止意外crash.
|
||||
6.修复了mapx的Keys()方法的bug导致内网穿透bridge不稳定的问题.
|
||||
7.修复了部分服务不能绑定IPv6地址的bug.
|
||||
|
||||
v6.0 企业版开源啦
|
||||
本次更新主要是把企业版开源,把企业版代码合并到现在的开源goproxy当中,继续遵循GPLv3,免费开源,
|
||||
之所以直接跳过5.x,用6.0版本号是为了与现有开源版本做一个明显的区分,下面功能主要来自企业版.
|
||||
|
||||
82
Dockerfile
82
Dockerfile
@ -1,82 +0,0 @@
|
||||
FROM alpine:3.7 AS builder
|
||||
|
||||
RUN apk add --no-cache \
|
||||
ca-certificates
|
||||
|
||||
# set up nsswitch.conf for Go's "netgo" implementation
|
||||
# - https://github.com/golang/go/blob/go1.9.1/src/net/conf.go#L194-L275
|
||||
# - docker run --rm debian:stretch grep '^hosts:' /etc/nsswitch.conf
|
||||
RUN [ ! -e /etc/nsswitch.conf ] && echo 'hosts: files dns' > /etc/nsswitch.conf
|
||||
|
||||
ENV GOLANG_VERSION 1.10.3
|
||||
|
||||
# make-sure-R0-is-zero-before-main-on-ppc64le.patch: https://github.com/golang/go/commit/9aea0e89b6df032c29d0add8d69ba2c95f1106d9 (Go 1.9)
|
||||
#COPY *.patch /go-alpine-patches/
|
||||
|
||||
RUN set -eux; \
|
||||
apk add --no-cache --virtual .build-deps \
|
||||
bash \
|
||||
gcc \
|
||||
musl-dev \
|
||||
openssl \
|
||||
go \
|
||||
; \
|
||||
export \
|
||||
# set GOROOT_BOOTSTRAP such that we can actually build Go
|
||||
GOROOT_BOOTSTRAP="$(go env GOROOT)" \
|
||||
# ... and set "cross-building" related vars to the installed system's values so that we create a build targeting the proper arch
|
||||
# (for example, if our build host is GOARCH=amd64, but our build env/image is GOARCH=386, our build needs GOARCH=386)
|
||||
GOOS="$(go env GOOS)" \
|
||||
GOARCH="$(go env GOARCH)" \
|
||||
GOHOSTOS="$(go env GOHOSTOS)" \
|
||||
GOHOSTARCH="$(go env GOHOSTARCH)" \
|
||||
; \
|
||||
# also explicitly set GO386 and GOARM if appropriate
|
||||
# https://github.com/docker-library/golang/issues/184
|
||||
apkArch="$(apk --print-arch)"; \
|
||||
case "$apkArch" in \
|
||||
armhf) export GOARM='6' ;; \
|
||||
x86) export GO386='387' ;; \
|
||||
esac; \
|
||||
\
|
||||
wget -O go.tgz "https://golang.org/dl/go$GOLANG_VERSION.src.tar.gz"; \
|
||||
echo '567b1cc66c9704d1c019c50bef946272e911ec6baf244310f87f4e678be155f2 *go.tgz' | sha256sum -c -; \
|
||||
tar -C /usr/local -xzf go.tgz; \
|
||||
rm go.tgz; \
|
||||
\
|
||||
cd /usr/local/go/src; \
|
||||
for p in /go-alpine-patches/*.patch; do \
|
||||
[ -f "$p" ] || continue; \
|
||||
patch -p2 -i "$p"; \
|
||||
done; \
|
||||
./make.bash; \
|
||||
\
|
||||
rm -rf /go-alpine-patches; \
|
||||
apk del .build-deps; \
|
||||
\
|
||||
export PATH="/usr/local/go/bin:$PATH"; \
|
||||
go version
|
||||
|
||||
ENV GOPATH /go
|
||||
ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH
|
||||
|
||||
RUN mkdir -p "$GOPATH/src" "$GOPATH/bin" && chmod -R 777 "$GOPATH"
|
||||
WORKDIR $GOPATH
|
||||
|
||||
ARG GOPROXY_VERSION=master
|
||||
RUN apk update; apk upgrade; \
|
||||
apk add --no-cache git; \
|
||||
cd /go/src/; \
|
||||
mkdir github.com; \
|
||||
mkdir github.com/snail007; \
|
||||
cd github.com/snail007; \
|
||||
git clone https://github.com/snail007/goproxy.git; \
|
||||
cd goproxy; \
|
||||
git checkout ${GOPROXY_VERSION}; \
|
||||
CGO_ENABLED=0 GOOS=linux go build -ldflags "-s -w" -a -installsuffix cgo -o proxy; \
|
||||
chmod 0777 proxy
|
||||
|
||||
FROM 1.10.3-stretch
|
||||
RUN mkdir /proxy && chmod 0777 /proxy
|
||||
COPY --from=builder builder /go/src/github.com/snail007/goproxy/proxy /proxy/
|
||||
CMD cd /proxy && /proxy ${OPTS}
|
||||
20
Gopkg.lock
generated
20
Gopkg.lock
generated
@ -1,6 +1,12 @@
|
||||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/Yawning/chacha20"
|
||||
packages = ["."]
|
||||
revision = "e3b1f968fc6397b51d963fee8ec8711a47bc0ce8"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/alecthomas/template"
|
||||
@ -28,6 +34,12 @@
|
||||
packages = ["."]
|
||||
revision = "3520598351bb3500a49ae9563f5539666ae0a27c"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/juju/ratelimit"
|
||||
packages = ["."]
|
||||
revision = "59fac5042749a5afb9af70e813da1dd5474f0167"
|
||||
version = "1.0.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/klauspost/cpuid"
|
||||
packages = ["."]
|
||||
@ -119,6 +131,12 @@
|
||||
]
|
||||
revision = "db08ff08e8622530d9ed3a0e8ac279f6d4c02196"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/sys"
|
||||
packages = ["unix"]
|
||||
revision = "dad3d9fb7b6e83d0f9ac8f54670f6334c3a287b4"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/time"
|
||||
@ -134,6 +152,6 @@
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "eab0ef29432489696d8bfd524757dcb03a83f91c329f2d05c36da70df850360d"
|
||||
inputs-digest = "15e4e23c0695db1458b3dc5514c8765be091a420c923b24bb9e186f43400995f"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
|
||||
230
README.md
230
README.md
@ -1,5 +1,5 @@
|
||||
<img src="https://github.com/snail007/goproxy/blob/master/docs/images/logo.jpg?raw=true" width="200"/>
|
||||
Proxy is a high performance HTTP, HTTPS, HTTPS, websocket, TCP, UDP, Socks5 proxy server implemented by golang. It supports parent proxy,nat forward,TCP/UDP port forwarding, SSH transfer, TLS encrypted transmission, protocol conversion. you can expose a local server behind a NAT or firewall to the internet, secure DNS proxy.
|
||||
Proxy is a high performance HTTP, HTTPS, HTTPS, websocket, TCP, UDP, Socks5, ss proxy server implemented by golang. It supports parent proxy,nat forward,TCP/UDP port forwarding, SSH transfer, TLS encrypted transmission, protocol conversion. you can expose a local server behind a NAT or firewall to the internet, secure DNS proxy.
|
||||
|
||||
|
||||
---
|
||||
@ -8,9 +8,11 @@ Proxy is a high performance HTTP, HTTPS, HTTPS, websocket, TCP, UDP, Socks5 prox
|
||||
|
||||
**[中文手册](/README_ZH.md)**
|
||||
|
||||
**[全平台图形界面版本](/gui/README.md)**
|
||||
**[Full-platform graphical interface version](/gui/README.md)**
|
||||
|
||||
**[全平台SDK](/sdk/README.md)**
|
||||
**[Full platform SDK](/sdk/README.md)**
|
||||
|
||||
**[GoProxy special authorization](/AUTHORIZATION.md)**
|
||||
|
||||
### How to contribute to the code (Pull Request)?
|
||||
|
||||
@ -33,10 +35,15 @@ PR needs to explain what changes have been made and why you change them.
|
||||
- The integrated external API, HTTP (S): SOCKS5 proxy authentication can be integrated with the external HTTP API, which can easily control the user's access through the external system.
|
||||
- Reverse proxy: goproxy supports directly parsing the domain to proxy monitor IP, and then proxy will help you to access the HTTP (S) site that you need to access.
|
||||
- Transparent proxy: with the iptables, goproxy can directly forward the 80 and 443 port's traffic to proxy in the gateway, and can realize the unaware intelligent router proxy.
|
||||
- Protocol conversion: The existing HTTP (S) or SOCKS5 proxy can be converted to a proxy which support both HTTP (S) and SOCKS5 by one port, but the converted SOCKS5 proxy does not support the UDP function.Also support powerful cascading authentication.
|
||||
- Protocol conversion: The existing HTTP (S) or SOCKS5 or ss proxy can be converted to a proxy which support HTTP (S), SOCKS5 and ss by one port, if the converted SOCKS5 and ss proxy's parent proxy is SOCKS5, which can support the UDP function.Also support powerful cascading authentication.
|
||||
- Custom underlying encrypted transmission, HTTP(s)\sps\socks proxy can encrypt TCP data through TLS standard encryption and KCP protocol encryption. In addition, it also supports custom encryption after TLS and KCP. That is to say, custom encryption and tls|kcp can be used together. The internal uses AES256 encryption, and it only needs to define one password by yourself when is used.
|
||||
- Low level compression and efficient transmission,The HTTP(s)\sps\socks proxy can encrypt TCP data through a custom encryption and TLS standard encryption and KCP protocol encryption, and can also compress the data after encryption. That is to say, the compression and custom encryption and tls|kcp can be used together.
|
||||
- The secure DNS proxy, Through the DNS proxy provided by the local proxy, you can encrypted communicate with the father proxy to realize the DNS query of security and pollution prevention.
|
||||
- Load balance,High availability,HTTP(S)\SOCKS5\SPS proxy support Superior load balance and high availability. Multiple superiors repeat -P parameters.
|
||||
- Designated exporting IP,HTTP(S)\SOCKS5\SPS proxy supports the client to connect with the entry IP,Using the entry IP as the exporting IP to visit the target website。If the entry IP is the intranet IP,Exporting IP will not use entry IP
|
||||
- Support speed limit. HTTP (S) \SOCKS5\SPS proxy supports speed limit.
|
||||
- SOCKS5 proxy supports cascade authentication.
|
||||
- Certificate parameters use base64 data. By default, the - C, - K parameters are the path of the CRT certificate and key file. If “base64://” begins, the subsequent data is thought to be Base64 encoded which will be decoded and used.
|
||||
|
||||
### Why need these?
|
||||
- Because for some reason, we cannot access our services elsewhere. We can build a secure tunnel to access our services through multiple connected proxy nodes.
|
||||
@ -48,7 +55,7 @@ PR needs to explain what changes have been made and why you change them.
|
||||
- ...
|
||||
|
||||
|
||||
This page is the v5.4 manual, and the other version of the manual can be checked by the following [link](docs/old-release.md).
|
||||
This page is the v6.0 manual, and the other version of the manual can be checked by the following [link](docs/old-release.md).
|
||||
|
||||
|
||||
### How to find the organization?
|
||||
@ -72,6 +79,7 @@ This page is the v5.4 manual, and the other version of the manual can be checked
|
||||
- [Safety advice](#safety-advice)
|
||||
|
||||
### Manual catalogues
|
||||
- [Load balance and high available](#load-balance-and-high-available)
|
||||
- [1.HTTP proxy](#1http-proxy)
|
||||
- [1.1 Common HTTP proxy](#11common-http-proxy)
|
||||
- [1.2 Common HTTP second level proxy](#12common-http-second-level-proxy)
|
||||
@ -88,7 +96,12 @@ This page is the v5.4 manual, and the other version of the manual can be checked
|
||||
- [1.11 Custom DNS](#111custom-dns)
|
||||
- [1.12 Custom encryption](#112-custom-encryption)
|
||||
- [1.13 Compressed transmission](#113-compressed-transmission)
|
||||
- [1.14 View help](#114view-help)
|
||||
- [1.14 load balance](#114-load-balance)
|
||||
- [1.15 speed limit](#115-speed-limit)
|
||||
- [1.16 Designated exporting IP](#116-designated-export-ip)
|
||||
- [1.17 Certificate parameters using Base64 data](#117-certificate-parameters-using-Base64-data)
|
||||
- [1.18 Intelligent mode](#118-intelligent-mode)
|
||||
- [1.19 View help](#119view-help)
|
||||
- [2.TCP proxy](#2tcp-proxy)
|
||||
- [2.1 Common TCP first level proxy](#21common-tcp-first-level-proxy)
|
||||
- [2.2 Common TCP second level proxy](#22common-tcp-second-level-proxy)
|
||||
@ -128,17 +141,28 @@ This page is the v5.4 manual, and the other version of the manual can be checked
|
||||
- [5.9 Custom DNS](#59custom-dns)
|
||||
- [5.10 Custom encryption](#510custom-encryption)
|
||||
- [5.11 Compressed transmission](#511compressed-transmission)
|
||||
- [5.12 View help](#512view-help)
|
||||
- [5.12 load balance](#512-load-balance)
|
||||
- [5.13 speed limit](#513-speed-limit)
|
||||
- [5.14 Designated exporting IP](#514-designated-exporting-ip)
|
||||
- [5.15 Cascade authentication](#515-cascade-authentication)
|
||||
- [5.16 Certificate parameters using Base64 data](#516-certificate-parameters-using-base64-data)
|
||||
- [5.17 Intelligent mode](#517-intelligent-mode)
|
||||
- [5.18 View help](#518view-help)
|
||||
- [6.Proxy protocol conversion](#6proxy-protocol-conversion)
|
||||
- [6.1 Functional introduction](#61functional-introduction)
|
||||
- [6.2 HTTP(S) to HTTP(S) + SOCKS5](#62http-to-http-socks5)
|
||||
- [6.3 SOCKS5 to HTTP(S) + SOCKS5](#63socks5-to-http-socks5)
|
||||
- [6.4 Chain style connection](#64chain-style-connection)
|
||||
- [6.5 Listening on multiple ports](#65listening-on-multiple-ports)
|
||||
- [6.6 Authentication](#66authentication)
|
||||
- [6.7 Custom encryption](#67-custom-encryption)
|
||||
- [6.8 Compressed transmission](#68-compressed-transmission)
|
||||
- [6.9 View Help](#69view-help)
|
||||
- [6.4 SS to HTTP(S)+SOCKS5+SS](#64-ss-to-httpssocks5ss)
|
||||
- [6.5 Chain style connection](#65chain-style-connection)
|
||||
- [6.6 Listening on multiple ports](#66listening-on-multiple-ports)
|
||||
- [6.7 Authentication](#67authentication)
|
||||
- [6.8 Custom encryption](#68-custom-encryption)
|
||||
- [6.9 Compressed transmission](#69-compressed-transmission)
|
||||
- [6.10 Disable-protocol](#610-disable-protocol)
|
||||
- [6.11 speed limit](#611-speed-limit)
|
||||
- [6.12 Designated exporting IP](#612-designated-exporting-ip)
|
||||
- [6.13 Certificate parameters using Base64 data](#613-certificate-parameters-using-base64-data)
|
||||
- [6.14 View Help](#614view-help)
|
||||
- [7.KCP Configuration](#7kcp-configuration)
|
||||
- [7.1 Configuration introduction](#71configuration-introduction)
|
||||
- [7.2 Configuration details](#72configuration-details)
|
||||
@ -155,7 +179,7 @@ tips:all operations require root permissions.
|
||||
```shell
|
||||
curl -L https://raw.githubusercontent.com/snail007/goproxy/master/install_auto.sh | bash
|
||||
```
|
||||
The installation is completed, the configuration directory is /etc/proxy, more detailed use of the method referred to the following manual for further understanding.
|
||||
The installation is completed, the configuration directory is /etc/proxy, For more detailed usage, please refer to the manual above to further understand the functions you want to use.
|
||||
If the installation fails or your VPS is not a linux64 system, please follow the semi-automatic step below:
|
||||
|
||||
#### Manual installation
|
||||
@ -164,7 +188,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.4/proxy-linux-amd64.tar.gz
|
||||
wget https://github.com/snail007/goproxy/releases/download/v6.0/proxy-linux-amd64.tar.gz
|
||||
|
||||
```
|
||||
#### **2.Download the automatic installation script**
|
||||
@ -177,12 +201,14 @@ chmod +x install.sh
|
||||
|
||||
#### Docker installation
|
||||
|
||||
[docker](https://hub.docker.com/r/snail007/goproxy)
|
||||
|
||||
Dockerfile root of project uses multistage build and alpine project to comply with best practices. Uses golang 1.10.3 for building as noted in the project README.md and will be pretty small image. total extracted size will be 17.3MB for goproxy latest version.
|
||||
|
||||
The default build process builds the master branch (latest commits/ cutting edge), and it can be configured to build specific version, just edit Dockerfile before build, following builds release version 5.4:
|
||||
The default build process builds the master branch (latest commits/ cutting edge), and it can be configured to build specific version, just edit Dockerfile before build, following builds release version 6.0:
|
||||
|
||||
```
|
||||
ARG GOPROXY_VERSION=v5.4
|
||||
ARG GOPROXY_VERSION=v6.0
|
||||
```
|
||||
|
||||
To Run:
|
||||
@ -261,6 +287,20 @@ When vps is behind the NAT, the network card IP on VPS is an internal network IP
|
||||
Assuming that your VPS outer external network IP is 23.23.23.23, the following command sets the 23.23.23.23 through the -g parameter.
|
||||
`./proxy http -g "23.23.23.23"`
|
||||
|
||||
### **Load balance and high available**
|
||||
HTTP(S)\SOCKS5\SPS proxy support Superior load balance and high availability. Multiple superiors repeat -P parameters.
|
||||
Load balancing have 5 kinds of policy, It can be specified by the `--lb-method` parameter.:
|
||||
roundrobin take turns
|
||||
leastconn Using minimum connection number
|
||||
leasttime Use minimum connection time
|
||||
hash Use the client address to calculate a fixed superior
|
||||
weight According to the weight and connection number of each superior, choose a superior
|
||||
Tips:
|
||||
The load balance check interval can be set by `--lb-retrytime`, unit milliseconds.
|
||||
Load balancing connection timeout can be set by `--lb-timeout`, unit milliseconds.
|
||||
If the load balance policy is weighted (weight), the -P format is: 2.2.2.2:3880@1,1 is the weight which is greater than 0.
|
||||
If the load balance strategy is hash, the default is to select the parent based on the client address, and the parent can be selected by switching `- lb-hashtarget', using the access destination address.
|
||||
|
||||
### **1.HTTP proxy**
|
||||
#### **1.1.common HTTP proxy**
|
||||

|
||||
@ -287,7 +327,7 @@ accessing the local 8080 port is accessing the proxy port 38080 above VPS.
|
||||
|
||||
HTTP second level proxy(local windows)
|
||||
`./proxy.exe http -t tcp -p ":8080" -T tls -P "22.22.22.22:38080" -C proxy.crt -K proxy.key`
|
||||
In your windos system, the mode of the program that needs to surf the Internet by proxy is setted up as HTTP mode, the address is 127.0.0.1, the port is: 8080, the program can go through the encrypted channel through VPS to surf on the internet.
|
||||
In your windows system, the mode of the program that needs to surf the Internet by proxy is setted up as HTTP mode, the address is 127.0.0.1, the port is: 8080, the program can go through the encrypted channel through VPS to surf on the internet.
|
||||
|
||||
#### **1.4.HTTP third level encrypted proxy**
|
||||

|
||||
@ -459,7 +499,40 @@ Local third level execution:
|
||||
`proxy http -T tcp -P 3.3.3.3:8888 -M -t tcp -p :8080`
|
||||
through this way, When you visits the website by local proxy 8080, it visits the target website by compressed transmission with the parents proxy.
|
||||
|
||||
#### **1.14.view help**
|
||||
### **1.14 Load balance**
|
||||
HTTP (S) proxy supports superior load balance, and multiple -P parameters can be repeated by multiple superiors.
|
||||
`proxy http --lb-method=hash -T tcp -P 1.1.1.1:33080 -P 2.1.1.1:33080 -P 3.1.1.1:33080`
|
||||
|
||||
#### **1.14.1 Set retry interval and timeout time**
|
||||
`proxy http --lb-method=leastconn --lb-retrytime 300 --lb-timeout 300 -T tcp -P 1.1.1.1:33080 -P 2.1.1.1:33080 -P 3.1.1.1:33080 -t tcp -p :33080`
|
||||
|
||||
#### **1.14.2 Set weight**
|
||||
`proxy http --lb-method=weight -T tcp -P 1.1.1.1:33080@1 -P 2.1.1.1:33080@2 -P 3.1.1.1:33080@1 -t tcp -p :33080`
|
||||
|
||||
#### **1.14.3 Use target address to select superior**
|
||||
`proxy http --lb-hashtarget --lb-method=leasttime -T tcp -P 1.1.1.1:33080 -P 2.1.1.1:33080 -P 3.1.1.1:33080 -t tcp -p :33080`
|
||||
|
||||
### **1.15 Speed limit**
|
||||
The speed limit is 100K, which can be specified through the `-l` parameter, for example: 100K 1.5M. 0 means unlimited.
|
||||
`proxy http -t tcp -p 2.2.2.2:33080 -l 100K`
|
||||
|
||||
### **1.16 Designated exporting IP**
|
||||
The `--bind-listen` parameter open the client's ability to access the target site with an entry IP connection, using the entry IP as the exporting IP. If the entry IP is the intranet IP, the exporting IP will not use the entry IP..
|
||||
`proxy http -t tcp -p 2.2.2.2:33080 --bind-listen`
|
||||
|
||||
### **1.17 Certificate parameters using Base64 data**
|
||||
By default, the -C and -K parameters are the paths of CRT certificates and key files,
|
||||
If it is the beginning of base64://, then it is considered that the data behind is Base64 encoded and will be used after decoding.
|
||||
|
||||
#### **1.18 Intelligent mode**
|
||||
Intelligent mode setting which can be one of intelligent|direct|parent.
|
||||
default:intelligent.
|
||||
The meaning of each value is as follows:
|
||||
`--intelligent=direct`, Targets that are not in blocked directly connected.
|
||||
`--intelligent=parent`, Targets that are not in direct connect to parent proxy.
|
||||
`--intelligent=intelligent`, Targets that are not in direct and blocked Neither can intelligently judge on whether to connetc parent proxy.
|
||||
|
||||
#### **1.19.view help**
|
||||
`./proxy help http`
|
||||
|
||||
### **2.TCP proxy**
|
||||
@ -868,41 +941,88 @@ Local third level execution:
|
||||
`proxy socks -T tcp -P 3.3.3.3:8888 -M -t tcp -p :8080`
|
||||
through this way, When you visits the website by local proxy 8080, it visits the target website by compressed transmission with the parents proxy.
|
||||
|
||||
#### **5.12.view help**
|
||||
#### **5.12 Load balance**
|
||||
SOCKS proxy supports the load balancing of superior authorities, and the -P parameters can be repeated by multiple superiors.
|
||||
`proxy socks --lb-method=hash -T tcp -P 1.1.1.1:33080 -P 2.1.1.1:33080 -P 3.1.1.1:33080 -p :33080 -t tcp`
|
||||
|
||||
#### **5.12.1 Set retry interval and timeout time**
|
||||
`proxy socks --lb-method=leastconn --lb-retrytime 300 --lb-timeout 300 -T tcp -P 1.1.1.1:33080 -P 2.1.1.1:33080 -P 3.1.1.1:33080 -p :33080 -t tcp`
|
||||
|
||||
#### **5.12.2 Set weight**
|
||||
`proxy socks --lb-method=weight -T tcp -P 1.1.1.1:33080@1 -P 2.1.1.1:33080@2 -P 3.1.1.1:33080@1 -p :33080 -t tcp`
|
||||
|
||||
#### **5.12.3 Use target address to select parent proxy**
|
||||
`proxy socks --lb-hashtarget --lb-method=leasttime -T tcp -P 1.1.1.1:33080 -P 2.1.1.1:33080 -P 3.1.1.1:33080 -p :33080 -t tcp`
|
||||
|
||||
#### **5.13 Speed limit**
|
||||
The speed limit is 100K, which can be specified through the -l parameter, for example: 100K 1.5M. 0 means unlimited.
|
||||
`proxy socks -t tcp -p 2.2.2.2:33080 -l 100K`
|
||||
|
||||
#### **5.14 Designated exporting IP**
|
||||
The `- bind-listen` parameter opens the client's ability to access the target site with an entry IP connection, using the entry IP as the exporting IP. If the entry IP is the intranet IP, the exporting IP will not use the entry IP..
|
||||
`proxy socks -t tcp -p 2.2.2.2:33080 --bind-listen`
|
||||
|
||||
#### **5.15 Cascade authentication**
|
||||
SOCKS5 supports cascading authentication, and -A can set up parents proxy's authentication information..
|
||||
parents proxy:
|
||||
`proxy socks -t tcp -p 2.2.2.2:33080 -a user:pass`
|
||||
localhost:
|
||||
`proxy socks -T tcp -P 2.2.2.2:33080 -A user:pass -t tcp -p :33080`
|
||||
|
||||
#### **5.16 Certificate parameters using Base64 data**
|
||||
By default, the -C and -K parameters are the paths of CRT certificates and key files,
|
||||
If it is the beginning of base64://, then it is considered that the data behind is Base64 encoded and will be used after decoding.
|
||||
|
||||
#### **5.17 Intelligent mode**
|
||||
Intelligent mode setting which can be one of intelligent|direct|parent.
|
||||
default:intelligent.
|
||||
The meaning of each value is as follows:
|
||||
`--intelligent=direct`, Targets that are not in blocked directly connected.
|
||||
`--intelligent=parent`, Targets that are not in direct connect to parent proxy.
|
||||
`--intelligent=intelligent`, Targets that are not in direct and blocked Neither can intelligently judge on whether to connetc parent proxy.
|
||||
|
||||
#### **5.18.view help**
|
||||
`./proxy help socks`
|
||||
|
||||
### **6.Proxy protocol conversion**
|
||||
|
||||
#### **6.1.Functional introduction**
|
||||
The proxy protocol conversion use the SPS subcommand (abbreviation of socks+https), SPS itself does not provide the proxy function, just accept the proxy request and then converse protocol and forwarded to the existing HTTP (s) or Socks5 proxy. SPS can use existing HTTP (s) or Socks5 proxy converse to support HTTP (s) and Socks5 HTTP (s) proxy at the same time by one port, and proxy supports forward and reverse proxy (SNI), SOCKS5 proxy which is also does support UDP when parent is Socks5. in addition to the existing HTTP or Socks5 proxy, which supports TLS, TCP, KCP three modes and chain-style connection. That is more than one SPS node connection can build encryption channel.
|
||||
The proxy protocol conversion use the SPS subcommand, SPS itself does not provide the proxy function, just accept the proxy request and then converse protocol and forwarded to the existing HTTP (s) or Socks5 proxy. SPS can use existing HTTP (s) or Socks5 proxy converse to support HTTP (s) and Socks5 HTTP (s) proxy at the same time by one port, and proxy supports forward and reverse proxy (SNI), SOCKS5 proxy which is also does support UDP when parent is Socks5. in addition to the existing HTTP or Socks5 proxy, which supports TLS, TCP, KCP three modes and chain-style connection. That is more than one SPS node connection can build encryption channel.
|
||||
|
||||
#### **6.2.HTTP(S) to HTTP(S) + SOCKS5**
|
||||
Suppose there is a common HTTP (s) proxy: 127.0.0.1:8080. Now we turn it into a common proxy that supports HTTP (s) and Socks5 at the same time. The local port after transformation is 18080.
|
||||
Suppose there is a common HTTP (s) proxy: 127.0.0.1:8080. Now we turn it into a common proxy that supports HTTP (s), Socks5 and ss at the same time. The local port after transformation is 18080. ss's Encryption method is aes-192-cfb and its password is pass.
|
||||
command:
|
||||
`./proxy sps -S http -T tcp -P 127.0.0.1:8080 -t tcp -p :18080`
|
||||
`./proxy sps -S http -T tcp -P 127.0.0.1:8080 -t tcp -p :18080 -h aes-192-cfb -j pass`
|
||||
|
||||
Suppose that there is a TLS HTTP (s) proxy: 127.0.0.1:8080. Now we turn it into a common proxy that supports HTTP (s) and Socks5 at the same time. The local port after transformation is 18080, TLS needs certificate file.
|
||||
Suppose that there is a TLS HTTP (s) proxy: 127.0.0.1:8080. Now we turn it into a common proxy that supports HTTP (s), Socks5 and ss at the same time. The local port after transformation is 18080, TLS needs certificate file,ss's Encryption method is aes-192-cfb and its password is pass.
|
||||
command:
|
||||
`./proxy sps -S http -T tls -P 127.0.0.1:8080 -t tcp -p :18080 -C proxy.crt -K proxy.key`
|
||||
`./proxy sps -S http -T tls -P 127.0.0.1:8080 -t tcp -p :18080 -C proxy.crt -K proxy.key -h aes-192-cfb -j pass`
|
||||
|
||||
Suppose there is a KCP HTTP (s) proxy (password: demo123): 127.0.0.1:8080. Now we turn it into a common proxy that supports HTTP (s) and Socks5 at the same time. The local port after transformation is 18080.
|
||||
Suppose there is a KCP HTTP (s) proxy (password: demo123): 127.0.0.1:8080. Now we turn it into a common proxy that supports HTTP (s), Socks5 and ss at the same time. The local port after transformation is 18080. ss's Encryption method is aes-192-cfb and its password is pass.
|
||||
command:
|
||||
`./proxy sps -S http -T kcp -P 127.0.0.1:8080 -t tcp -p :18080 --kcp-key demo123`
|
||||
`./proxy sps -S http -T kcp -P 127.0.0.1:8080 -t tcp -p :18080 --kcp-key demo123 -h aes-192-cfb -j pass`
|
||||
|
||||
#### **6.3.SOCKS5 to HTTP(S) + SOCKS5**
|
||||
Suppose there is a common Socks5 proxy: 127.0.0.1:8080, now we turn it into a common proxy that supports HTTP (s) and Socks5 at the same time, and the local port after transformation is 18080.
|
||||
Suppose there is a common Socks5 proxy: 127.0.0.1:8080, now we turn it into a common proxy that supports HTTP (s), Socks5 and ss at the same time, and the local port after transformation is 18080. ss's Encryption method is aes-192-cfb and its password is pass.
|
||||
command:
|
||||
`./proxy sps -S socks -T tcp -P 127.0.0.1:8080 -t tcp -p :18080`
|
||||
`./proxy sps -S socks -T tcp -P 127.0.0.1:8080 -t tcp -p :18080 -h aes-192-cfb -j pass`
|
||||
|
||||
Suppose there is a TLS Socks5 proxy: 127.0.0.1:8080. Now we turn it into a common proxy that support HTTP (s) and Socks5 at the same time. The local port after transformation is 18080, TLS needs certificate file.
|
||||
Suppose there is a TLS Socks5 proxy: 127.0.0.1:8080. Now we turn it into a common proxy that supports HTTP (s), Socks5 and ss at the same time. The local port after transformation is 18080, TLS needs certificate file. ss's Encryption method is aes-192-cfb and its password is pass.
|
||||
command:
|
||||
`./proxy sps -S socks -T tls -P 127.0.0.1:8080 -t tcp -p :18080 -C proxy.crt -K proxy.key`
|
||||
`./proxy sps -S socks -T tls -P 127.0.0.1:8080 -t tcp -p :18080 -C proxy.crt -K proxy.key -h aes-192-cfb -j pass`
|
||||
|
||||
Suppose there is a KCP Socks5 proxy (password: demo123): 127.0.0.1:8080, now we turn it into a common proxy that support HTTP (s) and Socks5 at the same time, and the local port after transformation is 18080.
|
||||
Suppose there is a KCP Socks5 proxy (password: demo123): 127.0.0.1:8080, now we turn it into a common proxy that supports HTTP (s), Socks5 and ss at the same time, and the local port after transformation is 18080. ss's Encryption method is aes-192-cfb and its password is pass.
|
||||
command:
|
||||
`./proxy sps -S socks -T kcp -P 127.0.0.1:8080 -t tcp -p :18080 --kcp-key demo123`
|
||||
`./proxy sps -S socks -T kcp -P 127.0.0.1:8080 -t tcp -p :18080 --kcp-key demo123 -h aes-192-cfb -j pass`
|
||||
|
||||
#### **6.4.Chain style connection**
|
||||
#### **6.4 SS to HTTP(S)+SOCKS5+SS**
|
||||
SPS support the SS protocol with the local authorities. The parent proxy can be SPS or standard SS services.
|
||||
By default, SPS provides three proxies, HTTP (S), SOCKS5 and SPS. the converted SOCKS5 and SS support UDP when the parent proxy is SOCKS5.
|
||||
Suppose there is an ordinary SS or SPS proxy (open SS, encryption: aes-256-cfb, password: Demo):127.0.0.1:8080,Now we turn it into a common proxy that supports both http (s) and Socks5 and ss. The converted local port is 18080, and the converted ss encryption mode is aes-192-cfb, ss password:pass.
|
||||
command:
|
||||
`./proxy sps -S socks -T kcp -P 127.0.0.1:8080 -t tcp -p :18080 --kcp-key demo123` `./proxy sps -S ss -H aes-256-cfb -J pass -T tcp -P 127.0.0.1:8080 -t tcp -p :18080 -h aes-192-cfb -j pass`.
|
||||
|
||||
#### **6.5.Chain style connection**
|
||||

|
||||
It is mentioned above that multiple SPS nodes can be connected to build encrypted channels, assuming you have the following VPS and a PC.
|
||||
vps01:2.2.2.2
|
||||
@ -922,11 +1042,11 @@ Then run a SPS node on the PC,excute:
|
||||
|
||||
finish。
|
||||
|
||||
#### **6.5.Listening on multiple ports**
|
||||
#### **6.6.Listening on multiple ports**
|
||||
In general, listening one port is enough, but if you need to monitor 80 and 443 ports at the same time as a reverse proxy, the -p parameter can support it.
|
||||
The format is:`-p 0.0.0.0:80,0.0.0.0:443`, Multiple bindings are separated by a comma.
|
||||
|
||||
#### **6.6.Authentication**
|
||||
#### **6.7.Authentication**
|
||||
SPS supports HTTP(s)\socks5 proxy authentication, which can concatenate authentication, there are four important information:
|
||||
1:Users send authentication information`user-auth`。
|
||||
2:Local authentication information set up`local-auth`。
|
||||
@ -968,7 +1088,7 @@ target: if the client is the HTTP (s) proxy request, this represents the complet
|
||||
If there is no -a or -F or --auth-url parameters, local authentication is closed.
|
||||
If there is no -A parameter, the connection to the father proxy does not use authentication.
|
||||
|
||||
#### **6.7 Custom encryption**
|
||||
#### **6.8 Custom encryption**
|
||||
HTTP(s) proxy can encrypt TCP data by TLS standard encryption and KCP protocol encryption, in addition to supporting custom encryption after TLS and KCP, That is to say, custom encryption and tls|kcp can be combined to use. The internal AES256 encryption is used, and it only needs to define one password by yourself. Encryption is divided into two parts, the one is whether the local (-z) is encrypted and decrypted, the other is whether the parents (-Z) is encrypted and decrypted.
|
||||
Custom encryption requires both ends are proxy. Next, we use two level example and three level example as examples:
|
||||
Suppose there is already a HTTP (s) proxy:`6.6.6.6:6666`
|
||||
@ -989,7 +1109,7 @@ Local third level execution:
|
||||
`proxy sps -T tcp -P 3.3.3.3:8888 -Z other_password -t tcp -p :8080`
|
||||
through this way, When you visits the website by local proxy 8080, it visits the target website by encryption transmission with the parents proxy.
|
||||
|
||||
#### **6.8 Compressed transmission**
|
||||
#### **6.9 Compressed transmission**
|
||||
HTTP(s) proxy can encrypt TCP data through TCP standard encryption and KCP protocol encryption, and can also compress data before custom encryption.
|
||||
That is to say, compression and custom encryption and tls|kcp can be used together, compression is divided into two parts, the one is whether the local (-z) is compressed transmission, the other is whether the parents (-Z) is compressed transmission.
|
||||
The compression requires both ends are proxy. Compression also protects the (encryption) data in certain extent. we use two level example and three level example as examples:
|
||||
@ -1004,13 +1124,36 @@ through this way, When you visits the website by local proxy 8080, it visits the
|
||||
**three level example**
|
||||
First level VPS (ip:2.2.2.2) execution:
|
||||
`proxy sps -t tcp -m -p :7777`
|
||||
Second level VPS (ip:3.3.3.3) execution::
|
||||
Second level VPS (ip:3.3.3.3) execution:
|
||||
`proxy sps -T tcp -P 2.2.2.2:7777 -M -t tcp -m -p :8888`
|
||||
Local third level execution:
|
||||
`proxy sps -T tcp -P 3.3.3.3:8888 -M -t tcp -p :8080`
|
||||
through this way, When you visits the website by local proxy 8080, it visits the target website by compressed transmission with the parents proxy.
|
||||
|
||||
#### **6.9.view help**
|
||||
#### **6.10 Disable protocol**
|
||||
By default, SPS's port supports two proxy protocols, http (s) and socks5, and we can disable a protocol with parameters.
|
||||
for example:
|
||||
1.Disable the HTTP (S) proxy, retaining only the SOCKS5 proxy,parameter:`--disable-http`.
|
||||
`proxy sps -T tcp -P 3.3.3.3:8888 -M -t tcp -p :8080 --disable-http`
|
||||
1.Disable the SOCKS5 proxy, retaining only the HTTP (S) proxy,parameter:`--disable-socks`.
|
||||
`proxy sps -T tcp -P 3.3.3.3:8888 -M -t tcp -p :8080 --disable-http`
|
||||
|
||||
#### **6.11 Speed limit**
|
||||
Suppose there has a SOCKS5 parent proxy:
|
||||
`proxy socks -p 2.2.2.2:33080 -z password -t tcp`
|
||||
SPS lower speed limit 100K
|
||||
`proxy sps -S socks -P 2.2.2.2:33080 -T tcp -Z password -l 100K -t tcp -p :33080`
|
||||
It can be specified through the `-l` parameter, for example: 100K 1.5M. 0 means unlimited.
|
||||
|
||||
#### **6.12 Designated exporting IP**
|
||||
The `- bind-listen` parameter opens the client's ability to access the target site with an entry IP connection, using the entry IP as the exporting IP. If the entry IP is the intranet IP, the exporting IP will not use the entry IP.
|
||||
`proxy sps -S socks -P 2.2.2.2:33080 -T tcp -Z password -l 100K -t tcp --bind-listen -p :33080`
|
||||
|
||||
#### **6.13 Certificate parameters using Base64 data**
|
||||
By default, the -C and -K parameters are the paths of CRT certificates and key files,
|
||||
If it is the beginning of base64://, then it is considered that the data behind is Base64 encoded and will be used after decoding.
|
||||
|
||||
#### **6.14.view help**
|
||||
`./proxy help sps`
|
||||
|
||||
### **7.KCP Configuration**
|
||||
@ -1128,16 +1271,15 @@ execution: `go run *.go`
|
||||
|
||||
### License
|
||||
Proxy is licensed under GPLv3 license.
|
||||
|
||||
### Contact
|
||||
proxy QQ group:189618940
|
||||
proxy QQ group: 793015219 , 189618940 (full)
|
||||
|
||||
### Donation
|
||||
if proxy help you a lot,you can support us by:
|
||||
|
||||
### AliPay
|
||||
<img src="https://github.com/snail007/goproxy/blob/master/docs/images/alipay.jpg?raw=true" width="200"/>
|
||||
|
||||
### Wechat Pay
|
||||
<img src="https://github.com/snail007/goproxy/blob/master/docs/images/wxpay.jpg?raw=true" width="200"/>
|
||||
|
||||
|
||||
|
||||
|
||||
81
README_ZH.md
81
README_ZH.md
@ -1,7 +1,7 @@
|
||||
<img src="https://github.com/snail007/goproxy/blob/master/docs/images/logo.jpg?raw=true" width="200"/>
|
||||
Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5,ss代理服务器,支持正向代理、反向代理、透明代理、内网穿透、TCP/UDP端口映射、SSH中转、TLS加密传输、协议转换、防污染DNS代理。
|
||||
|
||||
[点击下载](https://github.com/snail007/goproxy/releases) 官方QQ交流群:189618940
|
||||
[点击下载](https://github.com/snail007/goproxy/releases) 官方QQ交流群: 793015219 (2群), 189618940 (1群满)
|
||||
|
||||
---
|
||||
|
||||
@ -9,9 +9,11 @@ Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5,ss代理服
|
||||
|
||||
**[English Manual](/README.md)**
|
||||
|
||||
**[全平台图形界面版本](/gui/README.md)**
|
||||
**[全平台图形界面版本](/gui/README_ZH.md)**
|
||||
|
||||
**[全平台SDK](/sdk/README.md)**
|
||||
**[全平台SDK](/sdk/README_ZH.md)**
|
||||
|
||||
**[GoProxy特殊授权](/AUTHORIZATION_ZH.md)**
|
||||
|
||||
### 如何贡献代码(Pull Request)?
|
||||
|
||||
@ -54,7 +56,7 @@ Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5,ss代理服
|
||||
- ...
|
||||
|
||||
|
||||
本页是v5.4手册,其他版本手册请点击[这里](docs/old-release.md)查看.
|
||||
本页是v5.4手册,其他版本手册请点击[这里](docs/old-release-zh.md)查看.
|
||||
|
||||
|
||||
### 怎么找到组织?
|
||||
@ -97,7 +99,8 @@ Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5,ss代理服
|
||||
- [1.15 限速](#115-限速)
|
||||
- [1.16 指定出口IP](#116-指定出口ip)
|
||||
- [1.17 证书参数使用base64数据](#117-证书参数使用base64数据)
|
||||
- [1.18 查看帮助](#118-查看帮助)
|
||||
- [1.18 智能模式](#118-智能模式)
|
||||
- [1.19 查看帮助](#119-查看帮助)
|
||||
- [2. TCP代理(端口映射)](#2tcp代理)
|
||||
- [2.1 普通一级TCP代理](#21普通一级tcp代理)
|
||||
- [2.2 普通二级TCP代理](#22普通二级tcp代理)
|
||||
@ -142,7 +145,8 @@ Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5,ss代理服
|
||||
- [5.14 指定出口IP](#514-指定出口ip)
|
||||
- [5.15 级联认证](#515-级联认证)
|
||||
- [5.16 证书参数使用base64数据](#516-证书参数使用base64数据)
|
||||
- [5.17 查看帮助](#517查看帮助)
|
||||
- [5.17 智能模式](#517-智能模式)
|
||||
- [5.18 查看帮助](#518-查看帮助)
|
||||
- [6. 代理协议转换](#6代理协议转换)
|
||||
- [6.1 功能介绍](#61-功能介绍)
|
||||
- [6.2 HTTP(S)转HTTP(S)+SOCKS5+SS](#62-https转httpssocks5ss)
|
||||
@ -169,21 +173,27 @@ Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5,ss代理服
|
||||
提示:所有操作需要root权限.
|
||||
#### 自动安装
|
||||
#### **0.如果你的VPS是linux64位的系统,那么只需要执行下面一句,就可以完成自动安装和配置.**
|
||||
|
||||
```shell
|
||||
curl -L https://raw.githubusercontent.com/snail007/goproxy/master/install_auto.sh | bash
|
||||
```
|
||||
|
||||
安装完成,配置目录是/etc/proxy,更详细的使用方法请参考上面的手册目录,进一步了解你想要使用的功能.
|
||||
如果安装失败或者你的vps不是linux64位系统,请按照下面的半自动步骤安装:
|
||||
|
||||
#### 手动安装
|
||||
|
||||
#### **1.下载proxy**
|
||||
下载地址:https://github.com/snail007/goproxy/releases
|
||||
下载地址:https://github.com/snail007/goproxy/releases/latest
|
||||
下面以v6.2为例,如果有最新版,请使用最新版链接.
|
||||
|
||||
```shell
|
||||
cd /root/proxy/
|
||||
wget https://github.com/snail007/goproxy/releases/download/v6.0/proxy-linux-amd64.tar.gz
|
||||
wget https://github.com/snail007/goproxy/releases/download/v6.2/proxy-linux-amd64.tar.gz
|
||||
```
|
||||
|
||||
#### **2.下载自动安装脚本**
|
||||
|
||||
```shell
|
||||
cd /root/proxy/
|
||||
wget https://raw.githubusercontent.com/snail007/goproxy/master/install.sh
|
||||
@ -192,6 +202,9 @@ chmod +x install.sh
|
||||
```
|
||||
|
||||
#### Docker安装
|
||||
|
||||
[docker](https://hub.docker.com/r/snail007/goproxy)
|
||||
|
||||
项目根目录的Dockerfile文件用来构建,使用golang 1.10.3,构建基于goproxy的master分支最新版本,
|
||||
全部大小17.3MB,默认情况下使用master分支,不过可以通过修改配置文件Dockerfile
|
||||
或者使用参数GOPROXY_VERSION指定构建的goproxy版本.
|
||||
@ -356,11 +369,12 @@ weight 根据每个上级的权重和连接数情况,选择出一个上级
|
||||
比如:
|
||||
`./proxy http -t tcp -p ":33080" --auth-url "http://test.com/auth.php"`
|
||||
用户连接的时候,proxy会GET方式请求这url("http://test.com/auth.php"),
|
||||
带上user,pass,ip,target四个参数:
|
||||
http://test.com/auth.php?user={USER}&pass={PASS}&ip={IP}&target={TARGET}
|
||||
带上user,pass,ip,local_ip,target五个参数:
|
||||
http://test.com/auth.php?user={USER}&pass={PASS}&ip={IP}&local_ip={LOCAL_IP}&target={TARGET}
|
||||
user:用户名
|
||||
pass:密码
|
||||
ip:用户的IP,比如:192.168.1.200
|
||||
local_ip:用户访问的服务器的IP,比如:3.3.3.3
|
||||
target:用户访问的URL,比如:http://demo.com:80/1.html或https://www.baidu.com:80
|
||||
|
||||
如果没有-a或-F或--auth-url参数,就是关闭Basic认证.
|
||||
@ -378,7 +392,7 @@ target:用户访问的URL,比如:http://demo.com:80/1.html或https://www.baidu.c
|
||||
|
||||
##### ***1.7.1 ssh用户名和密码的方式***
|
||||
本地HTTP(S)代理28080端口,执行:
|
||||
`./proxy http -T ssh -P "2.2.2.2:22" -u user -A demo -t tcp -p ":28080"`
|
||||
`./proxy http -T ssh -P "2.2.2.2:22" -u user -D demo -t tcp -p ":28080"`
|
||||
##### ***1.7.2 ssh用户名和密钥的方式***
|
||||
本地HTTP(S)代理28080端口,执行:
|
||||
`./proxy http -T ssh -P "2.2.2.2:22" -u user -S user.key -t tcp -p ":28080"`
|
||||
@ -523,7 +537,7 @@ HTTP(S)代理支持上级负载均衡,多个上级重复-P参数即可.
|
||||
|
||||
#### **1.14.3 使用目标地址选择上级**
|
||||
|
||||
`proxy http --lb-hashtarget --lb-method=leasttime -T tcp -P 1.1.1.1:33080 -P 2.1.1.1:33080 -P 3.1.1.1:33080 -t tcp -p :33080`
|
||||
`proxy http --lb-hashtarget --lb-method=hash -T tcp -P 1.1.1.1:33080 -P 2.1.1.1:33080 -P 3.1.1.1:33080 -t tcp -p :33080`
|
||||
|
||||
### **1.15 限速**
|
||||
|
||||
@ -543,7 +557,15 @@ HTTP(S)代理支持上级负载均衡,多个上级重复-P参数即可.
|
||||
|
||||
如果是base64://开头,那么就认为后面的数据是base64编码的,会解码后使用.
|
||||
|
||||
#### **1.18 查看帮助**
|
||||
#### **1.18 智能模式**
|
||||
智能模式设置,可以是intelligent|direct|parent三者之一.
|
||||
默认是:intelligent.
|
||||
每个值的含义如下:
|
||||
`--intelligent=direct`,不在blocked里面的目标都直连.
|
||||
`--intelligent=parent`,不在direct里面的目标都走上级.
|
||||
`--intelligent=intelligent`,blocked和direct里面都没有的目标,智能判断是否使用上级访问目标.
|
||||
|
||||
#### **1.19 查看帮助**
|
||||
`./proxy help http`
|
||||
|
||||
### **2.TCP代理**
|
||||
@ -877,7 +899,7 @@ SOCKS5代理,支持CONNECT,UDP协议,不支持BIND,支持用户名密码认证.
|
||||
|
||||
##### ***5.6.1 ssh用户名和密码的方式***
|
||||
本地SOCKS5代理28080端口,执行:
|
||||
`./proxy socks -T ssh -P "2.2.2.2:22" -u user -A demo -t tcp -p ":28080"`
|
||||
`./proxy socks -T ssh -P "2.2.2.2:22" -u user -D demo -t tcp -p ":28080"`
|
||||
##### ***5.6.2 ssh用户名和密钥的方式***
|
||||
本地SOCKS5代理28080端口,执行:
|
||||
`./proxy socks -T ssh -P "2.2.2.2:22" -u user -S user.key -t tcp -p ":28080"`
|
||||
@ -897,11 +919,12 @@ SOCKS5代理,支持CONNECT,UDP协议,不支持BIND,支持用户名密码认证.
|
||||
比如:
|
||||
`./proxy socks -t tcp -p ":33080" --auth-url "http://test.com/auth.php"`
|
||||
用户连接的时候,proxy会GET方式请求这url("http://test.com/auth.php"),
|
||||
带上user,pass,ip,三个参数:
|
||||
http://test.com/auth.php?user={USER}&pass={PASS}&ip={IP}
|
||||
带上user,pass,ip,local_ip四个参数:
|
||||
http://test.com/auth.php?user={USER}&pass={PASS}&ip={IP}&local_ip={LOCAL_IP}
|
||||
user:用户名
|
||||
pass:密码
|
||||
ip:用户的IP,比如:192.168.1.200
|
||||
local_ip:用户访问的服务器的IP,比如:3.3.3.3
|
||||
|
||||
如果没有-a或-F或--auth-url参数,就是关闭认证.
|
||||
|
||||
@ -989,7 +1012,7 @@ SOCKS代理支持上级负载均衡,多个上级重复-P参数即可.
|
||||
|
||||
#### **5.12.3 使用目标地址选择上级**
|
||||
|
||||
`proxy socks --lb-hashtarget --lb-method=leasttime -T tcp -P 1.1.1.1:33080 -P 2.1.1.1:33080 -P 3.1.1.1:33080 -p :33080 -t tcp`
|
||||
`proxy socks --lb-hashtarget --lb-method=hash -T tcp -P 1.1.1.1:33080 -P 2.1.1.1:33080 -P 3.1.1.1:33080 -p :33080 -t tcp`
|
||||
|
||||
#### **5.13 限速**
|
||||
|
||||
@ -1022,7 +1045,15 @@ SOCKS5支持级联认证,-A可以设置上级认证信息.
|
||||
如果是base64://开头,那么就认为后面的数据是base64编码的,会解码后使用.
|
||||
|
||||
|
||||
#### **5.17.查看帮助**
|
||||
#### **5.17 智能模式**
|
||||
智能模式设置,可以是intelligent|direct|parent三者之一.
|
||||
默认是:intelligent.
|
||||
每个值的含义如下:
|
||||
`--intelligent=direct`,不在blocked里面的目标都直连.
|
||||
`--intelligent=parent`,不在direct里面的目标都走上级.
|
||||
`--intelligent=intelligent`,blocked和direct里面都没有的目标,智能判断是否使用上级访问目标.
|
||||
|
||||
#### **5.18.查看帮助**
|
||||
`./proxy help socks`
|
||||
|
||||
### **6.代理协议转换**
|
||||
@ -1129,6 +1160,18 @@ target:如果客户端是http(s)代理请求,这里代表的是请求的完整ur
|
||||
如果没有-a或-F或--auth-url参数,就是关闭本地认证.
|
||||
如果没有-A参数,连接上级不使用认证.
|
||||
|
||||
**设置单独认证信息**
|
||||
|
||||
如果存在多个不同上级,而且他们的密码有的一样有的不一样,那么可以针对每个上级设置认证信息,
|
||||
同时还可以用-A参数设置一个全局认证信息,如果某个上级没有单独设置认证信息就使用全局设置的认证信息.
|
||||
认证信息和上级写在一起.
|
||||
格式是: YTpi#2.2.2.2:33080@1
|
||||
说明:
|
||||
YTpi 是经过base64编码的认证信息,比如是http(s)/socks原始认证信息a:b,用户是a密码是b,base64编码之后是:YTpi
|
||||
如果是ss,那么a就是加密方法,b是密码,比如:aes-192-cfb:your_pass,base64编码之后是:YWVzLTE5Mi1jZmI6eW91cl9wYXNz
|
||||
# 是间隔符号,如果有认证信息,必须有#,没有认证信息可以省略#
|
||||
2.2.2.2:33080 是上级地址
|
||||
@1 是设置权重,没有可以省略,详细说明可以参考手册***权重部分***
|
||||
|
||||
#### **6.8 自定义加密**
|
||||
proxy的sps代理在tcp之上可以通过tls标准加密以及kcp协议加密tcp数据,除此之外还支持在tls和kcp之后进行
|
||||
@ -1342,7 +1385,7 @@ utils是工具包,service是具体的每个服务类.
|
||||
### License
|
||||
Proxy is licensed under GPLv3 license.
|
||||
### Contact
|
||||
QQ交流群:189618940
|
||||
官方QQ交流群: 793015219 (2群), 189618940 (1群满)
|
||||
|
||||
|
||||
### Donation
|
||||
|
||||
50
config.go
50
config.go
@ -12,12 +12,14 @@ import (
|
||||
"path/filepath"
|
||||
"runtime/debug"
|
||||
"runtime/pprof"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/snail007/goproxy/core/lib/kcpcfg"
|
||||
encryptconn "github.com/snail007/goproxy/core/lib/transport/encrypt"
|
||||
sdk "github.com/snail007/goproxy/sdk/android-ios"
|
||||
services "github.com/snail007/goproxy/services"
|
||||
httpx "github.com/snail007/goproxy/services/http"
|
||||
"github.com/snail007/goproxy/services/kcpcfg"
|
||||
keygenx "github.com/snail007/goproxy/services/keygen"
|
||||
mux "github.com/snail007/goproxy/services/mux"
|
||||
socksx "github.com/snail007/goproxy/services/socks"
|
||||
@ -35,8 +37,9 @@ var (
|
||||
app *kingpin.Application
|
||||
service *services.ServiceItem
|
||||
cmd *exec.Cmd
|
||||
cpuProfilingFile, memProfilingFile, blockProfilingFile, goroutineProfilingFile, threadcreateProfilingFile *os.File
|
||||
isDebug bool
|
||||
cpuProfilingFile, memProfilingFile, blockProfilingFile,
|
||||
goroutineProfilingFile, threadcreateProfilingFile *os.File
|
||||
isDebug *bool
|
||||
)
|
||||
|
||||
func initConfig() (err error) {
|
||||
@ -58,7 +61,7 @@ func initConfig() (err error) {
|
||||
//build srvice args
|
||||
app = kingpin.New("proxy", "happy with proxy")
|
||||
app.Author("snail").Version(APP_VERSION)
|
||||
isDebug := app.Flag("debug", "debug log output").Default("false").Bool()
|
||||
isDebug = app.Flag("debug", "debug log output").Default("false").Bool()
|
||||
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()
|
||||
@ -114,13 +117,15 @@ func initConfig() (err error) {
|
||||
httpArgs.ParentKey = http.Flag("parent-key", "the password for auto encrypt/decrypt parent connection data").Short('Z').Default("").String()
|
||||
httpArgs.LocalCompress = http.Flag("local-compress", "auto compress/decompress data on local connection").Short('m').Default("false").Bool()
|
||||
httpArgs.ParentCompress = http.Flag("parent-compress", "auto compress/decompress data on parent connection").Short('M').Default("false").Bool()
|
||||
httpArgs.LoadBalanceMethod = http.Flag("lb-method", "load balance method when use multiple parent,can be <roundrobin|leastconn|leasttime|hash|weight>").Default("hash").Enum("roundrobin", "weight", "leastconn", "leasttime", "hash")
|
||||
httpArgs.Intelligent = http.Flag("intelligent", "settting intelligent HTTP, SOCKS5 proxy mode, can be <intelligent|direct|parent>").Default("intelligent").Enum("intelligent", "direct", "parent")
|
||||
httpArgs.LoadBalanceMethod = http.Flag("lb-method", "load balance method when use multiple parent,can be <roundrobin|leastconn|leasttime|hash|weight>").Default("roundrobin").Enum("roundrobin", "weight", "leastconn", "leasttime", "hash")
|
||||
httpArgs.LoadBalanceTimeout = http.Flag("lb-timeout", "tcp milliseconds timeout of connecting to parent").Default("500").Int()
|
||||
httpArgs.LoadBalanceRetryTime = http.Flag("lb-retrytime", "sleep time milliseconds after checking").Default("1000").Int()
|
||||
httpArgs.LoadBalanceHashTarget = http.Flag("lb-hashtarget", "use target address to choose parent for LB").Default("false").Bool()
|
||||
httpArgs.LoadBalanceOnlyHA = http.Flag("lb-onlyha", "use only `high availability mode` to choose parent for LB").Default("false").Bool()
|
||||
httpArgs.RateLimit = http.Flag("rate-limit", "rate limit (bytes/second) of each connection, such as: 100K 1.5M . 0 means no limitation").Short('l').Default("0").String()
|
||||
httpArgs.BindListen = http.Flag("bind-listen", "using listener binding IP when connect to target").Short('B').Default("false").Bool()
|
||||
httpArgs.Jumper = http.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()
|
||||
httpArgs.Debug = isDebug
|
||||
//########tcp#########
|
||||
tcp := app.Command("tcp", "proxy on tcp mode")
|
||||
@ -147,7 +152,7 @@ func initConfig() (err error) {
|
||||
//########mux-server#########
|
||||
muxServer := app.Command("server", "proxy on mux server mode")
|
||||
muxServerArgs.Parent = muxServer.Flag("parent", "parent address, such as: \"23.32.32.19:28008\"").Default("").Short('P').String()
|
||||
muxServerArgs.ParentType = muxServer.Flag("parent-type", "parent protocol type <tls|tcp|kcp>").Default("tls").Short('T').Enum("tls", "tcp", "kcp")
|
||||
muxServerArgs.ParentType = muxServer.Flag("parent-type", "parent protocol type <tls|tcp|tcps|kcp|tou>").Default("tls").Short('T').Enum("tls", "tcp", "tcps", "kcp", "tou")
|
||||
muxServerArgs.CertFile = muxServer.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String()
|
||||
muxServerArgs.KeyFile = muxServer.Flag("key", "key file for tls").Short('K').Default("proxy.key").String()
|
||||
muxServerArgs.Timeout = muxServer.Flag("timeout", "tcp timeout with milliseconds").Short('i').Default("2000").Int()
|
||||
@ -157,11 +162,15 @@ func initConfig() (err error) {
|
||||
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()
|
||||
muxServerArgs.TCPSMethod = muxServer.Flag("tcps-method", "method of parent tcps's encrpyt/decrypt, these below are supported :\n"+strings.Join(encryptconn.GetCipherMethods(), ",")).Default("aes-192-cfb").String()
|
||||
muxServerArgs.TCPSPassword = muxServer.Flag("tcps-password", "password of parent tcps's encrpyt/decrypt").Default("snail007's_goproxy").String()
|
||||
muxServerArgs.TOUMethod = muxServer.Flag("tou-method", "method of parent tou's encrpyt/decrypt, these below are supported :\n"+strings.Join(encryptconn.GetCipherMethods(), ",")).Default("aes-192-cfb").String()
|
||||
muxServerArgs.TOUPassword = muxServer.Flag("tou-password", "password of parent tou's encrpyt/decrypt").Default("snail007's_goproxy").String()
|
||||
|
||||
//########mux-client#########
|
||||
muxClient := app.Command("client", "proxy on mux client mode")
|
||||
muxClientArgs.Parent = muxClient.Flag("parent", "parent address, such as: \"23.32.32.19:28008\"").Default("").Short('P').String()
|
||||
muxClientArgs.ParentType = muxClient.Flag("parent-type", "parent protocol type <tls|tcp|kcp>").Default("tls").Short('T').Enum("tls", "tcp", "kcp")
|
||||
muxClientArgs.ParentType = muxClient.Flag("parent-type", "parent protocol type <tls|tcp|tcps|kcp|tou>").Default("tls").Short('T').Enum("tls", "tcp", "tcps", "kcp", "tou")
|
||||
muxClientArgs.CertFile = muxClient.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String()
|
||||
muxClientArgs.KeyFile = muxClient.Flag("key", "key file for tls").Short('K').Default("proxy.key").String()
|
||||
muxClientArgs.Timeout = muxClient.Flag("timeout", "tcp timeout with milliseconds").Short('i').Default("2000").Int()
|
||||
@ -169,6 +178,10 @@ func initConfig() (err error) {
|
||||
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()
|
||||
muxClientArgs.TCPSMethod = muxClient.Flag("tcps-method", "method of parent tcps's encrpyt/decrypt, these below are supported :\n"+strings.Join(encryptconn.GetCipherMethods(), ",")).Default("aes-192-cfb").String()
|
||||
muxClientArgs.TCPSPassword = muxClient.Flag("tcps-password", "password of parent tcps's encrpyt/decrypt").Default("snail007's_goproxy").String()
|
||||
muxClientArgs.TOUMethod = muxClient.Flag("tou-method", "method of parent tou's encrpyt/decrypt, these below are supported :\n"+strings.Join(encryptconn.GetCipherMethods(), ",")).Default("aes-192-cfb").String()
|
||||
muxClientArgs.TOUPassword = muxClient.Flag("tou-password", "password of parent tou's encrpyt/decrypt").Default("snail007's_goproxy").String()
|
||||
|
||||
//########mux-bridge#########
|
||||
muxBridge := app.Command("bridge", "proxy on mux bridge mode")
|
||||
@ -176,7 +189,11 @@ func initConfig() (err error) {
|
||||
muxBridgeArgs.KeyFile = muxBridge.Flag("key", "key file for tls").Short('K').Default("proxy.key").String()
|
||||
muxBridgeArgs.Timeout = muxBridge.Flag("timeout", "tcp timeout with milliseconds").Short('i').Default("2000").Int()
|
||||
muxBridgeArgs.Local = muxBridge.Flag("local", "local ip:port to listen").Short('p').Default(":33080").String()
|
||||
muxBridgeArgs.LocalType = muxBridge.Flag("local-type", "local protocol type <tls|tcp|kcp>").Default("tls").Short('t').Enum("tls", "tcp", "kcp")
|
||||
muxBridgeArgs.LocalType = muxBridge.Flag("local-type", "local protocol type <tls|tcp|tcps|kcp|tou>").Default("tls").Short('t').Enum("tls", "tcp", "tcps", "kcp", "tou")
|
||||
muxBridgeArgs.TCPSMethod = muxBridge.Flag("tcps-method", "method of local tcps's encrpyt/decrypt, these below are supported :\n"+strings.Join(encryptconn.GetCipherMethods(), ",")).Default("aes-192-cfb").String()
|
||||
muxBridgeArgs.TCPSPassword = muxBridge.Flag("tcps-password", "password of local tcps's encrpyt/decrypt").Default("snail007's_goproxy").String()
|
||||
muxBridgeArgs.TOUMethod = muxBridge.Flag("tou-method", "method of local tou's encrpyt/decrypt, these below are supported :\n"+strings.Join(encryptconn.GetCipherMethods(), ",")).Default("aes-192-cfb").String()
|
||||
muxBridgeArgs.TOUPassword = muxBridge.Flag("tou-password", "password of local tou's encrpyt/decrypt").Default("snail007's_goproxy").String()
|
||||
|
||||
//########tunnel-server#########
|
||||
tunnelServer := app.Command("tserver", "proxy on tunnel server mode")
|
||||
@ -205,7 +222,7 @@ func initConfig() (err error) {
|
||||
tunnelBridgeArgs.Timeout = tunnelBridge.Flag("timeout", "tcp timeout with milliseconds").Short('t').Default("2000").Int()
|
||||
tunnelBridgeArgs.Local = tunnelBridge.Flag("local", "local ip:port to listen").Short('p').Default(":33080").String()
|
||||
|
||||
//########ssh#########
|
||||
//########socks#########
|
||||
socks := app.Command("socks", "proxy on ssh mode")
|
||||
socksArgs.Parent = socks.Flag("parent", "parent ssh address, such as: \"23.32.32.19:22\"").Default("").Short('P').Strings()
|
||||
socksArgs.ParentType = socks.Flag("parent-type", "parent protocol type <tls|tcp|kcp|ssh>").Default("tcp").Short('T').Enum("tls", "tcp", "kcp", "ssh")
|
||||
@ -237,7 +254,8 @@ func initConfig() (err error) {
|
||||
socksArgs.ParentKey = socks.Flag("parent-key", "the password for auto encrypt/decrypt parent connection data").Short('Z').Default("").String()
|
||||
socksArgs.LocalCompress = socks.Flag("local-compress", "auto compress/decompress data on local connection").Short('m').Default("false").Bool()
|
||||
socksArgs.ParentCompress = socks.Flag("parent-compress", "auto compress/decompress data on parent connection").Short('M').Default("false").Bool()
|
||||
socksArgs.LoadBalanceMethod = socks.Flag("lb-method", "load balance method when use multiple parent,can be <roundrobin|leastconn|leasttime|hash|weight>").Default("hash").Enum("roundrobin", "weight", "leastconn", "leasttime", "hash")
|
||||
socksArgs.Intelligent = socks.Flag("intelligent", "settting intelligent HTTP, SOCKS5 proxy mode, can be <intelligent|direct|parent>").Default("intelligent").Enum("intelligent", "direct", "parent")
|
||||
socksArgs.LoadBalanceMethod = socks.Flag("lb-method", "load balance method when use multiple parent,can be <roundrobin|leastconn|leasttime|hash|weight>").Default("roundrobin").Enum("roundrobin", "weight", "leastconn", "leasttime", "hash")
|
||||
socksArgs.LoadBalanceTimeout = socks.Flag("lb-timeout", "tcp milliseconds timeout of connecting to parent").Default("500").Int()
|
||||
socksArgs.LoadBalanceRetryTime = socks.Flag("lb-retrytime", "sleep time milliseconds after checking").Default("1000").Int()
|
||||
socksArgs.LoadBalanceHashTarget = socks.Flag("lb-hashtarget", "use target address to choose parent for LB").Default("false").Bool()
|
||||
@ -246,7 +264,7 @@ func initConfig() (err error) {
|
||||
socksArgs.BindListen = socks.Flag("bind-listen", "using listener binding IP when connect to target").Short('B').Default("false").Bool()
|
||||
socksArgs.Debug = isDebug
|
||||
|
||||
//########socks+http(s)#########
|
||||
//########sps#########
|
||||
sps := app.Command("sps", "proxy on socks+http(s) mode")
|
||||
spsArgs.Parent = sps.Flag("parent", "parent address, such as: \"23.32.32.19:28008\"").Default("").Short('P').Strings()
|
||||
spsArgs.CertFile = sps.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String()
|
||||
@ -278,12 +296,14 @@ func initConfig() (err error) {
|
||||
spsArgs.DisableHTTP = sps.Flag("disable-http", "disable http(s) proxy").Default("false").Bool()
|
||||
spsArgs.DisableSocks5 = sps.Flag("disable-socks", "disable socks proxy").Default("false").Bool()
|
||||
spsArgs.DisableSS = sps.Flag("disable-ss", "disable ss proxy").Default("false").Bool()
|
||||
spsArgs.LoadBalanceMethod = sps.Flag("lb-method", "load balance method when use multiple parent,can be <roundrobin|leastconn|leasttime|hash|weight>").Default("hash").Enum("roundrobin", "weight", "leastconn", "leasttime", "hash")
|
||||
spsArgs.LoadBalanceMethod = sps.Flag("lb-method", "load balance method when use multiple parent,can be <roundrobin|leastconn|leasttime|hash|weight>").Default("roundrobin").Enum("roundrobin", "weight", "leastconn", "leasttime", "hash")
|
||||
spsArgs.LoadBalanceTimeout = sps.Flag("lb-timeout", "tcp milliseconds timeout of connecting to parent").Default("500").Int()
|
||||
spsArgs.LoadBalanceRetryTime = sps.Flag("lb-retrytime", "sleep time milliseconds after checking").Default("1000").Int()
|
||||
spsArgs.LoadBalanceHashTarget = sps.Flag("lb-hashtarget", "use target address to choose parent for LB").Default("false").Bool()
|
||||
spsArgs.LoadBalanceOnlyHA = sps.Flag("lb-onlyha", "use only `high availability mode` to choose parent for LB").Default("false").Bool()
|
||||
spsArgs.RateLimit = sps.Flag("rate-limit", "rate limit (bytes/second) of each connection, such as: 100K 1.5M . 0 means no limitation").Short('l').Default("0").String()
|
||||
spsArgs.Jumper = sps.Flag("jumper", "https or socks5 proxies used when connecting to parent, only worked of -T is tls or tcp, format is https://username:password@host:port https://host:port or socks5://username:password@host:port socks5://host:port").Default("").String()
|
||||
spsArgs.ParentTLSSingle = sps.Flag("parent-tls-single", "conntect to parent insecure skip verify").Default("false").Bool()
|
||||
spsArgs.Debug = isDebug
|
||||
|
||||
//########dns#########
|
||||
@ -418,7 +438,7 @@ func initConfig() (err error) {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
for {
|
||||
@ -442,7 +462,7 @@ func initConfig() (err error) {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
for scanner.Scan() {
|
||||
@ -452,7 +472,7 @@ func initConfig() (err error) {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
for scannerStdErr.Scan() {
|
||||
|
||||
@ -11,10 +11,10 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/snail007/goproxy/core/dst"
|
||||
"github.com/snail007/goproxy/core/lib/kcpcfg"
|
||||
compressconn "github.com/snail007/goproxy/core/lib/transport"
|
||||
encryptconn "github.com/snail007/goproxy/core/lib/transport/encrypt"
|
||||
"github.com/snail007/goproxy/core/dst"
|
||||
kcp "github.com/xtaci/kcp-go"
|
||||
)
|
||||
|
||||
@ -35,6 +35,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
|
||||
|
||||
@ -11,10 +11,10 @@ import (
|
||||
"runtime/debug"
|
||||
"strconv"
|
||||
|
||||
tou "github.com/snail007/goproxy/core/dst"
|
||||
compressconn "github.com/snail007/goproxy/core/lib/transport"
|
||||
transportc "github.com/snail007/goproxy/core/lib/transport"
|
||||
encryptconn "github.com/snail007/goproxy/core/lib/transport/encrypt"
|
||||
tou "github.com/snail007/goproxy/core/dst"
|
||||
|
||||
"github.com/snail007/goproxy/core/lib/kcpcfg"
|
||||
|
||||
@ -120,7 +120,7 @@ func (s *ServerChannel) listenTLS(ip string, port int, certBytes, keyBytes, caCe
|
||||
config.ClientCAs = clientCertPool
|
||||
config.ClientAuth = tls.RequireAndVerifyClientCert
|
||||
}
|
||||
_ln, err := tls.Listen("tcp", fmt.Sprintf("%s:%d", ip, port), config)
|
||||
_ln, err := tls.Listen("tcp", net.JoinHostPort(ip, fmt.Sprintf("%d", port)), config)
|
||||
if err == nil {
|
||||
ln = &_ln
|
||||
}
|
||||
@ -141,7 +141,7 @@ func (s *ServerChannel) ListenTCPS(method, password string, compress bool, fn fu
|
||||
}
|
||||
func (s *ServerChannel) ListenTCP(fn func(conn net.Conn)) (err error) {
|
||||
var l net.Listener
|
||||
l, err = net.Listen("tcp", fmt.Sprintf("%s:%d", s.ip, s.port))
|
||||
l, err = net.Listen("tcp", net.JoinHostPort(s.ip, fmt.Sprintf("%d", s.port)))
|
||||
if err == nil {
|
||||
s.Listener = &l
|
||||
go func() {
|
||||
@ -172,7 +172,7 @@ func (s *ServerChannel) ListenTCP(fn func(conn net.Conn)) (err error) {
|
||||
}
|
||||
return
|
||||
}
|
||||
func (s *ServerChannel) ListenUDP(fn func(packet []byte, localAddr, srcAddr *net.UDPAddr)) (err error) {
|
||||
func (s *ServerChannel) ListenUDP(fn func(listener *net.UDPConn, packet []byte, localAddr, srcAddr *net.UDPAddr)) (err error) {
|
||||
addr := &net.UDPAddr{IP: net.ParseIP(s.ip), Port: s.port}
|
||||
l, err := net.ListenUDP("udp", addr)
|
||||
if err == nil {
|
||||
@ -194,7 +194,7 @@ func (s *ServerChannel) ListenUDP(fn func(packet []byte, localAddr, srcAddr *net
|
||||
s.log.Printf("udp data handler crashed , err : %s , \ntrace:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
fn(packet, addr, srcAddr)
|
||||
fn(s.UDPListener, packet, addr, srcAddr)
|
||||
}()
|
||||
} else {
|
||||
s.errAcceptHandler(err)
|
||||
@ -207,7 +207,7 @@ func (s *ServerChannel) ListenUDP(fn func(packet []byte, localAddr, srcAddr *net
|
||||
return
|
||||
}
|
||||
func (s *ServerChannel) ListenKCP(config kcpcfg.KCPConfigArgs, fn func(conn net.Conn), log *logger.Logger) (err error) {
|
||||
lis, err := kcp.ListenWithOptions(fmt.Sprintf("%s:%d", s.ip, s.port), config.Block, *config.DataShard, *config.ParityShard)
|
||||
lis, err := kcp.ListenWithOptions(net.JoinHostPort(s.ip, fmt.Sprintf("%d", s.port)), config.Block, *config.DataShard, *config.ParityShard)
|
||||
if err == nil {
|
||||
if err = lis.SetDSCP(*config.DSCP); err != nil {
|
||||
log.Println("SetDSCP:", err)
|
||||
@ -230,7 +230,6 @@ func (s *ServerChannel) ListenKCP(config kcpcfg.KCPConfigArgs, fn func(conn net.
|
||||
}
|
||||
}()
|
||||
for {
|
||||
//var conn net.Conn
|
||||
conn, err := lis.AcceptKCP()
|
||||
if err == nil {
|
||||
go func() {
|
||||
|
||||
@ -137,7 +137,7 @@ func (c *Conn) start() {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:\n%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
c.reader()
|
||||
@ -433,6 +433,12 @@ func (c *Conn) String() string {
|
||||
// Read can be made to time out and return a Error with Timeout() == true
|
||||
// after a fixed time limit; see SetDeadline and SetReadDeadline.
|
||||
func (c *Conn) Read(b []byte) (n int, err error) {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
n = 0
|
||||
err = io.EOF
|
||||
}
|
||||
}()
|
||||
c.inbufMut.Lock()
|
||||
defer c.inbufMut.Unlock()
|
||||
for c.inbuf.Len() == 0 {
|
||||
@ -497,6 +503,9 @@ func (c *Conn) Write(b []byte) (n int, err error) {
|
||||
// Close closes the connection.
|
||||
// Any blocked Read or Write operations will be unblocked and return errors.
|
||||
func (c *Conn) Close() error {
|
||||
defer func() {
|
||||
_ = recover()
|
||||
}()
|
||||
c.closeOnce.Do(func() {
|
||||
if debugConnection {
|
||||
log.Println(c, "explicit close start")
|
||||
|
||||
@ -82,7 +82,7 @@ func NewMux(conn net.PacketConn, packetSize int) *Mux {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
m.readerLoop()
|
||||
|
||||
@ -56,7 +56,7 @@ func newSendBuffer(m *Mux) *sendBuffer {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
b.writerLoop()
|
||||
|
||||
@ -155,7 +155,7 @@ func (m ConcurrentMap) Iter() <-chan Tuple {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:\n%s",e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
fanIn(chans, ch)
|
||||
@ -174,7 +174,7 @@ func (m ConcurrentMap) IterBuffered() <-chan Tuple {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:\n%s",e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
fanIn(chans, ch)
|
||||
@ -195,7 +195,7 @@ func snapshot(m ConcurrentMap) (chans []chan Tuple) {
|
||||
go func(index int, shard *ConcurrentMapShared) {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:\n%s",e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
// Foreach key, value pair.
|
||||
@ -221,7 +221,7 @@ func fanIn(chans []chan Tuple, out chan Tuple) {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:\n%s",e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
func(ch chan Tuple) {
|
||||
@ -274,7 +274,7 @@ func (m ConcurrentMap) Keys() []string {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:\n%s",e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
// Foreach shard.
|
||||
@ -284,7 +284,7 @@ func (m ConcurrentMap) Keys() []string {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:\n%s",e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
func(shard *ConcurrentMapShared) {
|
||||
|
||||
@ -39,8 +39,11 @@ func (c *CompStream) Write(p []byte) (n int, err error) {
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (c *CompStream) Close() error {
|
||||
return c.conn.Close()
|
||||
func (c *CompStream) Close() (err error) {
|
||||
err = c.conn.Close()
|
||||
c.r = nil
|
||||
c.w = nil
|
||||
return
|
||||
}
|
||||
func (c *CompStream) LocalAddr() net.Addr {
|
||||
return c.conn.LocalAddr()
|
||||
|
||||
@ -2,6 +2,7 @@ package encrypt
|
||||
|
||||
import (
|
||||
"crypto/cipher"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
|
||||
@ -33,8 +34,23 @@ func NewConn(c net.Conn, method, password string) (conn net.Conn, err error) {
|
||||
return
|
||||
}
|
||||
func (s *Conn) Read(b []byte) (n int, err error) {
|
||||
if s.r == nil {
|
||||
return 0, fmt.Errorf("use of closed network connection")
|
||||
}
|
||||
return s.r.Read(b)
|
||||
}
|
||||
func (s *Conn) Write(b []byte) (n int, err error) {
|
||||
if s.w == nil {
|
||||
return 0, fmt.Errorf("use of closed network connection")
|
||||
}
|
||||
return s.w.Write(b)
|
||||
}
|
||||
func (s *Conn) Close() (err error) {
|
||||
if s.Cipher != nil {
|
||||
err = s.Conn.Close()
|
||||
s.Cipher = nil
|
||||
s.r = nil
|
||||
s.w = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -62,7 +62,7 @@ func (s *IOBinder) AliveWithServeConn(srcAddr string, inTCPConn *net.Conn) *IOBi
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:\n%s",e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
buf := make([]byte, 1)
|
||||
@ -75,7 +75,7 @@ func (s *IOBinder) AliveWithServeConn(srcAddr string, inTCPConn *net.Conn) *IOBi
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:\n%s",e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
for {
|
||||
@ -96,7 +96,7 @@ func (s *IOBinder) AliveWithClientConn(srcAddr string, outTCPConn *net.Conn) *IO
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:\n%s",e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
buf := make([]byte, 1)
|
||||
@ -156,7 +156,7 @@ func (s *IOBinder) Run() (err error) {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:\n%s",e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
defer func() {
|
||||
|
||||
@ -10,11 +10,11 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
socks5c "github.com/snail007/goproxy/core/proxy/common/socks5"
|
||||
socks5c "github.com/snail007/goproxy/core/lib/socks5"
|
||||
)
|
||||
|
||||
type BasicAuther interface {
|
||||
CheckUserPass(username, password, fromIP, ToTarget string) bool
|
||||
CheckUserPass(username, password, userIP, localIP, toTarget string) bool
|
||||
}
|
||||
type Request struct {
|
||||
ver uint8
|
||||
@ -239,15 +239,16 @@ func (s *ServerConn) Target() string {
|
||||
}
|
||||
func (s *ServerConn) Handshake() (err error) {
|
||||
remoteAddr := (*s.conn).RemoteAddr()
|
||||
localAddr := (*s.conn).LocalAddr()
|
||||
//协商开始
|
||||
//method select request
|
||||
var methodReq MethodsRequest
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(time.Second * s.timeout))
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(s.timeout))
|
||||
|
||||
methodReq, e := NewMethodsRequest((*s.conn), s.header)
|
||||
(*s.conn).SetReadDeadline(time.Time{})
|
||||
if e != nil {
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(time.Second * s.timeout))
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(s.timeout))
|
||||
methodReq.Reply(socks5c.Method_NONE_ACCEPTABLE)
|
||||
(*s.conn).SetReadDeadline(time.Time{})
|
||||
err = fmt.Errorf("new methods request fail,ERR: %s", e)
|
||||
@ -264,7 +265,7 @@ func (s *ServerConn) Handshake() (err error) {
|
||||
// }
|
||||
s.method = socks5c.Method_NO_AUTH
|
||||
//method select reply
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(time.Second * s.timeout))
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(s.timeout))
|
||||
err = methodReq.Reply(socks5c.Method_NO_AUTH)
|
||||
(*s.conn).SetReadDeadline(time.Time{})
|
||||
if err != nil {
|
||||
@ -275,7 +276,7 @@ func (s *ServerConn) Handshake() (err error) {
|
||||
} else {
|
||||
//auth
|
||||
if !methodReq.Select(socks5c.Method_USER_PASS) {
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(time.Second * s.timeout))
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(s.timeout))
|
||||
methodReq.Reply(socks5c.Method_NONE_ACCEPTABLE)
|
||||
(*s.conn).SetReadDeadline(time.Time{})
|
||||
err = fmt.Errorf("none method found : Method_USER_PASS")
|
||||
@ -283,7 +284,7 @@ func (s *ServerConn) Handshake() (err error) {
|
||||
}
|
||||
s.method = socks5c.Method_USER_PASS
|
||||
//method reply need auth
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(time.Second * s.timeout))
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(s.timeout))
|
||||
err = methodReq.Reply(socks5c.Method_USER_PASS)
|
||||
(*s.conn).SetReadDeadline(time.Time{})
|
||||
if err != nil {
|
||||
@ -293,7 +294,7 @@ func (s *ServerConn) Handshake() (err error) {
|
||||
//read auth
|
||||
buf := make([]byte, 500)
|
||||
var n int
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(time.Second * s.timeout))
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(s.timeout))
|
||||
n, err = (*s.conn).Read(buf)
|
||||
(*s.conn).SetReadDeadline(time.Time{})
|
||||
if err != nil {
|
||||
@ -305,9 +306,10 @@ func (s *ServerConn) Handshake() (err error) {
|
||||
s.password = string(r[2+r[1]+1:])
|
||||
//err = fmt.Errorf("user:%s,pass:%s", user, pass)
|
||||
//auth
|
||||
_addr := strings.Split(remoteAddr.String(), ":")
|
||||
if s.auth == nil || (*s.auth).CheckUserPass(s.user, s.password, _addr[0], "") {
|
||||
(*s.conn).SetDeadline(time.Now().Add(time.Millisecond * time.Duration(s.timeout)))
|
||||
_userAddr := strings.Split(remoteAddr.String(), ":")
|
||||
_localAddr := strings.Split(localAddr.String(), ":")
|
||||
if s.auth == nil || (*s.auth).CheckUserPass(s.user, s.password, _userAddr[0], _localAddr[0], "") {
|
||||
(*s.conn).SetDeadline(time.Now().Add(s.timeout))
|
||||
_, err = (*s.conn).Write([]byte{0x01, 0x00})
|
||||
(*s.conn).SetDeadline(time.Time{})
|
||||
if err != nil {
|
||||
@ -315,7 +317,7 @@ func (s *ServerConn) Handshake() (err error) {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
(*s.conn).SetDeadline(time.Now().Add(time.Millisecond * time.Duration(s.timeout)))
|
||||
(*s.conn).SetDeadline(time.Now().Add(s.timeout))
|
||||
_, err = (*s.conn).Write([]byte{0x01, 0x01})
|
||||
(*s.conn).SetDeadline(time.Time{})
|
||||
if err != nil {
|
||||
@ -327,7 +329,7 @@ func (s *ServerConn) Handshake() (err error) {
|
||||
}
|
||||
}
|
||||
//request detail
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(time.Second * s.timeout))
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(s.timeout))
|
||||
request, e := NewRequest(*s.conn)
|
||||
(*s.conn).SetReadDeadline(time.Time{})
|
||||
if e != nil {
|
||||
|
||||
@ -1,35 +1,35 @@
|
||||
# 透传用户IP手册
|
||||
# Pass-through user IP manual
|
||||
|
||||
说明:
|
||||
## Description:
|
||||
|
||||
通过Linux的TPROXY功能,可以实现源站服务程序可以看见客户端真实IP,实现该功能需要linux操作系统和程序都要满足一定的条件.
|
||||
By Linux TPROXY function,you can achieve the source Station service program can see the client's real IP, to achieve this feature requires linux operating systems and programs must meet certain conditions.
|
||||
|
||||
环境要求:
|
||||
## Environmental requirements:
|
||||
|
||||
源站必须是运行在Linux上面的服务程序,同时Linux需要满足下面条件:
|
||||
The source station must be a service program running on Linux, and Linux needs to meet the following conditions:
|
||||
|
||||
1.Linux内核版本 >= 2.6.28
|
||||
1. Linux kernel version >= 2.6.28
|
||||
|
||||
2.判断系统是否支持TPROXY,执行:
|
||||
2. Determine whether the system supports TPROXY, execute:
|
||||
|
||||
grep TPROXY /boot/config-`uname -r`
|
||||
|
||||
如果输出有下面的结果说明支持.
|
||||
If the output has the following result description is supported.
|
||||
|
||||
CONFIG_NETFILTER_XT_TARGET_TPROXY=m
|
||||
|
||||
部署步骤:
|
||||
## Deployment steps:
|
||||
|
||||
1.在源站的linux系统里面每次开机启动都要用root权限执行tproxy环境设置脚本:tproxy_setup.sh
|
||||
1. The tproxy environment setup script should be executed with root privileges every time the boot from the source Linux system: tproxy_setup.sh
|
||||
|
||||
2.在源站的linux系统里面使用root权限执行代理proxy
|
||||
2. Execute proxy proxy with root access on the source Linux system
|
||||
|
||||
参数 -tproxy 是开启代理的tproxy功能.
|
||||
## Parameter-tproxy is the tproxy function that turns on the proxy.
|
||||
|
||||
./proxy -tproxy
|
||||
|
||||
2.源站的程序监听的地址IP需要使用:127.0.1.1
|
||||
2. The IP address of the source station to listen to the program requires the use of: `127.0.1.1`
|
||||
|
||||
比如源站以前监听的地址是: 0.0.0.0:8800 , 现在需要修改为:127.0.1.1:8800
|
||||
For example, the address of the source station before listening is: `0.0.0.0:8800`, now need to be modified to: `127.0.1.1:8800`
|
||||
|
||||
3.转发规则里面源站地址必须是对应的,比如上面的:127.0.1.1:8800
|
||||
3. Forwarding rules inside the source address must be the corresponding, such as the above: `127.0.1.1:8800`
|
||||
|
||||
35
core/tproxy/README_ZH.md
Normal file
35
core/tproxy/README_ZH.md
Normal file
@ -0,0 +1,35 @@
|
||||
# 透传用户IP手册
|
||||
|
||||
## 说明:
|
||||
|
||||
通过Linux的TPROXY功能,可以实现源站服务程序可以看见客户端真实IP,实现该功能需要linux操作系统和程序都要满足一定的条件.
|
||||
|
||||
## 环境要求:
|
||||
|
||||
源站必须是运行在Linux上面的服务程序,同时Linux需要满足下面条件:
|
||||
|
||||
1. Linux内核版本 >= 2.6.28
|
||||
|
||||
2. 判断系统是否支持TPROXY,执行:
|
||||
|
||||
grep TPROXY /boot/config-`uname -r`
|
||||
|
||||
如果输出有下面的结果说明支持.
|
||||
|
||||
CONFIG_NETFILTER_XT_TARGET_TPROXY=m
|
||||
|
||||
## 部署步骤:
|
||||
|
||||
1. 在源站的linux系统里面每次开机启动都要用root权限执行tproxy环境设置脚本:tproxy_setup.sh
|
||||
|
||||
2. 在源站的linux系统里面使用root权限执行代理proxy
|
||||
|
||||
## 参数 -tproxy 是开启代理的tproxy功能.
|
||||
|
||||
./proxy -tproxy
|
||||
|
||||
2. 源站的程序监听的地址IP需要使用:127.0.1.1
|
||||
|
||||
比如源站以前监听的地址是: 0.0.0.0:8800 , 现在需要修改为:127.0.1.1:8800
|
||||
|
||||
3. 转发规则里面源站地址必须是对应的,比如上面的:127.0.1.1:8800
|
||||
@ -81,7 +81,7 @@ func dtoi(s string, i0 int) (n int, i int, ok bool) {
|
||||
return n, i, true
|
||||
}
|
||||
|
||||
// IPTcpAddrToUnixSocksAddr ---
|
||||
// IPTcpAddrToUnixSocksAddr returns Sockaddr for specified TCP addr.
|
||||
func IPTcpAddrToUnixSocksAddr(addr string) (sa unix.Sockaddr, err error) {
|
||||
if Debug {
|
||||
fmt.Println("DEBUG: IPTcpAddrToUnixSocksAddr recieved address:", addr)
|
||||
@ -97,7 +97,7 @@ func IPTcpAddrToUnixSocksAddr(addr string) (sa unix.Sockaddr, err error) {
|
||||
return ipToSocksAddr(ipType(addr), tcpAddr.IP, tcpAddr.Port, tcpAddr.Zone)
|
||||
}
|
||||
|
||||
// IPv6UdpAddrToUnixSocksAddr ---
|
||||
// IPv6UdpAddrToUnixSocksAddr returns Sockaddr for specified IPv6 addr.
|
||||
func IPv6UdpAddrToUnixSocksAddr(addr string) (sa unix.Sockaddr, err error) {
|
||||
tcpAddr, err := net.ResolveTCPAddr("udp6", addr)
|
||||
if err != nil {
|
||||
|
||||
19
docker/Dockerfile
Normal file
19
docker/Dockerfile
Normal file
@ -0,0 +1,19 @@
|
||||
FROM golang:alpine AS builder
|
||||
WORKDIR $GOPATH
|
||||
ARG GOPROXY_VERSION=master
|
||||
RUN apk update; apk upgrade; \
|
||||
apk add --no-cache ca-certificates git; \
|
||||
cd /go/src/; \
|
||||
mkdir -p github.com/snail007; \
|
||||
cd github.com/snail007; \
|
||||
git clone --depth=1 https://github.com/snail007/goproxy.git; \
|
||||
cd goproxy; \
|
||||
git checkout ${GOPROXY_VERSION}; \
|
||||
CGO_ENABLED=0 GOOS=linux go build -ldflags "-s -w" -a -installsuffix cgo -o proxy; \
|
||||
chmod 0777 proxy
|
||||
|
||||
FROM debian:stable-slim
|
||||
COPY --from=builder /go/src/github.com/snail007/goproxy/proxy /usr/local/bin/
|
||||
# RUN chmod 0777 /usr/local/bin/proxy
|
||||
EXPOSE 80 443
|
||||
CMD /usr/local/bin/proxy http -t tcp -p :80,:443
|
||||
25
docs/old-release-zh.md
Normal file
25
docs/old-release-zh.md
Normal file
@ -0,0 +1,25 @@
|
||||
# Old Versions of Proxy
|
||||
|
||||
- [v5.3手册](https://github.com/snail007/goproxy/tree/v5.3)
|
||||
- [v5.2手册](https://github.com/snail007/goproxy/tree/v5.2)
|
||||
- [v5.1手册](https://github.com/snail007/goproxy/tree/v5.1)
|
||||
- [v5.0手册](https://github.com/snail007/goproxy/tree/v5.0)
|
||||
- [v4.9手册](https://github.com/snail007/goproxy/tree/v4.9)
|
||||
- [v4.8手册](https://github.com/snail007/goproxy/tree/v4.8)
|
||||
- [v4.7手册](https://github.com/snail007/goproxy/tree/v4.7)
|
||||
- [v4.6手册](https://github.com/snail007/goproxy/tree/v4.6)
|
||||
- [v4.5手册](https://github.com/snail007/goproxy/tree/v4.5)
|
||||
- [v4.4手册](https://github.com/snail007/goproxy/tree/v4.4)
|
||||
- [v4.3手册](https://github.com/snail007/goproxy/tree/v4.3)
|
||||
- [v4.2手册](https://github.com/snail007/goproxy/tree/v4.2)
|
||||
- [v4.0-v4.1手册](https://github.com/snail007/goproxy/tree/v4.1)
|
||||
- [v3.9手册](https://github.com/snail007/goproxy/tree/v3.9)
|
||||
- [v3.8手册](https://github.com/snail007/goproxy/tree/v3.8)
|
||||
- [v3.6-v3.7手册](https://github.com/snail007/goproxy/tree/v3.6)
|
||||
- [v3.5手册](https://github.com/snail007/goproxy/tree/v3.5)
|
||||
- [v3.4手册](https://github.com/snail007/goproxy/tree/v3.4)
|
||||
- [v3.3手册](https://github.com/snail007/goproxy/tree/v3.3)
|
||||
- [v3.2手册](https://github.com/snail007/goproxy/tree/v3.2)
|
||||
- [v3.1手册](https://github.com/snail007/goproxy/tree/v3.1)
|
||||
- [v3.0手册](https://github.com/snail007/goproxy/tree/v3.0)
|
||||
- [v2.x手册](https://github.com/snail007/goproxy/tree/v2.2)
|
||||
@ -1,25 +1,25 @@
|
||||
# Old Versions of Proxy
|
||||
|
||||
- [v5.3手册](https://github.com/snail007/goproxy/tree/v5.3)
|
||||
- [v5.2手册](https://github.com/snail007/goproxy/tree/v5.2)
|
||||
- [v5.1手册](https://github.com/snail007/goproxy/tree/v5.1)
|
||||
- [v5.0手册](https://github.com/snail007/goproxy/tree/v5.0)
|
||||
- [v4.9手册](https://github.com/snail007/goproxy/tree/v4.9)
|
||||
- [v4.8手册](https://github.com/snail007/goproxy/tree/v4.8)
|
||||
- [v4.7手册](https://github.com/snail007/goproxy/tree/v4.7)
|
||||
- [v4.6手册](https://github.com/snail007/goproxy/tree/v4.6)
|
||||
- [v4.5手册](https://github.com/snail007/goproxy/tree/v4.5)
|
||||
- [v4.4手册](https://github.com/snail007/goproxy/tree/v4.4)
|
||||
- [v4.3手册](https://github.com/snail007/goproxy/tree/v4.3)
|
||||
- [v4.2手册](https://github.com/snail007/goproxy/tree/v4.2)
|
||||
- [v4.0-v4.1手册](https://github.com/snail007/goproxy/tree/v4.1)
|
||||
- [v3.9手册](https://github.com/snail007/goproxy/tree/v3.9)
|
||||
- [v3.8手册](https://github.com/snail007/goproxy/tree/v3.8)
|
||||
- [v3.6-v3.7手册](https://github.com/snail007/goproxy/tree/v3.6)
|
||||
- [v3.5手册](https://github.com/snail007/goproxy/tree/v3.5)
|
||||
- [v3.4手册](https://github.com/snail007/goproxy/tree/v3.4)
|
||||
- [v3.3手册](https://github.com/snail007/goproxy/tree/v3.3)
|
||||
- [v3.2手册](https://github.com/snail007/goproxy/tree/v3.2)
|
||||
- [v3.1手册](https://github.com/snail007/goproxy/tree/v3.1)
|
||||
- [v3.0手册](https://github.com/snail007/goproxy/tree/v3.0)
|
||||
- [v2.x手册](https://github.com/snail007/goproxy/tree/v2.2)
|
||||
- [v5.3 Manual](https://github.com/snail007/goproxy/tree/v5.3)
|
||||
- [v5.2 Manual](https://github.com/snail007/goproxy/tree/v5.2)
|
||||
- [v5.1 Manual](https://github.com/snail007/goproxy/tree/v5.1)
|
||||
- [v5.0 Manual](https://github.com/snail007/goproxy/tree/v5.0)
|
||||
- [v4.9 Manual](https://github.com/snail007/goproxy/tree/v4.9)
|
||||
- [v4.8 Manual](https://github.com/snail007/goproxy/tree/v4.8)
|
||||
- [v4.7 Manual](https://github.com/snail007/goproxy/tree/v4.7)
|
||||
- [v4.6 Manual](https://github.com/snail007/goproxy/tree/v4.6)
|
||||
- [v4.5 Manual](https://github.com/snail007/goproxy/tree/v4.5)
|
||||
- [v4.4 Manual](https://github.com/snail007/goproxy/tree/v4.4)
|
||||
- [v4.3 Manual](https://github.com/snail007/goproxy/tree/v4.3)
|
||||
- [v4.2 Manual](https://github.com/snail007/goproxy/tree/v4.2)
|
||||
- [v4.0-v4.1 Manual](https://github.com/snail007/goproxy/tree/v4.1)
|
||||
- [v3.9 Manual](https://github.com/snail007/goproxy/tree/v3.9)
|
||||
- [v3.8 Manual](https://github.com/snail007/goproxy/tree/v3.8)
|
||||
- [v3.6-v3.7 Manual](https://github.com/snail007/goproxy/tree/v3.6)
|
||||
- [v3.5 Manual](https://github.com/snail007/goproxy/tree/v3.5)
|
||||
- [v3.4 Manual](https://github.com/snail007/goproxy/tree/v3.4)
|
||||
- [v3.3 Manual](https://github.com/snail007/goproxy/tree/v3.3)
|
||||
- [v3.2 Manual](https://github.com/snail007/goproxy/tree/v3.2)
|
||||
- [v3.1 Manual](https://github.com/snail007/goproxy/tree/v3.1)
|
||||
- [v3.0 Manual](https://github.com/snail007/goproxy/tree/v3.0)
|
||||
- [v2.x Manual](https://github.com/snail007/goproxy/tree/v2.2)
|
||||
@ -1,13 +1,13 @@
|
||||
# Proxy-GUI
|
||||
基于proxy的各平台SDK,作者和众多热心人士开发了各平台的GUI版本的proxy,下面分平台介绍.
|
||||
Based on the proxy platform SDK, the author and many enthusiasts have developed the GUI version of the proxy for each platform.
|
||||
|
||||
## Windows
|
||||
|
||||
- 官方java版本,项目主页:[goproxy-jui](https://github.com/snail007/goproxy-jui)
|
||||
- Official java version, Project Homepage:[goproxy-jui](https://github.com/snail007/goproxy-jui)
|
||||
|
||||
## Linux
|
||||
|
||||
- 官方java版本,项目主页:[goproxy-jui](https://github.com/snail007/goproxy-jui)
|
||||
- Official java version, Project Homepage:[goproxy-jui](https://github.com/snail007/goproxy-jui)
|
||||
|
||||
## MacOS
|
||||
|
||||
@ -15,13 +15,13 @@
|
||||
|
||||
## Android
|
||||
|
||||
- proxy-go,一个非官方实现版本,界面比较简陋,但是够用.下载地址:[proxy-go](https://github.com/snail007/goproxy-gui-stuff/releases/tag/proxy-go-release)
|
||||
- proxy-go,An unofficial implementation version, the interface is relatively simple, but enough.Download address:[proxy-go](https://github.com/snail007/goproxy-gui-stuff/releases/tag/proxy-go-release)
|
||||
|
||||
|
||||
## IOS
|
||||
|
||||
- Coming Soon ...
|
||||
|
||||
## 跨平台
|
||||
## Cross-platform
|
||||
|
||||
- proxy-web,一个跨平台的web UI版本,项目主页:[proxy-web](https://github.com/yincongcyincong/proxy-web)
|
||||
- proxy-web,A cross-platform web UI version,project home page:[proxy-web](https://github.com/yincongcyincong/proxy-web)
|
||||
27
gui/README_ZH.md
Normal file
27
gui/README_ZH.md
Normal file
@ -0,0 +1,27 @@
|
||||
# Proxy-GUI
|
||||
基于proxy的各平台SDK,作者和众多热心人士开发了各平台的GUI版本的proxy,下面分平台介绍.
|
||||
|
||||
## Windows
|
||||
|
||||
- 官方java版本,项目主页:[goproxy-jui](https://github.com/snail007/goproxy-jui)
|
||||
|
||||
## Linux
|
||||
|
||||
- 官方java版本,项目主页:[goproxy-jui](https://github.com/snail007/goproxy-jui)
|
||||
|
||||
## MacOS
|
||||
|
||||
- Coming Soon ...
|
||||
|
||||
## Android
|
||||
|
||||
- proxy-go,一个非官方实现版本,界面比较简陋,但是够用.下载地址:[proxy-go](https://github.com/snail007/goproxy-gui-stuff/releases/tag/proxy-go-release)
|
||||
|
||||
|
||||
## IOS
|
||||
|
||||
- Coming Soon ...
|
||||
|
||||
## 跨平台
|
||||
|
||||
- proxy-web,一个跨平台的web UI版本,项目主页:[proxy-web](https://github.com/yincongcyincong/proxy-web)
|
||||
@ -5,7 +5,10 @@ if [ -e /tmp/proxy ]; then
|
||||
fi
|
||||
mkdir /tmp/proxy
|
||||
cd /tmp/proxy
|
||||
wget https://github.com/snail007/goproxy/releases/download/v6.0/proxy-linux-amd64.tar.gz
|
||||
|
||||
LAST_VERSION=$(curl --silent "https://api.github.com/repos/snail007/goproxy/releases/latest" | grep -Po '"tag_name": "\K.*?(?=")')
|
||||
|
||||
wget "https://github.com/snail007/goproxy/releases/download/${LAST_VERSION}/proxy-linux-amd64.tar.gz"
|
||||
|
||||
# #install proxy
|
||||
tar zxvf proxy-linux-amd64.tar.gz
|
||||
|
||||
7
main.go
7
main.go
@ -36,10 +36,10 @@ func Clean(s *services.Service) {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:\n%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
for _ = range signalChan {
|
||||
for range signalChan {
|
||||
log.Println("Received an interrupt, stopping services...")
|
||||
if s != nil && *s != nil {
|
||||
(*s).Clean()
|
||||
@ -48,11 +48,12 @@ func Clean(s *services.Service) {
|
||||
log.Printf("clean process %d", cmd.Process.Pid)
|
||||
cmd.Process.Kill()
|
||||
}
|
||||
if isDebug {
|
||||
if *isDebug {
|
||||
saveProfiling()
|
||||
}
|
||||
cleanupDone <- true
|
||||
}
|
||||
}()
|
||||
<-cleanupDone
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
@ -82,6 +82,3 @@ CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build $OPTS -ldflags "$X" -o proxy.e
|
||||
|
||||
rm -rf proxy proxy.exe proxy-noconsole.exe .cert
|
||||
|
||||
#todo
|
||||
#1.install_auto.sh goproxy/releases/download/vxxx
|
||||
#2.README goproxy/releases/download/vxxx
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
v4.8
|
||||
1.修复了多个服务同时开启日志,只会输出到最后一个日志文件的bug.
|
||||
2.增加了获取sdk版本的Version()方法.
|
||||
v6.8
|
||||
1.sdk增加了调试锁,避免潜在的并发问题.
|
||||
2.sdk的Stop方法增加了锁,避免潜在的并发问题.
|
||||
3.sdk的Stop方法增加了关闭文件操作.
|
||||
118
sdk/README.md
118
sdk/README.md
@ -1,53 +1,53 @@
|
||||
|
||||
# Proxy SDK 使用说明
|
||||
# Proxy SDK usage instructions
|
||||
|
||||
支持以下平台:
|
||||
- Android,`.arr`库
|
||||
- IOS,`.framework`库
|
||||
- Windows,`.dll`库
|
||||
- Linux,`.so`库
|
||||
- MacOS,`.dylib`库
|
||||
The following platforms are supported:
|
||||
- Android, `.arr` library
|
||||
- IOS, `.framework` library
|
||||
- Windows, `.dll` library
|
||||
- Linux, `.so` library
|
||||
- MacOS, `.dylib` library
|
||||
|
||||
proxy使用gombile实现了一份go代码编译为android和ios平台下面可以直接调用的sdk类库,
|
||||
另外还为linux和windows,MacOS提供sdk支持,基于这些类库,APP开发者可以轻松的开发出各种形式的代理工具。
|
||||
proxy uses gombile to compile a copy of go code into an sdk library that can be called directly from the android and ios platforms,
|
||||
It also provides sdk support for linux and windows, MacOS,based on these libraries, APP developers can easily develop various forms of proxy tools.
|
||||
|
||||
# 下面分平台介绍SDK的用法
|
||||
# The following sub-platform describes the use of the SDK
|
||||
|
||||
## Android SDK
|
||||
|
||||
[](https://github.com/snail007/goproxy-sdk-android/) []() [](https://github.com/snail007/goproxy-sdk-android/releases) [](https://github.com/snail007/goproxy-sdk-android/releases)
|
||||
|
||||
[点击下载Android-SDK](https://github.com/snail007/goproxy-sdk-android/releases)
|
||||
在Android系统提供的sdk形式是一个后缀为.aar的类库文件,开发的时候只需要把arr类库文件引入android项目即可.
|
||||
[Click to download Android-SDK](https://github.com/snail007/goproxy-sdk-android/releases)
|
||||
The sdk form provided in the Android system is a suffix.aar class library files, development time only need to ARR class library files into the android project can be.
|
||||
|
||||
### Android-SDK使用实例
|
||||
### Android-SDK usage examples
|
||||
|
||||
#### 1.导入包
|
||||
#### 1. Importing packages
|
||||
|
||||
```java
|
||||
import snail007.proxy.Porxy
|
||||
```
|
||||
|
||||
#### 2.启动一个服务
|
||||
#### 2. Start a service
|
||||
|
||||
```java
|
||||
String serviceID="http01";//这里serviceID是自定义的唯一标识字符串,保证每个启动的服务不一样即可
|
||||
String serviceID="http01";// Here serviceID is a custom unique identifier string, ensure that each start of the service is not the same
|
||||
String serviceArgs="http -p :8080";
|
||||
String err=Proxy.start(serviceID,serviceArgs);
|
||||
if (!err.isEmpty()){
|
||||
//启动失败
|
||||
// Failed to start
|
||||
System.out.println("start fail,error:"+err);
|
||||
}else{
|
||||
//启动成功
|
||||
// Successful launch
|
||||
}
|
||||
```
|
||||
|
||||
#### 3.停止一个服务
|
||||
#### 3. Stop service
|
||||
|
||||
```java
|
||||
String serviceID="http01";
|
||||
Proxy.stop(serviceID);
|
||||
//停止完毕
|
||||
// Stop over.
|
||||
|
||||
```
|
||||
|
||||
@ -55,23 +55,23 @@ Proxy.stop(serviceID);
|
||||
|
||||
[](https://github.com/snail007/goproxy-sdk-ios/) []() [](https://github.com/snail007/goproxy-sdk-ios/releases) [](https://github.com/snail007/goproxy-sdk-ios/releases)
|
||||
|
||||
[点击下载IOS-SDK](https://github.com/snail007/goproxy-sdk-ios/releases)
|
||||
在IOS系统提供的sdk形式是一个后缀为.framework的类库文件夹,开发的时候只需要把类库文件引入项目,然后调用方法即可.
|
||||
[Click to download IOS-SDK](https://github.com/snail007/goproxy-sdk-ios/releases)
|
||||
The sdk form provided in IOS is a suffix.framework Class Library folder, the development of the class library files only need to be introduced into the project, and then call the method.
|
||||
|
||||
### IOS-SDK使用实例
|
||||
### IOS-SDK usage examples
|
||||
|
||||
#### 导入包
|
||||
#### Importing packages
|
||||
|
||||
```objc
|
||||
#import <Proxy/Proxy.objc.h>
|
||||
```
|
||||
|
||||
#### 2.启动一个服务
|
||||
#### 2. Start a service
|
||||
|
||||
```objc
|
||||
-(IBAction)doStart:(id)sender
|
||||
{
|
||||
//这里serviceID是自定义的唯一标识字符串,保证每个启动的服务不一样
|
||||
// Here serviceID is a custom unique identifier string, guaranteed to be different for each started service
|
||||
NSString *serviceID = @"http01";
|
||||
NSString *serviceArgs = @"http -p :8080";
|
||||
NSString *error = ProxyStart(serviceID,serviceArgs);
|
||||
@ -80,19 +80,19 @@ Proxy.stop(serviceID);
|
||||
{
|
||||
NSLog(@"start error %@",error);
|
||||
}else{
|
||||
NSLog(@"启动成功");
|
||||
NSLog(@"Successful launch");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 3.停止一个服务
|
||||
#### 3. Stop service
|
||||
|
||||
```objc
|
||||
-(IBAction)doStop:(id)sender
|
||||
{
|
||||
NSString *serviceID = @"http01";
|
||||
ProxyStop(serviceID);
|
||||
//停止完毕
|
||||
// Stop over.
|
||||
}
|
||||
```
|
||||
|
||||
@ -100,12 +100,13 @@ Proxy.stop(serviceID);
|
||||
## Windows SDK
|
||||
[](https://github.com/snail007/goproxy-sdk-windows/) []() [](https://github.com/snail007/goproxy-sdk-windows/releases) [](https://github.com/snail007/goproxy-sdk-windows/releases)
|
||||
|
||||
[点击下载Windows-SDK](https://github.com/snail007/goproxy-sdk-windows/releases)
|
||||
在Windows系统提供的sdk形式是一个后缀为.dll的类库文件,开发的时候只需要把dll类库文件加载,然后调用方法即可.
|
||||
[Click to download Windows-SDK](https://github.com/snail007/goproxy-sdk-windows/releases)
|
||||
The sdk form provided in the Windows system is a suffix.when developing,you only need to load the dll class library file, and then call the method.
|
||||
|
||||
### Windows-SDK使用实例
|
||||
C++示例,不需要包含头文件,只需要加载proxy-sdk.dll即可,ieshims.dll需要和proxy-sdk.dll在一起。
|
||||
作者:[yjbdsky](https://github.com/yjbdsky)
|
||||
### Windows-SDK usage instance
|
||||
|
||||
C++examples, do not need to include header files, only need to load proxy-sdk.dll can, ieshims.dll needed and proxy-sdk.dll together.
|
||||
Author: [yjbdsky](https://github.com/yjbdsky)
|
||||
|
||||
```cpp
|
||||
#include <stdio.h>
|
||||
@ -152,13 +153,13 @@ char * Stop(char * p)
|
||||
|
||||
int main()
|
||||
{
|
||||
//这里p0是自定义的唯一标识字符串,保证每个启动的服务不一样
|
||||
// Here p0 is a custom unique identifier string, guaranteed to be different for each started service
|
||||
char *p0 = "http01";
|
||||
char *p1 = "http -t tcp -p :38080";
|
||||
printf("This is demo application.\n");
|
||||
//启动服务,返回空字符串说明启动成功;返回非空字符串说明启动失败,返回的字符串是错误原因
|
||||
// Start the service, returns an empty string description starts successfully;returns a non-empty string description fails to start, the returned string is the cause of the error
|
||||
printf("start result %s\n", Start(p0,p1));
|
||||
//停止服务,没有返回值
|
||||
// Stop service, no return value
|
||||
Stop(p0);
|
||||
return 0;
|
||||
}
|
||||
@ -169,16 +170,16 @@ int main()
|
||||
#endif
|
||||
```
|
||||
|
||||
C++示例2,请移步:[GoProxyForC](https://github.com/SuperPowerLF2/GoProxyForC)
|
||||
C++ Example 2, move step:[GoProxyForC](https://github.com/SuperPowerLF2/GoProxyForC)
|
||||
|
||||
## Linux SDK
|
||||
[](https://github.com/snail007/goproxy-sdk-linux/) []() [](https://github.com/snail007/goproxy-sdk-linux/releases) [](https://github.com/snail007/goproxy-sdk-linux/releases)
|
||||
|
||||
[点击下载Linux-SDK](https://github.com/snail007/goproxy-sdk-linux/releases)
|
||||
在Linux系统提供的sdk形式是一个后缀为.so的类库文件,开发的时候只需要把so类库加载,调用方法即可.
|
||||
[Click to download Linux-SDK](https://github.com/snail007/goproxy-sdk-linux/releases)
|
||||
The sdk form provided in the Linux system is a suffix.so library files, development time only need to load the so library, you can call the method.
|
||||
|
||||
### Linux-SDK使用实例
|
||||
Linux下面使用的sdk是so文件即libproxy-sdk.so,下面写一个简单的C程序示例,调用so库里面的方法.
|
||||
### Linux-SDK usage examples
|
||||
The SDK that is used below Linux is the so file i.e. libproxy-sdk. so,write a simple example of a C program that calls the method inside the so library.
|
||||
|
||||
`vi test-proxy.c`
|
||||
|
||||
@ -188,31 +189,31 @@ Linux下面使用的sdk是so文件即libproxy-sdk.so,下面写一个简单的C
|
||||
|
||||
int main() {
|
||||
printf("This is demo application.\n");
|
||||
//这里p0是自定义的唯一标识字符串,保证每个启动的服务不一样
|
||||
// Here p0 is a custom unique identifier string, guaranteed to be different for each started service
|
||||
char *p0 = "http01";
|
||||
char *p1 = "http -t tcp -p :38080";
|
||||
//启动服务,返回空字符串说明启动成功;返回非空字符串说明启动失败,返回的字符串是错误原因
|
||||
// Start the service, returns an empty string description starts successfully;returns a non-empty string description fails to start, the returned string is the cause of the error
|
||||
printf("start result %s\n",Start(p0,p1));
|
||||
//停止服务,没有返回值
|
||||
// Stop service, no return value
|
||||
Stop(p0);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
#### 编译test-proxy.c ####
|
||||
#### Compile test-proxy.c ####
|
||||
`export LD_LIBRARY_PATH=./ && gcc -o test-proxy test-proxy.c libproxy-sdk.so`
|
||||
|
||||
#### 执行 ####
|
||||
#### Execution ####
|
||||
`./test-proxy`
|
||||
|
||||
## MacOS SDK
|
||||
[](https://github.com/snail007/goproxy-sdk-mac/) []() [](https://github.com/snail007/goproxy-sdk-mac/releases) [](https://github.com/snail007/goproxy-sdk-mac/releases)
|
||||
|
||||
[点击下载MacOS-SDK](https://github.com/snail007/goproxy-sdk-mac/releases)
|
||||
在MacOS系统提供的sdk形式是一个后缀为.dylib的类库文件,开发的时候只需要把so类库加载,调用方法即可.
|
||||
[Click to download MacOS-SDK](https://github.com/snail007/goproxy-sdk-mac/releases)
|
||||
The sdk form provided in the MacOS system is a suffix.dylib library files, development time only need to load so library, you can call the method.
|
||||
|
||||
### MacOS-SDK使用实例
|
||||
MacOS下面使用的sdk是dylib文件即libproxy-sdk.dylib,下面写一个简单的Obj-C程序示例,调用dylib库里面的方法.
|
||||
### MacOS-SDK usage instance
|
||||
The sdk used below for MacOS is the dylib file i.e. libproxy-sdk.dylib, write a simple Obj-C program example, call dylib library inside the method.
|
||||
|
||||
```objc
|
||||
#import "libproxy-sdk.h"
|
||||
@ -235,8 +236,9 @@ MacOS下面使用的sdk是dylib文件即libproxy-sdk.dylib,下面写一个简单
|
||||
}
|
||||
```
|
||||
|
||||
### 关于服务
|
||||
proxy的服务有11种,分别是:
|
||||
### About the service
|
||||
|
||||
There are 11 types of proxy services:
|
||||
|
||||
```shell
|
||||
http
|
||||
@ -251,9 +253,11 @@ tbridge
|
||||
tserver
|
||||
tclient
|
||||
```
|
||||
服务启动时,如果存在正在运行的相同ID的服务,那么之前的服务会被停掉,后面启动的服务覆盖之前的服务.
|
||||
所以要保证每次启动服务的时候,第一个ID参数唯一.
|
||||
上面这些服务的具体使用方式和具体参数,可以参考[proxy手册](https://github.com/snail007/goproxy/blob/master/README_ZH.md)
|
||||
sdk里面的服务不支持手册里面的:--daemon和--forever参数.
|
||||
|
||||
When the service starts,if there is a service running with the same ID, then the previous service will be stopped and the previous service will be overwritten later.
|
||||
|
||||
So make sure that the first ID parameter is unique every time you start the service.
|
||||
|
||||
The specific usage and parameters of these services can be found in [proxy manual](https://github.com/snail007/goproxy/blob/master/README.md) the SDK service does not support the manual inside: -- daemon and -- forever parameters.
|
||||
|
||||
|
||||
|
||||
259
sdk/README_ZH.md
Normal file
259
sdk/README_ZH.md
Normal file
@ -0,0 +1,259 @@
|
||||
|
||||
# Proxy SDK 使用说明
|
||||
|
||||
支持以下平台:
|
||||
- Android,`.arr`库
|
||||
- IOS,`.framework`库
|
||||
- Windows,`.dll`库
|
||||
- Linux,`.so`库
|
||||
- MacOS,`.dylib`库
|
||||
|
||||
proxy使用gombile实现了一份go代码编译为android和ios平台下面可以直接调用的sdk类库,
|
||||
另外还为linux和windows,MacOS提供sdk支持,基于这些类库,APP开发者可以轻松的开发出各种形式的代理工具。
|
||||
|
||||
# 下面分平台介绍SDK的用法
|
||||
|
||||
## Android SDK
|
||||
|
||||
[](https://github.com/snail007/goproxy-sdk-android/) []() [](https://github.com/snail007/goproxy-sdk-android/releases) [](https://github.com/snail007/goproxy-sdk-android/releases)
|
||||
|
||||
[点击下载Android-SDK](https://github.com/snail007/goproxy-sdk-android/releases)
|
||||
在Android系统提供的sdk形式是一个后缀为.aar的类库文件,开发的时候只需要把arr类库文件引入android项目即可.
|
||||
|
||||
### Android-SDK使用实例
|
||||
|
||||
#### 1.导入包
|
||||
|
||||
```java
|
||||
import snail007.proxy.Porxy
|
||||
```
|
||||
|
||||
#### 2.启动一个服务
|
||||
|
||||
```java
|
||||
String serviceID="http01";//这里serviceID是自定义的唯一标识字符串,保证每个启动的服务不一样即可
|
||||
String serviceArgs="http -p :8080";
|
||||
String err=Proxy.start(serviceID,serviceArgs);
|
||||
if (!err.isEmpty()){
|
||||
//启动失败
|
||||
System.out.println("start fail,error:"+err);
|
||||
}else{
|
||||
//启动成功
|
||||
}
|
||||
```
|
||||
|
||||
#### 3.停止一个服务
|
||||
|
||||
```java
|
||||
String serviceID="http01";
|
||||
Proxy.stop(serviceID);
|
||||
//停止完毕
|
||||
|
||||
```
|
||||
|
||||
## IOS SDK
|
||||
|
||||
[](https://github.com/snail007/goproxy-sdk-ios/) []() [](https://github.com/snail007/goproxy-sdk-ios/releases) [](https://github.com/snail007/goproxy-sdk-ios/releases)
|
||||
|
||||
[点击下载IOS-SDK](https://github.com/snail007/goproxy-sdk-ios/releases)
|
||||
在IOS系统提供的sdk形式是一个后缀为.framework的类库文件夹,开发的时候只需要把类库文件引入项目,然后调用方法即可.
|
||||
|
||||
### IOS-SDK使用实例
|
||||
|
||||
#### 导入包
|
||||
|
||||
```objc
|
||||
#import <Proxy/Proxy.objc.h>
|
||||
```
|
||||
|
||||
#### 2.启动一个服务
|
||||
|
||||
```objc
|
||||
-(IBAction)doStart:(id)sender
|
||||
{
|
||||
//这里serviceID是自定义的唯一标识字符串,保证每个启动的服务不一样
|
||||
NSString *serviceID = @"http01";
|
||||
NSString *serviceArgs = @"http -p :8080";
|
||||
NSString *error = ProxyStart(serviceID,serviceArgs);
|
||||
|
||||
if (error != nil && error.length > 0)
|
||||
{
|
||||
NSLog(@"start error %@",error);
|
||||
}else{
|
||||
NSLog(@"启动成功");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 3.停止一个服务
|
||||
|
||||
```objc
|
||||
-(IBAction)doStop:(id)sender
|
||||
{
|
||||
NSString *serviceID = @"http01";
|
||||
ProxyStop(serviceID);
|
||||
//停止完毕
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Windows SDK
|
||||
[](https://github.com/snail007/goproxy-sdk-windows/) []() [](https://github.com/snail007/goproxy-sdk-windows/releases) [](https://github.com/snail007/goproxy-sdk-windows/releases)
|
||||
|
||||
[点击下载Windows-SDK](https://github.com/snail007/goproxy-sdk-windows/releases)
|
||||
在Windows系统提供的sdk形式是一个后缀为.dll的类库文件,开发的时候只需要把dll类库文件加载,然后调用方法即可.
|
||||
|
||||
### Windows-SDK使用实例
|
||||
C++示例,不需要包含头文件,只需要加载proxy-sdk.dll即可,ieshims.dll需要和proxy-sdk.dll在一起。
|
||||
作者:[yjbdsky](https://github.com/yjbdsky)
|
||||
|
||||
```cpp
|
||||
#include <stdio.h>
|
||||
#include<stdlib.h>
|
||||
#include <string.h>
|
||||
#include<pthread.h>
|
||||
#include<Windows.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef char *(*GOSTART)(char *s);
|
||||
typedef char *(*GOSTOP)(char *s);
|
||||
typedef int(*GOISRUN)(char *s);
|
||||
HMODULE GODLL = LoadLibrary("proxy-sdk.dll");
|
||||
|
||||
char * Start(char * p0,char * p1)
|
||||
{
|
||||
if (GODLL != NULL)
|
||||
{
|
||||
GOSTART gostart = *(GOSTART)(GetProcAddress(GODLL, "Start"));
|
||||
if (gostart != NULL){
|
||||
printf("%s:%s\n",p0, p1);
|
||||
char *ret = gostart(p0,p1);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return "Cannot Find dll";
|
||||
}
|
||||
char * Stop(char * p)
|
||||
{
|
||||
if (GODLL != NULL)
|
||||
{
|
||||
GOSTOP gostop = *(GOSTOP)(GetProcAddress(GODLL, "Stop"));
|
||||
if (gostop != NULL){
|
||||
printf("%s\n", p);
|
||||
char *ret = gostop(p);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return "Cannot Find dll";
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
//这里p0是自定义的唯一标识字符串,保证每个启动的服务不一样
|
||||
char *p0 = "http01";
|
||||
char *p1 = "http -t tcp -p :38080";
|
||||
printf("This is demo application.\n");
|
||||
//启动服务,返回空字符串说明启动成功;返回非空字符串说明启动失败,返回的字符串是错误原因
|
||||
printf("start result %s\n", Start(p0,p1));
|
||||
//停止服务,没有返回值
|
||||
Stop(p0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
C++示例2,请移步:[GoProxyForC](https://github.com/SuperPowerLF2/GoProxyForC)
|
||||
|
||||
## Linux SDK
|
||||
[](https://github.com/snail007/goproxy-sdk-linux/) []() [](https://github.com/snail007/goproxy-sdk-linux/releases) [](https://github.com/snail007/goproxy-sdk-linux/releases)
|
||||
|
||||
[点击下载Linux-SDK](https://github.com/snail007/goproxy-sdk-linux/releases)
|
||||
在Linux系统提供的sdk形式是一个后缀为.so的类库文件,开发的时候只需要把so类库加载,调用方法即可.
|
||||
|
||||
### Linux-SDK使用实例
|
||||
Linux下面使用的sdk是so文件即libproxy-sdk.so,下面写一个简单的C程序示例,调用so库里面的方法.
|
||||
|
||||
`vi test-proxy.c`
|
||||
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include "libproxy-sdk.h"
|
||||
|
||||
int main() {
|
||||
printf("This is demo application.\n");
|
||||
//这里p0是自定义的唯一标识字符串,保证每个启动的服务不一样
|
||||
char *p0 = "http01";
|
||||
char *p1 = "http -t tcp -p :38080";
|
||||
//启动服务,返回空字符串说明启动成功;返回非空字符串说明启动失败,返回的字符串是错误原因
|
||||
printf("start result %s\n",Start(p0,p1));
|
||||
//停止服务,没有返回值
|
||||
Stop(p0);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
#### 编译test-proxy.c ####
|
||||
`export LD_LIBRARY_PATH=./ && gcc -o test-proxy test-proxy.c libproxy-sdk.so`
|
||||
|
||||
#### 执行 ####
|
||||
`./test-proxy`
|
||||
|
||||
## MacOS SDK
|
||||
[](https://github.com/snail007/goproxy-sdk-mac/) []() [](https://github.com/snail007/goproxy-sdk-mac/releases) [](https://github.com/snail007/goproxy-sdk-mac/releases)
|
||||
|
||||
[点击下载MacOS-SDK](https://github.com/snail007/goproxy-sdk-mac/releases)
|
||||
在MacOS系统提供的sdk形式是一个后缀为.dylib的类库文件,开发的时候只需要把so类库加载,调用方法即可.
|
||||
|
||||
### MacOS-SDK使用实例
|
||||
MacOS下面使用的sdk是dylib文件即libproxy-sdk.dylib,下面写一个简单的Obj-C程序示例,调用dylib库里面的方法.
|
||||
|
||||
```objc
|
||||
#import "libproxy-sdk.h"
|
||||
-(IBAction)doStart:(id)sender
|
||||
{
|
||||
char *result = Start("http01", "http -t tcp -p :38080");
|
||||
|
||||
if (result)
|
||||
{
|
||||
printf("started");
|
||||
}else{
|
||||
printf("not started");
|
||||
}
|
||||
|
||||
}
|
||||
-(IBAction)doStop:(id)sender
|
||||
{
|
||||
Stop("http01");
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
### 关于服务
|
||||
proxy的服务有11种,分别是:
|
||||
|
||||
```shell
|
||||
http
|
||||
socks
|
||||
sps
|
||||
tcp
|
||||
udp
|
||||
bridge
|
||||
server
|
||||
client
|
||||
tbridge
|
||||
tserver
|
||||
tclient
|
||||
```
|
||||
服务启动时,如果存在正在运行的相同ID的服务,那么之前的服务会被停掉,后面启动的服务覆盖之前的服务.
|
||||
所以要保证每次启动服务的时候,第一个ID参数唯一.
|
||||
上面这些服务的具体使用方式和具体参数,可以参考[proxy手册](https://github.com/snail007/goproxy/blob/master/README_ZH.md)
|
||||
sdk里面的服务不支持手册里面的:--daemon和--forever参数.
|
||||
|
||||
|
||||
@ -13,8 +13,8 @@ import (
|
||||
|
||||
"github.com/miekg/dns"
|
||||
gocache "github.com/pmylund/go-cache"
|
||||
"github.com/snail007/goproxy/core/lib/kcpcfg"
|
||||
services "github.com/snail007/goproxy/services"
|
||||
"github.com/snail007/goproxy/services/kcpcfg"
|
||||
)
|
||||
|
||||
type DNSArgs struct {
|
||||
@ -57,10 +57,21 @@ func (s *DNS) CheckArgs() (err error) {
|
||||
func (s *DNS) InitService() (err error) {
|
||||
s.cache = gocache.New(time.Second*time.Duration(*s.cfg.DNSTTL), time.Second*60)
|
||||
s.cache.LoadFile(*s.cfg.CacheFile)
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-s.exitSig:
|
||||
return
|
||||
case <-time.After(time.Second * 300):
|
||||
s.cache.DeleteExpired()
|
||||
s.cache.SaveFile(*s.cfg.CacheFile)
|
||||
}
|
||||
}
|
||||
}()
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
for {
|
||||
@ -81,7 +92,7 @@ func (s *DNS) InitService() (err error) {
|
||||
nil,
|
||||
&net.Dialer{
|
||||
Timeout: 5 * time.Second,
|
||||
KeepAlive: 5 * time.Second,
|
||||
KeepAlive: 2 * time.Second,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
@ -122,7 +133,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)
|
||||
@ -142,7 +153,7 @@ func (s *DNS) Start(args interface{}, log *logger.Logger) (err error) {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
log.Printf("dns server on udp %s", *s.cfg.Local)
|
||||
|
||||
@ -8,11 +8,14 @@ import (
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"runtime/pprof"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/snail007/goproxy/core/lib/kcpcfg"
|
||||
encryptconn "github.com/snail007/goproxy/core/lib/transport/encrypt"
|
||||
"github.com/snail007/goproxy/services"
|
||||
httpx "github.com/snail007/goproxy/services/http"
|
||||
"github.com/snail007/goproxy/services/kcpcfg"
|
||||
keygenx "github.com/snail007/goproxy/services/keygen"
|
||||
mux "github.com/snail007/goproxy/services/mux"
|
||||
socksx "github.com/snail007/goproxy/services/socks"
|
||||
@ -30,6 +33,10 @@ var SDK_VERSION = "No Version Provided"
|
||||
|
||||
var (
|
||||
app *kingpin.Application
|
||||
cpuProfilingFile, memProfilingFile, blockProfilingFile,
|
||||
goroutineProfilingFile, threadcreateProfilingFile *os.File
|
||||
isProfiling bool
|
||||
profilingLock = &sync.Mutex{}
|
||||
)
|
||||
|
||||
type LogCallback interface {
|
||||
@ -84,8 +91,8 @@ func StartWithLog(serviceID, serviceArgsStr string, loggerCallback LogCallback)
|
||||
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")
|
||||
kcpArgs.MTU = app.Flag("kcp-mtu", "set maximum transmission unit for UDP packets").Default("450").Int()
|
||||
kcpArgs.Mode = app.Flag("kcp-mode", "profiles: fast3, fast2, fast, normal, manual").Default("fast3").Enum("fast3", "fast2", "fast", "normal", "manual")
|
||||
kcpArgs.MTU = app.Flag("kcp-mtu", "set maximum transmission unit for UDP packets").Default("1350").Int()
|
||||
kcpArgs.SndWnd = app.Flag("kcp-sndwnd", "set send window size(num of packets)").Default("1024").Int()
|
||||
kcpArgs.RcvWnd = app.Flag("kcp-rcvwnd", "set receive window size(num of packets)").Default("1024").Int()
|
||||
kcpArgs.DataShard = app.Flag("kcp-ds", "set reed-solomon erasure coding - datashard").Default("10").Int()
|
||||
@ -133,13 +140,15 @@ func StartWithLog(serviceID, serviceArgsStr string, loggerCallback LogCallback)
|
||||
httpArgs.ParentKey = http.Flag("parent-key", "the password for auto encrypt/decrypt parent connection data").Short('Z').Default("").String()
|
||||
httpArgs.LocalCompress = http.Flag("local-compress", "auto compress/decompress data on local connection").Short('m').Default("false").Bool()
|
||||
httpArgs.ParentCompress = http.Flag("parent-compress", "auto compress/decompress data on parent connection").Short('M').Default("false").Bool()
|
||||
httpArgs.LoadBalanceMethod = http.Flag("lb-method", "load balance method when use multiple parent,can be <roundrobin|leastconn|leasttime|hash|weight>").Default("hash").Enum("roundrobin", "weight", "leastconn", "leasttime", "hash")
|
||||
httpArgs.Intelligent = http.Flag("intelligent", "settting intelligent HTTP, SOCKS5 proxy mode, can be <intelligent|direct|parent>").Default("intelligent").Enum("intelligent", "direct", "parent")
|
||||
httpArgs.LoadBalanceMethod = http.Flag("lb-method", "load balance method when use multiple parent,can be <roundrobin|leastconn|leasttime|hash|weight>").Default("roundrobin").Enum("roundrobin", "weight", "leastconn", "leasttime", "hash")
|
||||
httpArgs.LoadBalanceTimeout = http.Flag("lb-timeout", "tcp milliseconds timeout of connecting to parent").Default("500").Int()
|
||||
httpArgs.LoadBalanceRetryTime = http.Flag("lb-retrytime", "sleep time milliseconds after checking").Default("1000").Int()
|
||||
httpArgs.LoadBalanceHashTarget = http.Flag("lb-hashtarget", "use target address to choose parent for LB").Default("false").Bool()
|
||||
httpArgs.LoadBalanceOnlyHA = http.Flag("lb-onlyha", "use only `high availability mode` to choose parent for LB").Default("false").Bool()
|
||||
httpArgs.RateLimit = http.Flag("rate-limit", "rate limit (bytes/second) of each connection, such as: 100K 1.5M . 0 means no limitation").Short('l').Default("0").String()
|
||||
httpArgs.BindListen = http.Flag("bind-listen", "using listener binding IP when connect to target").Short('B').Default("false").Bool()
|
||||
httpArgs.Jumper = http.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()
|
||||
httpArgs.Debug = debug
|
||||
//########tcp#########
|
||||
tcp := app.Command("tcp", "proxy on tcp mode")
|
||||
@ -166,7 +175,7 @@ func StartWithLog(serviceID, serviceArgsStr string, loggerCallback LogCallback)
|
||||
//########mux-server#########
|
||||
muxServer := app.Command("server", "proxy on mux server mode")
|
||||
muxServerArgs.Parent = muxServer.Flag("parent", "parent address, such as: \"23.32.32.19:28008\"").Default("").Short('P').String()
|
||||
muxServerArgs.ParentType = muxServer.Flag("parent-type", "parent protocol type <tls|tcp|kcp>").Default("tls").Short('T').Enum("tls", "tcp", "kcp")
|
||||
muxServerArgs.ParentType = muxServer.Flag("parent-type", "parent protocol type <tls|tcp|tcps|kcp|tou>").Default("tls").Short('T').Enum("tls", "tcp", "tcps", "kcp", "tou")
|
||||
muxServerArgs.CertFile = muxServer.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String()
|
||||
muxServerArgs.KeyFile = muxServer.Flag("key", "key file for tls").Short('K').Default("proxy.key").String()
|
||||
muxServerArgs.Timeout = muxServer.Flag("timeout", "tcp timeout with milliseconds").Short('i').Default("2000").Int()
|
||||
@ -176,11 +185,15 @@ func StartWithLog(serviceID, serviceArgsStr string, loggerCallback LogCallback)
|
||||
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()
|
||||
muxServerArgs.TCPSMethod = muxServer.Flag("tcps-method", "method of parent tcps's encrpyt/decrypt, these below are supported :\n"+strings.Join(encryptconn.GetCipherMethods(), ",")).Default("aes-192-cfb").String()
|
||||
muxServerArgs.TCPSPassword = muxServer.Flag("tcps-password", "password of parent tcps's encrpyt/decrypt").Default("snail007's_goproxy").String()
|
||||
muxServerArgs.TOUMethod = muxServer.Flag("tou-method", "method of parent tou's encrpyt/decrypt, these below are supported :\n"+strings.Join(encryptconn.GetCipherMethods(), ",")).Default("aes-192-cfb").String()
|
||||
muxServerArgs.TOUPassword = muxServer.Flag("tou-password", "password of parent tou's encrpyt/decrypt").Default("snail007's_goproxy").String()
|
||||
|
||||
//########mux-client#########
|
||||
muxClient := app.Command("client", "proxy on mux client mode")
|
||||
muxClientArgs.Parent = muxClient.Flag("parent", "parent address, such as: \"23.32.32.19:28008\"").Default("").Short('P').String()
|
||||
muxClientArgs.ParentType = muxClient.Flag("parent-type", "parent protocol type <tls|tcp|kcp>").Default("tls").Short('T').Enum("tls", "tcp", "kcp")
|
||||
muxClientArgs.ParentType = muxClient.Flag("parent-type", "parent protocol type <tls|tcp|tcps|kcp|tou>").Default("tls").Short('T').Enum("tls", "tcp", "tcps", "kcp", "tou")
|
||||
muxClientArgs.CertFile = muxClient.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String()
|
||||
muxClientArgs.KeyFile = muxClient.Flag("key", "key file for tls").Short('K').Default("proxy.key").String()
|
||||
muxClientArgs.Timeout = muxClient.Flag("timeout", "tcp timeout with milliseconds").Short('i').Default("2000").Int()
|
||||
@ -188,6 +201,10 @@ func StartWithLog(serviceID, serviceArgsStr string, loggerCallback LogCallback)
|
||||
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()
|
||||
muxClientArgs.TCPSMethod = muxClient.Flag("tcps-method", "method of parent tcps's encrpyt/decrypt, these below are supported :\n"+strings.Join(encryptconn.GetCipherMethods(), ",")).Default("aes-192-cfb").String()
|
||||
muxClientArgs.TCPSPassword = muxClient.Flag("tcps-password", "password of parent tcps's encrpyt/decrypt").Default("snail007's_goproxy").String()
|
||||
muxClientArgs.TOUMethod = muxClient.Flag("tou-method", "method of parent tou's encrpyt/decrypt, these below are supported :\n"+strings.Join(encryptconn.GetCipherMethods(), ",")).Default("aes-192-cfb").String()
|
||||
muxClientArgs.TOUPassword = muxClient.Flag("tou-password", "password of parent tou's encrpyt/decrypt").Default("snail007's_goproxy").String()
|
||||
|
||||
//########mux-bridge#########
|
||||
muxBridge := app.Command("bridge", "proxy on mux bridge mode")
|
||||
@ -195,7 +212,11 @@ func StartWithLog(serviceID, serviceArgsStr string, loggerCallback LogCallback)
|
||||
muxBridgeArgs.KeyFile = muxBridge.Flag("key", "key file for tls").Short('K').Default("proxy.key").String()
|
||||
muxBridgeArgs.Timeout = muxBridge.Flag("timeout", "tcp timeout with milliseconds").Short('i').Default("2000").Int()
|
||||
muxBridgeArgs.Local = muxBridge.Flag("local", "local ip:port to listen").Short('p').Default(":33080").String()
|
||||
muxBridgeArgs.LocalType = muxBridge.Flag("local-type", "local protocol type <tls|tcp|kcp>").Default("tls").Short('t').Enum("tls", "tcp", "kcp")
|
||||
muxBridgeArgs.LocalType = muxBridge.Flag("local-type", "local protocol type <tls|tcp|tcps|kcp|tou>").Default("tls").Short('t').Enum("tls", "tcp", "tcps", "kcp", "tou")
|
||||
muxBridgeArgs.TCPSMethod = muxBridge.Flag("tcps-method", "method of local tcps's encrpyt/decrypt, these below are supported :\n"+strings.Join(encryptconn.GetCipherMethods(), ",")).Default("aes-192-cfb").String()
|
||||
muxBridgeArgs.TCPSPassword = muxBridge.Flag("tcps-password", "password of local tcps's encrpyt/decrypt").Default("snail007's_goproxy").String()
|
||||
muxBridgeArgs.TOUMethod = muxBridge.Flag("tou-method", "method of local tou's encrpyt/decrypt, these below are supported :\n"+strings.Join(encryptconn.GetCipherMethods(), ",")).Default("aes-192-cfb").String()
|
||||
muxBridgeArgs.TOUPassword = muxBridge.Flag("tou-password", "password of local tou's encrpyt/decrypt").Default("snail007's_goproxy").String()
|
||||
|
||||
//########tunnel-server#########
|
||||
tunnelServer := app.Command("tserver", "proxy on tunnel server mode")
|
||||
@ -256,7 +277,8 @@ func StartWithLog(serviceID, serviceArgsStr string, loggerCallback LogCallback)
|
||||
socksArgs.ParentKey = socks.Flag("parent-key", "the password for auto encrypt/decrypt parent connection data").Short('Z').Default("").String()
|
||||
socksArgs.LocalCompress = socks.Flag("local-compress", "auto compress/decompress data on local connection").Short('m').Default("false").Bool()
|
||||
socksArgs.ParentCompress = socks.Flag("parent-compress", "auto compress/decompress data on parent connection").Short('M').Default("false").Bool()
|
||||
socksArgs.LoadBalanceMethod = socks.Flag("lb-method", "load balance method when use multiple parent,can be <roundrobin|leastconn|leasttime|hash|weight>").Default("hash").Enum("roundrobin", "weight", "leastconn", "leasttime", "hash")
|
||||
socksArgs.Intelligent = socks.Flag("intelligent", "settting intelligent HTTP, SOCKS5 proxy mode, can be <intelligent|direct|parent>").Default("intelligent").Enum("intelligent", "direct", "parent")
|
||||
socksArgs.LoadBalanceMethod = socks.Flag("lb-method", "load balance method when use multiple parent,can be <roundrobin|leastconn|leasttime|hash|weight>").Default("roundrobin").Enum("roundrobin", "weight", "leastconn", "leasttime", "hash")
|
||||
socksArgs.LoadBalanceTimeout = socks.Flag("lb-timeout", "tcp milliseconds timeout of connecting to parent").Default("500").Int()
|
||||
socksArgs.LoadBalanceRetryTime = socks.Flag("lb-retrytime", "sleep time milliseconds after checking").Default("1000").Int()
|
||||
socksArgs.LoadBalanceHashTarget = socks.Flag("lb-hashtarget", "use target address to choose parent for LB").Default("false").Bool()
|
||||
@ -303,6 +325,8 @@ func StartWithLog(serviceID, serviceArgsStr string, loggerCallback LogCallback)
|
||||
spsArgs.LoadBalanceHashTarget = sps.Flag("lb-hashtarget", "use target address to choose parent for LB").Default("false").Bool()
|
||||
spsArgs.LoadBalanceOnlyHA = sps.Flag("lb-onlyha", "use only `high availability mode` to choose parent for LB").Default("false").Bool()
|
||||
spsArgs.RateLimit = sps.Flag("rate-limit", "rate limit (bytes/second) of each connection, such as: 100K 1.5M . 0 means no limitation").Short('l').Default("0").String()
|
||||
spsArgs.Jumper = sps.Flag("jumper", "https or socks5 proxies used when connecting to parent, only worked of -T is tls or tcp, format is https://username:password@host:port https://host:port or socks5://username:password@host:port socks5://host:port").Default("").String()
|
||||
spsArgs.ParentTLSSingle = sps.Flag("parent-tls-single", "conntect to parent insecure skip verify").Default("false").Bool()
|
||||
spsArgs.Debug = debug
|
||||
|
||||
//########dns#########
|
||||
@ -394,7 +418,7 @@ func StartWithLog(serviceID, serviceArgsStr string, loggerCallback LogCallback)
|
||||
muxClientArgs.KCP = kcpArgs
|
||||
dnsArgs.KCP = kcpArgs
|
||||
|
||||
log := logger.New(os.Stderr, "", logger.Ldate|logger.Ltime)
|
||||
log := logger.New(os.Stdout, "", logger.Ldate|logger.Ltime)
|
||||
flags := logger.Ldate
|
||||
if *debug {
|
||||
flags |= logger.Lshortfile | logger.Lmicroseconds
|
||||
@ -460,3 +484,41 @@ func Stop(serviceID string) {
|
||||
func Version() string {
|
||||
return SDK_VERSION
|
||||
}
|
||||
func StartProfiling(storePath string) {
|
||||
profilingLock.Lock()
|
||||
defer profilingLock.Unlock()
|
||||
if !isProfiling {
|
||||
isProfiling = true
|
||||
if storePath == "" {
|
||||
storePath = "."
|
||||
}
|
||||
cpuProfilingFile, _ = os.Create(filepath.Join(storePath, "cpu.prof"))
|
||||
memProfilingFile, _ = os.Create(filepath.Join(storePath, "memory.prof"))
|
||||
blockProfilingFile, _ = os.Create(filepath.Join(storePath, "block.prof"))
|
||||
goroutineProfilingFile, _ = os.Create(filepath.Join(storePath, "goroutine.prof"))
|
||||
threadcreateProfilingFile, _ = os.Create(filepath.Join(storePath, "threadcreate.prof"))
|
||||
pprof.StartCPUProfile(cpuProfilingFile)
|
||||
}
|
||||
}
|
||||
func StopProfiling() {
|
||||
profilingLock.Lock()
|
||||
defer profilingLock.Unlock()
|
||||
if isProfiling {
|
||||
isProfiling = false
|
||||
pprof.StopCPUProfile()
|
||||
goroutine := pprof.Lookup("goroutine")
|
||||
goroutine.WriteTo(goroutineProfilingFile, 1)
|
||||
heap := pprof.Lookup("heap")
|
||||
heap.WriteTo(memProfilingFile, 1)
|
||||
block := pprof.Lookup("block")
|
||||
block.WriteTo(blockProfilingFile, 1)
|
||||
threadcreate := pprof.Lookup("threadcreate")
|
||||
threadcreate.WriteTo(threadcreateProfilingFile, 1)
|
||||
//close
|
||||
goroutineProfilingFile.Close()
|
||||
memProfilingFile.Close()
|
||||
blockProfilingFile.Close()
|
||||
threadcreateProfilingFile.Close()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -21,5 +21,15 @@ func Version() (ver *C.char) {
|
||||
return C.CString(sdk.Version())
|
||||
}
|
||||
|
||||
//export StartProfiling
|
||||
func StartProfiling(storePath *C.char) {
|
||||
sdk.StartProfiling(C.GoString(storePath))
|
||||
}
|
||||
|
||||
//export StopProfiling
|
||||
func StopProfiling() {
|
||||
sdk.StopProfiling()
|
||||
}
|
||||
|
||||
func main() {
|
||||
}
|
||||
|
||||
@ -12,11 +12,13 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
server "github.com/snail007/goproxy/core/cs/server"
|
||||
"github.com/snail007/goproxy/core/lib/kcpcfg"
|
||||
"github.com/snail007/goproxy/services"
|
||||
"github.com/snail007/goproxy/services/kcpcfg"
|
||||
"github.com/snail007/goproxy/utils/datasize"
|
||||
"github.com/snail007/goproxy/utils/dnsx"
|
||||
"github.com/snail007/goproxy/utils/iolimiter"
|
||||
"github.com/snail007/goproxy/utils/jumper"
|
||||
"github.com/snail007/goproxy/utils/lb"
|
||||
"github.com/snail007/goproxy/utils/mapx"
|
||||
|
||||
@ -64,6 +66,7 @@ type HTTPArgs struct {
|
||||
ParentKey *string
|
||||
LocalCompress *bool
|
||||
ParentCompress *bool
|
||||
Intelligent *string
|
||||
LoadBalanceMethod *string
|
||||
LoadBalanceTimeout *int
|
||||
LoadBalanceRetryTime *int
|
||||
@ -74,6 +77,7 @@ type HTTPArgs struct {
|
||||
RateLimitBytes float64
|
||||
BindListen *bool
|
||||
Debug *bool
|
||||
Jumper *string
|
||||
}
|
||||
type HTTP struct {
|
||||
cfg HTTPArgs
|
||||
@ -83,10 +87,11 @@ type HTTP struct {
|
||||
lockChn chan bool
|
||||
domainResolver dnsx.DomainResolver
|
||||
isStop bool
|
||||
serverChannels []*utils.ServerChannel
|
||||
serverChannels []*server.ServerChannel
|
||||
userConns mapx.ConcurrentMap
|
||||
log *logger.Logger
|
||||
lb *lb.Group
|
||||
jumper *jumper.Jumper
|
||||
}
|
||||
|
||||
func NewHTTP() services.Service {
|
||||
@ -96,7 +101,7 @@ func NewHTTP() services.Service {
|
||||
basicAuth: utils.BasicAuth{},
|
||||
lockChn: make(chan bool, 1),
|
||||
isStop: false,
|
||||
serverChannels: []*utils.ServerChannel{},
|
||||
serverChannels: []*server.ServerChannel{},
|
||||
userConns: mapx.NewConcurrentMap(),
|
||||
}
|
||||
}
|
||||
@ -162,17 +167,30 @@ func (s *HTTP) CheckArgs() (err error) {
|
||||
}
|
||||
s.cfg.RateLimitBytes = float64(size)
|
||||
}
|
||||
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 *HTTP) InitService() (err error) {
|
||||
s.InitBasicAuth()
|
||||
//init lb
|
||||
if len(*s.cfg.Parent) > 0 {
|
||||
s.checker = utils.NewChecker(*s.cfg.HTTPTimeout, int64(*s.cfg.Interval), *s.cfg.Blocked, *s.cfg.Direct, s.log)
|
||||
s.checker = utils.NewChecker(*s.cfg.HTTPTimeout, int64(*s.cfg.Interval), *s.cfg.Blocked, *s.cfg.Direct, s.log, *s.cfg.Intelligent)
|
||||
s.InitLB()
|
||||
}
|
||||
if *s.cfg.DNSAddress != "" {
|
||||
(*s).domainResolver = dnsx.NewDomainResolver(*s.cfg.DNSAddress, *s.cfg.DNSTTL, s.log)
|
||||
s.domainResolver = dnsx.NewDomainResolver(*s.cfg.DNSAddress, *s.cfg.DNSTTL, s.log)
|
||||
}
|
||||
if *s.cfg.ParentType == "ssh" {
|
||||
err = s.ConnectSSH()
|
||||
@ -183,7 +201,7 @@ func (s *HTTP) InitService() (err error) {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
//循环检查ssh网络连通性
|
||||
@ -192,7 +210,7 @@ func (s *HTTP) InitService() (err error) {
|
||||
return
|
||||
}
|
||||
conn, err := utils.ConnectHost(s.Resolve(s.lb.Select("", *s.cfg.LoadBalanceOnlyHA)), *s.cfg.Timeout*2)
|
||||
if err == nil {
|
||||
if err == nil && conn != nil {
|
||||
conn.SetDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout)))
|
||||
_, err = conn.Write([]byte{0})
|
||||
conn.SetDeadline(time.Time{})
|
||||
@ -221,7 +239,7 @@ 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.basicAuth = utils.BasicAuth{}
|
||||
s.cfg = HTTPArgs{}
|
||||
@ -230,6 +248,7 @@ func (s *HTTP) StopService() {
|
||||
s.lb = nil
|
||||
s.lockChn = nil
|
||||
s.log = nil
|
||||
s.jumper = nil
|
||||
s.serverChannels = nil
|
||||
s.sshClient = nil
|
||||
s.userConns = nil
|
||||
@ -273,11 +292,11 @@ func (s *HTTP) Start(args interface{}, log *logger.Logger) (err error) {
|
||||
if addr != "" {
|
||||
host, port, _ := net.SplitHostPort(addr)
|
||||
p, _ := strconv.Atoi(port)
|
||||
sc := utils.NewServerChannel(host, p, s.log)
|
||||
sc := server.NewServerChannel(host, p, s.log)
|
||||
if *s.cfg.LocalType == "tcp" {
|
||||
err = sc.ListenTCP(s.callback)
|
||||
} else if *s.cfg.LocalType == "tls" {
|
||||
err = sc.ListenTls(s.cfg.CertBytes, s.cfg.KeyBytes, s.cfg.CaCertBytes, s.callback)
|
||||
err = sc.ListenTLS(s.cfg.CertBytes, s.cfg.KeyBytes, s.cfg.CaCertBytes, s.callback)
|
||||
} else if *s.cfg.LocalType == "kcp" {
|
||||
err = sc.ListenKCP(s.cfg.KCP, s.callback, s.log)
|
||||
}
|
||||
@ -367,12 +386,17 @@ func (s *HTTP) OutToTCP(useProxy bool, address string, inConn *net.Conn, req *ut
|
||||
}
|
||||
if useProxy {
|
||||
// s.log.Printf("%v", s.outPool)
|
||||
if *s.cfg.ParentType == "ssh" {
|
||||
outConn, err = s.getSSHConn(address)
|
||||
} else {
|
||||
selectAddr := (*inConn).RemoteAddr().String()
|
||||
if utils.LBMethod(*s.cfg.LoadBalanceMethod) == lb.SELECT_HASH && *s.cfg.LoadBalanceHashTarget {
|
||||
selectAddr = address
|
||||
}
|
||||
lbAddr = s.lb.Select(selectAddr, *s.cfg.LoadBalanceOnlyHA)
|
||||
outConn, err = s.GetParentConn(lbAddr)
|
||||
}
|
||||
|
||||
} else {
|
||||
outConn, err = s.GetDirectConn(s.Resolve(address), inLocalAddr)
|
||||
}
|
||||
@ -392,7 +416,7 @@ func (s *HTTP) OutToTCP(useProxy bool, address string, inConn *net.Conn, req *ut
|
||||
if *s.cfg.ParentCompress {
|
||||
outConn = utils.NewCompConn(outConn)
|
||||
}
|
||||
if *s.cfg.ParentKey != "" {
|
||||
if useProxy && *s.cfg.ParentKey != "" {
|
||||
outConn = conncrypt.New(outConn, &conncrypt.Config{
|
||||
Password: *s.cfg.ParentKey,
|
||||
})
|
||||
@ -407,7 +431,7 @@ func (s *HTTP) OutToTCP(useProxy bool, address string, inConn *net.Conn, req *ut
|
||||
//https或者http,上级是代理,proxy需要转发
|
||||
outConn.SetDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout)))
|
||||
//直连目标或上级非代理或非SNI,,清理HTTP头部的代理头信息
|
||||
if !useProxy || *s.cfg.ParentType == "ssh" && !req.IsSNI {
|
||||
if (!useProxy || *s.cfg.ParentType == "ssh") && !req.IsSNI {
|
||||
_, err = outConn.Write(utils.RemoveProxyHeaders(req.HeadBuf))
|
||||
} else {
|
||||
_, err = outConn.Write(req.HeadBuf)
|
||||
@ -496,6 +520,9 @@ func (s *HTTP) ConnectSSH() (err error) {
|
||||
s.sshClient.Close()
|
||||
}
|
||||
s.sshClient, err = ssh.Dial("tcp", s.Resolve(s.lb.Select("", *s.cfg.LoadBalanceOnlyHA)), &config)
|
||||
if err != nil {
|
||||
s.log.Printf("connect to ssh %s fail", s.cfg.Parent)
|
||||
}
|
||||
<-s.lockChn
|
||||
return
|
||||
}
|
||||
@ -601,11 +628,24 @@ func (s *HTTP) Resolve(address string) string {
|
||||
}
|
||||
func (s *HTTP) GetParentConn(address string) (conn net.Conn, err error) {
|
||||
if *s.cfg.ParentType == "tls" {
|
||||
if s.jumper == nil {
|
||||
var _conn tls.Conn
|
||||
_conn, err = utils.TlsConnectHost(address, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes, s.cfg.CaCertBytes)
|
||||
if err == nil {
|
||||
conn = net.Conn(&_conn)
|
||||
}
|
||||
} else {
|
||||
conf, err := utils.TlsConfig(s.cfg.CertBytes, s.cfg.KeyBytes, s.cfg.CaCertBytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var _c net.Conn
|
||||
_c, err = s.jumper.Dial(address, 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(address, s.cfg.KCP)
|
||||
} else if *s.cfg.ParentType == "ssh" {
|
||||
@ -615,7 +655,11 @@ func (s *HTTP) GetParentConn(address string) (conn net.Conn, err error) {
|
||||
err = fmt.Errorf("%s", e)
|
||||
}
|
||||
} else {
|
||||
if s.jumper == nil {
|
||||
conn, err = utils.ConnectHost(address, *s.cfg.Timeout)
|
||||
} else {
|
||||
conn, err = s.jumper.Dial(address, time.Millisecond*time.Duration(*s.cfg.Timeout))
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -8,16 +8,15 @@ import (
|
||||
"math/rand"
|
||||
"net"
|
||||
"runtime/debug"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
srvtransport "github.com/snail007/goproxy/core/cs/server"
|
||||
"github.com/snail007/goproxy/core/lib/kcpcfg"
|
||||
"github.com/snail007/goproxy/services"
|
||||
"github.com/snail007/goproxy/services/kcpcfg"
|
||||
"github.com/snail007/goproxy/utils"
|
||||
"github.com/snail007/goproxy/utils/mapx"
|
||||
|
||||
//"github.com/xtaci/smux"
|
||||
smux "github.com/hashicorp/yamux"
|
||||
)
|
||||
@ -32,6 +31,10 @@ type MuxBridgeArgs struct {
|
||||
Timeout *int
|
||||
IsCompress *bool
|
||||
KCP kcpcfg.KCPConfigArgs
|
||||
TCPSMethod *string
|
||||
TCPSPassword *string
|
||||
TOUMethod *string
|
||||
TOUPassword *string
|
||||
}
|
||||
type MuxBridge struct {
|
||||
cfg MuxBridgeArgs
|
||||
@ -40,7 +43,7 @@ type MuxBridge struct {
|
||||
router utils.ClientKeyRouter
|
||||
l *sync.Mutex
|
||||
isStop bool
|
||||
sc *utils.ServerChannel
|
||||
sc *srvtransport.ServerChannel
|
||||
log *logger.Logger
|
||||
}
|
||||
|
||||
@ -78,7 +81,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.cfg = MuxBridgeArgs{}
|
||||
s.clientControlConns = nil
|
||||
@ -112,21 +115,27 @@ func (s *MuxBridge) Start(args interface{}, log *logger.Logger) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
host, port, _ := net.SplitHostPort(*s.cfg.Local)
|
||||
p, _ := strconv.Atoi(port)
|
||||
sc := utils.NewServerChannel(host, p, s.log)
|
||||
sc := srvtransport.NewServerChannelHost(*s.cfg.Local, s.log)
|
||||
if *s.cfg.LocalType == "tcp" {
|
||||
err = sc.ListenTCP(s.handler)
|
||||
} else if *s.cfg.LocalType == "tls" {
|
||||
err = sc.ListenTls(s.cfg.CertBytes, s.cfg.KeyBytes, nil, s.handler)
|
||||
err = sc.ListenTLS(s.cfg.CertBytes, s.cfg.KeyBytes, nil, s.handler)
|
||||
} else if *s.cfg.LocalType == "kcp" {
|
||||
err = sc.ListenKCP(s.cfg.KCP, s.handler, s.log)
|
||||
} else if *s.cfg.LocalType == "tcps" {
|
||||
err = sc.ListenTCPS(*s.cfg.TCPSMethod, *s.cfg.TCPSPassword, false, s.handler)
|
||||
} else if *s.cfg.LocalType == "tou" {
|
||||
err = sc.ListenTOU(*s.cfg.TOUMethod, *s.cfg.TOUPassword, false, s.handler)
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
s.sc = &sc
|
||||
if *s.cfg.LocalType == "tou" {
|
||||
s.log.Printf("%s bridge on %s", *s.cfg.LocalType, sc.UDPListener.LocalAddr())
|
||||
} else {
|
||||
s.log.Printf("%s bridge on %s", *s.cfg.LocalType, (*sc.Listener).Addr())
|
||||
}
|
||||
return
|
||||
}
|
||||
func (s *MuxBridge) Clean() {
|
||||
@ -206,21 +215,25 @@ func (s *MuxBridge) handler(inConn net.Conn) {
|
||||
index := keyInfo[1]
|
||||
s.l.Lock()
|
||||
defer s.l.Unlock()
|
||||
var group *mapx.ConcurrentMap
|
||||
if !s.clientControlConns.Has(groupKey) {
|
||||
item := mapx.NewConcurrentMap()
|
||||
s.clientControlConns.Set(groupKey, &item)
|
||||
}
|
||||
_g := mapx.NewConcurrentMap()
|
||||
group = &_g
|
||||
s.clientControlConns.Set(groupKey, group)
|
||||
//s.log.Printf("init client session group %s", groupKey)
|
||||
} else {
|
||||
_group, _ := s.clientControlConns.Get(groupKey)
|
||||
group := _group.(*mapx.ConcurrentMap)
|
||||
group = _group.(*mapx.ConcurrentMap)
|
||||
}
|
||||
if v, ok := group.Get(index); ok {
|
||||
v.(*smux.Session).Close()
|
||||
}
|
||||
group.Set(index, session)
|
||||
// s.clientControlConns.Set(key, session)
|
||||
//s.log.Printf("set client session %s to group %s,grouplen:%d", index, groupKey, group.Count())
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
for {
|
||||
@ -232,10 +245,12 @@ func (s *MuxBridge) handler(inConn net.Conn) {
|
||||
defer s.l.Unlock()
|
||||
if sess, ok := group.Get(index); ok && sess.(*smux.Session).IsClosed() {
|
||||
group.Remove(index)
|
||||
//s.log.Printf("client session %s removed from group %s, grouplen:%d", key, groupKey, group.Count())
|
||||
s.log.Printf("client connection %s released", key)
|
||||
}
|
||||
if group.IsEmpty() {
|
||||
s.clientControlConns.Remove(groupKey)
|
||||
//s.log.Printf("client session group %s removed", groupKey)
|
||||
}
|
||||
break
|
||||
}
|
||||
@ -259,6 +274,7 @@ func (s *MuxBridge) callback(inConn net.Conn, serverID, key string) {
|
||||
if key == "*" {
|
||||
key = s.router.GetKey()
|
||||
}
|
||||
//s.log.Printf("server get client session %s", key)
|
||||
_group, ok := s.clientControlConns.Get(key)
|
||||
if !ok {
|
||||
s.log.Printf("client %s session not exists for server stream %s, retrying...", key, serverID)
|
||||
@ -266,8 +282,12 @@ func (s *MuxBridge) callback(inConn net.Conn, serverID, key string) {
|
||||
continue
|
||||
}
|
||||
group := _group.(*mapx.ConcurrentMap)
|
||||
keys := group.Keys()
|
||||
keys := []string{}
|
||||
group.IterCb(func(key string, v interface{}) {
|
||||
keys = append(keys, key)
|
||||
})
|
||||
keysLen := len(keys)
|
||||
//s.log.Printf("client session %s , len:%d , keysLen: %d", key, group.Count(), keysLen)
|
||||
i := 0
|
||||
if keysLen > 0 {
|
||||
i = rand.Intn(keysLen)
|
||||
@ -293,7 +313,7 @@ func (s *MuxBridge) callback(inConn net.Conn, serverID, key string) {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
io.Copy(stream, inConn)
|
||||
@ -302,7 +322,7 @@ func (s *MuxBridge) callback(inConn net.Conn, serverID, key string) {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
io.Copy(inConn, stream)
|
||||
|
||||
@ -8,15 +8,17 @@ import (
|
||||
"net"
|
||||
"runtime/debug"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/golang/snappy"
|
||||
clienttransport "github.com/snail007/goproxy/core/cs/client"
|
||||
"github.com/snail007/goproxy/core/lib/kcpcfg"
|
||||
encryptconn "github.com/snail007/goproxy/core/lib/transport/encrypt"
|
||||
"github.com/snail007/goproxy/services"
|
||||
"github.com/snail007/goproxy/services/kcpcfg"
|
||||
"github.com/snail007/goproxy/utils"
|
||||
"github.com/snail007/goproxy/utils/jumper"
|
||||
"github.com/snail007/goproxy/utils/mapx"
|
||||
|
||||
"github.com/golang/snappy"
|
||||
//"github.com/xtaci/smux"
|
||||
smux "github.com/hashicorp/yamux"
|
||||
)
|
||||
@ -34,6 +36,10 @@ type MuxClientArgs struct {
|
||||
SessionCount *int
|
||||
KCP kcpcfg.KCPConfigArgs
|
||||
Jumper *string
|
||||
TCPSMethod *string
|
||||
TCPSPassword *string
|
||||
TOUMethod *string
|
||||
TOUPassword *string
|
||||
}
|
||||
type ClientUDPConnItem struct {
|
||||
conn *smux.Stream
|
||||
@ -105,7 +111,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.cfg = MuxClientArgs{}
|
||||
s.jumper = nil
|
||||
@ -140,7 +146,7 @@ func (s *MuxClient) Start(args interface{}, log *logger.Logger) (err error) {
|
||||
defer func() {
|
||||
e := recover()
|
||||
if e != nil {
|
||||
s.log.Printf("session worker crashed: %s", e)
|
||||
s.log.Printf("session worker crashed: %s\nstack:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
for {
|
||||
@ -154,7 +160,16 @@ func (s *MuxClient) Start(args interface{}, log *logger.Logger) (err error) {
|
||||
continue
|
||||
}
|
||||
conn.SetDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout)))
|
||||
g := sync.WaitGroup{}
|
||||
g.Add(1)
|
||||
go func() {
|
||||
defer func() {
|
||||
_ = recover()
|
||||
g.Done()
|
||||
}()
|
||||
_, err = conn.Write(utils.BuildPacket(CONN_CLIENT, fmt.Sprintf("%s-%d", *s.cfg.Key, i)))
|
||||
}()
|
||||
g.Wait()
|
||||
conn.SetDeadline(time.Time{})
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
@ -222,14 +237,14 @@ 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)
|
||||
_conn, err = clienttransport.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
|
||||
conf, e := utils.TlsConfig(s.cfg.CertBytes, s.cfg.KeyBytes, nil)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
var _c net.Conn
|
||||
_c, err = s.jumper.Dial(*s.cfg.Parent, time.Millisecond*time.Duration(*s.cfg.Timeout))
|
||||
@ -239,10 +254,22 @@ func (s *MuxClient) getParentConn() (conn net.Conn, err error) {
|
||||
}
|
||||
|
||||
} else if *s.cfg.ParentType == "kcp" {
|
||||
conn, err = utils.ConnectKCPHost(*s.cfg.Parent, s.cfg.KCP)
|
||||
conn, err = clienttransport.KCPConnectHost(*s.cfg.Parent, s.cfg.KCP)
|
||||
} else if *s.cfg.ParentType == "tcps" {
|
||||
if s.jumper == nil {
|
||||
conn, err = clienttransport.TCPSConnectHost(*s.cfg.Parent, *s.cfg.TCPSMethod, *s.cfg.TCPSPassword, false, *s.cfg.Timeout)
|
||||
} else {
|
||||
conn, err = s.jumper.Dial(*s.cfg.Parent, time.Millisecond*time.Duration(*s.cfg.Timeout))
|
||||
if err == nil {
|
||||
conn, err = encryptconn.NewConn(conn, *s.cfg.TCPSMethod, *s.cfg.TCPSPassword)
|
||||
}
|
||||
}
|
||||
|
||||
} else if *s.cfg.ParentType == "tou" {
|
||||
conn, err = clienttransport.TOUConnectHost(*s.cfg.Parent, *s.cfg.TCPSMethod, *s.cfg.TCPSPassword, false, *s.cfg.Timeout)
|
||||
} else {
|
||||
if s.jumper == nil {
|
||||
conn, err = utils.ConnectHost(*s.cfg.Parent, *s.cfg.Timeout)
|
||||
conn, err = clienttransport.TCPConnectHost(*s.cfg.Parent, *s.cfg.Timeout)
|
||||
} else {
|
||||
conn, err = s.jumper.Dial(*s.cfg.Parent, time.Millisecond*time.Duration(*s.cfg.Timeout))
|
||||
}
|
||||
@ -299,14 +326,17 @@ func (s *MuxClient) ServeUDP(inConn *smux.Stream, localAddr, ID string) {
|
||||
item = v.(*ClientUDPConnItem)
|
||||
}
|
||||
(*item).touchtime = time.Now().Unix()
|
||||
go (*item).udpConn.Write(body)
|
||||
go func() {
|
||||
defer func() { _ = recover() }()
|
||||
(*item).udpConn.Write(body)
|
||||
}()
|
||||
}
|
||||
}
|
||||
func (s *MuxClient) UDPRevecive(key, ID string) {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
s.log.Printf("udp conn %s connected", ID)
|
||||
@ -336,7 +366,7 @@ func (s *MuxClient) UDPRevecive(key, ID string) {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
cui.conn.SetWriteDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout)))
|
||||
@ -355,7 +385,7 @@ func (s *MuxClient) UDPGCDeamon() {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
if s.isStop {
|
||||
@ -414,7 +444,7 @@ func (s *MuxClient) ServeConn(inConn *smux.Stream, localAddr, ID string) {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
io.Copy(outConn, snappy.NewReader(inConn))
|
||||
@ -423,7 +453,7 @@ func (s *MuxClient) ServeConn(inConn *smux.Stream, localAddr, ID string) {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
io.Copy(snappy.NewWriter(inConn), outConn)
|
||||
|
||||
@ -12,8 +12,11 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
clienttransport "github.com/snail007/goproxy/core/cs/client"
|
||||
server "github.com/snail007/goproxy/core/cs/server"
|
||||
"github.com/snail007/goproxy/core/lib/kcpcfg"
|
||||
encryptconn "github.com/snail007/goproxy/core/lib/transport/encrypt"
|
||||
"github.com/snail007/goproxy/services"
|
||||
"github.com/snail007/goproxy/services/kcpcfg"
|
||||
"github.com/snail007/goproxy/utils"
|
||||
"github.com/snail007/goproxy/utils/jumper"
|
||||
"github.com/snail007/goproxy/utils/mapx"
|
||||
@ -47,10 +50,14 @@ type MuxServerArgs struct {
|
||||
SessionCount *int
|
||||
KCP kcpcfg.KCPConfigArgs
|
||||
Jumper *string
|
||||
TCPSMethod *string
|
||||
TCPSPassword *string
|
||||
TOUMethod *string
|
||||
TOUPassword *string
|
||||
}
|
||||
type MuxServer struct {
|
||||
cfg MuxServerArgs
|
||||
sc utils.ServerChannel
|
||||
sc server.ServerChannel
|
||||
sessions mapx.ConcurrentMap
|
||||
lockChn chan bool
|
||||
isStop bool
|
||||
@ -133,6 +140,10 @@ func (s *MuxServerManager) Start(args interface{}, log *logger.Logger) (err erro
|
||||
KCP: s.cfg.KCP,
|
||||
ParentType: s.cfg.ParentType,
|
||||
Jumper: s.cfg.Jumper,
|
||||
TCPSMethod: s.cfg.TCPSMethod,
|
||||
TCPSPassword: s.cfg.TCPSPassword,
|
||||
TOUMethod: s.cfg.TOUMethod,
|
||||
TOUPassword: s.cfg.TOUPassword,
|
||||
}, log)
|
||||
|
||||
if err != nil {
|
||||
@ -196,13 +207,13 @@ 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.cfg = MuxServerArgs{}
|
||||
s.jumper = nil
|
||||
s.lockChn = nil
|
||||
s.log = nil
|
||||
s.sc = utils.ServerChannel{}
|
||||
s.sc = server.ServerChannel{}
|
||||
s.sessions = nil
|
||||
s.udpConns = nil
|
||||
s = nil
|
||||
@ -254,7 +265,7 @@ func (s *MuxServer) Start(args interface{}, log *logger.Logger) (err error) {
|
||||
}
|
||||
host, port, _ := net.SplitHostPort(*s.cfg.Local)
|
||||
p, _ := strconv.Atoi(port)
|
||||
s.sc = utils.NewServerChannel(host, p, s.log)
|
||||
s.sc = server.NewServerChannel(host, p, s.log)
|
||||
if *s.cfg.IsUDP {
|
||||
err = s.sc.ListenUDP(func(listener *net.UDPConn, packet []byte, localAddr, srcAddr *net.UDPAddr) {
|
||||
s.UDPSend(packet, localAddr, srcAddr)
|
||||
@ -293,7 +304,7 @@ func (s *MuxServer) Start(args interface{}, log *logger.Logger) (err error) {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
io.Copy(inConn, snappy.NewReader(outConn))
|
||||
@ -302,7 +313,7 @@ func (s *MuxServer) Start(args interface{}, log *logger.Logger) (err error) {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
io.Copy(snappy.NewWriter(outConn), inConn)
|
||||
@ -397,7 +408,7 @@ func (s *MuxServer) GetConn(index string) (conn net.Conn, err error) {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
for {
|
||||
@ -443,6 +454,18 @@ func (s *MuxServer) getParentConn() (conn net.Conn, err error) {
|
||||
|
||||
} else if *s.cfg.ParentType == "kcp" {
|
||||
conn, err = utils.ConnectKCPHost(*s.cfg.Parent, s.cfg.KCP)
|
||||
} else if *s.cfg.ParentType == "tcps" {
|
||||
if s.jumper == nil {
|
||||
conn, err = clienttransport.TCPSConnectHost(*s.cfg.Parent, *s.cfg.TCPSMethod, *s.cfg.TCPSPassword, false, *s.cfg.Timeout)
|
||||
} else {
|
||||
conn, err = s.jumper.Dial(*s.cfg.Parent, time.Millisecond*time.Duration(*s.cfg.Timeout))
|
||||
if err == nil {
|
||||
conn, err = encryptconn.NewConn(conn, *s.cfg.TCPSMethod, *s.cfg.TCPSPassword)
|
||||
}
|
||||
}
|
||||
|
||||
} else if *s.cfg.ParentType == "tou" {
|
||||
conn, err = clienttransport.TOUConnectHost(*s.cfg.Parent, *s.cfg.TCPSMethod, *s.cfg.TCPSPassword, false, *s.cfg.Timeout)
|
||||
} else {
|
||||
if s.jumper == nil {
|
||||
conn, err = utils.ConnectHost(*s.cfg.Parent, *s.cfg.Timeout)
|
||||
@ -457,7 +480,7 @@ func (s *MuxServer) UDPGCDeamon() {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
if s.isStop {
|
||||
@ -536,7 +559,7 @@ func (s *MuxServer) UDPRevecive(key, ID string) {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
s.log.Printf("udp conn %s connected", ID)
|
||||
@ -569,7 +592,7 @@ func (s *MuxServer) UDPRevecive(key, ID string) {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
s.sc.UDPListener.WriteToUDP(body, uc.srcAddr)
|
||||
|
||||
@ -39,6 +39,9 @@ func GetService(name string) *ServiceItem {
|
||||
func Stop(name string) {
|
||||
if s, ok := servicesMap.Load(name); ok && s.(*ServiceItem).S != nil {
|
||||
s.(*ServiceItem).S.Clean()
|
||||
*s.(*ServiceItem) = ServiceItem{}
|
||||
s = nil
|
||||
servicesMap.Store(name, nil)
|
||||
servicesMap.Delete(name)
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,8 +12,9 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
server "github.com/snail007/goproxy/core/cs/server"
|
||||
"github.com/snail007/goproxy/core/lib/kcpcfg"
|
||||
"github.com/snail007/goproxy/services"
|
||||
"github.com/snail007/goproxy/services/kcpcfg"
|
||||
"github.com/snail007/goproxy/utils"
|
||||
"github.com/snail007/goproxy/utils/conncrypt"
|
||||
"github.com/snail007/goproxy/utils/datasize"
|
||||
@ -63,6 +64,7 @@ type SocksArgs struct {
|
||||
ParentKey *string
|
||||
LocalCompress *bool
|
||||
ParentCompress *bool
|
||||
Intelligent *string
|
||||
LoadBalanceMethod *string
|
||||
LoadBalanceTimeout *int
|
||||
LoadBalanceRetryTime *int
|
||||
@ -80,8 +82,8 @@ type Socks struct {
|
||||
basicAuth utils.BasicAuth
|
||||
sshClient *ssh.Client
|
||||
lockChn chan bool
|
||||
udpSC utils.ServerChannel
|
||||
sc *utils.ServerChannel
|
||||
udpSC server.ServerChannel
|
||||
sc *server.ServerChannel
|
||||
domainResolver dnsx.DomainResolver
|
||||
isStop bool
|
||||
userConns mapx.ConcurrentMap
|
||||
@ -179,7 +181,7 @@ func (s *Socks) InitService() (err error) {
|
||||
(*s).domainResolver = dnsx.NewDomainResolver(*s.cfg.DNSAddress, *s.cfg.DNSTTL, s.log)
|
||||
}
|
||||
if len(*s.cfg.Parent) > 0 {
|
||||
s.checker = utils.NewChecker(*s.cfg.Timeout, int64(*s.cfg.Interval), *s.cfg.Blocked, *s.cfg.Direct, s.log)
|
||||
s.checker = utils.NewChecker(*s.cfg.Timeout, int64(*s.cfg.Interval), *s.cfg.Blocked, *s.cfg.Direct, s.log, *s.cfg.Intelligent)
|
||||
s.InitLB()
|
||||
}
|
||||
if *s.cfg.ParentType == "ssh" {
|
||||
@ -191,7 +193,7 @@ func (s *Socks) InitService() (err error) {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:\n%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
//循环检查ssh网络连通性
|
||||
@ -229,7 +231,7 @@ 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.basicAuth = utils.BasicAuth{}
|
||||
s.cfg = SocksArgs{}
|
||||
@ -243,7 +245,7 @@ func (s *Socks) StopService() {
|
||||
s.udpLocalKey = nil
|
||||
s.udpParentKey = nil
|
||||
s.udpRelatedPacketConns = nil
|
||||
s.udpSC = utils.ServerChannel{}
|
||||
s.udpSC = server.ServerChannel{}
|
||||
s.userConns = nil
|
||||
s = nil
|
||||
}()
|
||||
@ -283,11 +285,11 @@ func (s *Socks) Start(args interface{}, log *logger.Logger) (err error) {
|
||||
if len(*s.cfg.Parent) > 0 {
|
||||
s.log.Printf("use %s parent %v [ %s ]", *s.cfg.ParentType, *s.cfg.Parent, strings.ToUpper(*s.cfg.LoadBalanceMethod))
|
||||
}
|
||||
sc := utils.NewServerChannelHost(*s.cfg.Local, s.log)
|
||||
sc := server.NewServerChannelHost(*s.cfg.Local, s.log)
|
||||
if *s.cfg.LocalType == "tcp" {
|
||||
err = sc.ListenTCP(s.socksConnCallback)
|
||||
} else if *s.cfg.LocalType == "tls" {
|
||||
err = sc.ListenTls(s.cfg.CertBytes, s.cfg.KeyBytes, s.cfg.CaCertBytes, s.socksConnCallback)
|
||||
err = sc.ListenTLS(s.cfg.CertBytes, s.cfg.KeyBytes, s.cfg.CaCertBytes, s.socksConnCallback)
|
||||
} else if *s.cfg.LocalType == "kcp" {
|
||||
err = sc.ListenKCP(s.cfg.KCP, s.socksConnCallback, s.log)
|
||||
}
|
||||
@ -462,11 +464,7 @@ func (s *Socks) proxyTCP(inConn *net.Conn, serverConn *socks.ServerConn) {
|
||||
}
|
||||
func (s *Socks) GetParentConn(parentAddress string, serverConn *socks.ServerConn) (outConn net.Conn, err interface{}) {
|
||||
switch *s.cfg.ParentType {
|
||||
case "kcp":
|
||||
fallthrough
|
||||
case "tls":
|
||||
fallthrough
|
||||
case "tcp":
|
||||
case "kcp", "tls", "tcp":
|
||||
if *s.cfg.ParentType == "tls" {
|
||||
var _conn tls.Conn
|
||||
_conn, err = utils.TlsConnectHost(parentAddress, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes, s.cfg.CaCertBytes)
|
||||
|
||||
@ -174,9 +174,9 @@ func (s *Socks) proxyUDP(inConn *net.Conn, serverConn *socks.ServerConn) {
|
||||
}
|
||||
s.log.Printf("use proxy %v : udp %s", useProxy, serverConn.Target())
|
||||
//relay
|
||||
for {
|
||||
buf := utils.LeakyBuffer.Get()
|
||||
defer utils.LeakyBuffer.Put(buf)
|
||||
for {
|
||||
n, srcAddr, err := udpListener.ReadFromUDP(buf)
|
||||
if err != nil {
|
||||
s.log.Printf("udp listener read fail, %s", err.Error())
|
||||
|
||||
@ -101,7 +101,7 @@ func (s *SPS) proxyUDP(inConn *net.Conn, serverConn *socks.ServerConn) {
|
||||
s.log.Printf("connect %s for udp", serverConn.Target())
|
||||
//socks client
|
||||
|
||||
client, err := s.HandshakeSocksParent(&outconn, "udp", serverConn.Target(), serverConn.AuthData(), false)
|
||||
client, err := s.HandshakeSocksParent(s.getParentAuth(lbAddr), &outconn, "udp", serverConn.Target(), serverConn.AuthData(), false)
|
||||
if err != nil {
|
||||
clean("handshake fail", fmt.Sprintf("%s", err))
|
||||
return
|
||||
@ -126,9 +126,9 @@ func (s *SPS) proxyUDP(inConn *net.Conn, serverConn *socks.ServerConn) {
|
||||
//s.log.Printf("parent udp address %s", client.UDPAddr)
|
||||
destAddr, _ = net.ResolveUDPAddr("udp", client.UDPAddr)
|
||||
//relay
|
||||
for {
|
||||
buf := utils.LeakyBuffer.Get()
|
||||
defer utils.LeakyBuffer.Put(buf)
|
||||
for {
|
||||
n, srcAddr, err := udpListener.ReadFromUDP(buf)
|
||||
if err != nil {
|
||||
s.log.Printf("udp listener read fail, %s", err.Error())
|
||||
|
||||
@ -13,15 +13,19 @@ import (
|
||||
"runtime/debug"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/snail007/goproxy/core/cs/server"
|
||||
"github.com/snail007/goproxy/core/lib/kcpcfg"
|
||||
"github.com/snail007/goproxy/services"
|
||||
"github.com/snail007/goproxy/services/kcpcfg"
|
||||
"github.com/snail007/goproxy/utils"
|
||||
"github.com/snail007/goproxy/utils/conncrypt"
|
||||
cryptool "github.com/snail007/goproxy/utils/crypt"
|
||||
"github.com/snail007/goproxy/utils/datasize"
|
||||
"github.com/snail007/goproxy/utils/dnsx"
|
||||
"github.com/snail007/goproxy/utils/iolimiter"
|
||||
"github.com/snail007/goproxy/utils/jumper"
|
||||
"github.com/snail007/goproxy/utils/lb"
|
||||
"github.com/snail007/goproxy/utils/mapx"
|
||||
"github.com/snail007/goproxy/utils/sni"
|
||||
@ -69,16 +73,18 @@ type SPSArgs struct {
|
||||
LoadBalanceRetryTime *int
|
||||
LoadBalanceHashTarget *bool
|
||||
LoadBalanceOnlyHA *bool
|
||||
ParentTLSSingle *bool
|
||||
|
||||
RateLimit *string
|
||||
RateLimitBytes float64
|
||||
Debug *bool
|
||||
Jumper *string
|
||||
}
|
||||
type SPS struct {
|
||||
cfg SPSArgs
|
||||
domainResolver dnsx.DomainResolver
|
||||
basicAuth utils.BasicAuth
|
||||
serverChannels []*utils.ServerChannel
|
||||
serverChannels []*server.ServerChannel
|
||||
userConns mapx.ConcurrentMap
|
||||
log *logger.Logger
|
||||
localCipher *ss.Cipher
|
||||
@ -87,15 +93,20 @@ type SPS struct {
|
||||
lb *lb.Group
|
||||
udpLocalKey []byte
|
||||
udpParentKey []byte
|
||||
jumper *jumper.Jumper
|
||||
parentAuthData *sync.Map
|
||||
parentCipherData *sync.Map
|
||||
}
|
||||
|
||||
func NewSPS() services.Service {
|
||||
return &SPS{
|
||||
cfg: SPSArgs{},
|
||||
basicAuth: utils.BasicAuth{},
|
||||
serverChannels: []*utils.ServerChannel{},
|
||||
serverChannels: []*server.ServerChannel{},
|
||||
userConns: mapx.NewConcurrentMap(),
|
||||
udpRelatedPacketConns: mapx.NewConcurrentMap(),
|
||||
parentAuthData: &sync.Map{},
|
||||
parentCipherData: &sync.Map{},
|
||||
}
|
||||
}
|
||||
func (s *SPS) CheckArgs() (err error) {
|
||||
@ -117,10 +128,12 @@ func (s *SPS) CheckArgs() (err error) {
|
||||
return
|
||||
}
|
||||
if *s.cfg.ParentType == "tls" || *s.cfg.LocalType == "tls" {
|
||||
if !*s.cfg.ParentTLSSingle {
|
||||
s.cfg.CertBytes, s.cfg.KeyBytes, err = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
if *s.cfg.CaCertFile != "" {
|
||||
s.cfg.CaCertBytes, err = ioutil.ReadFile(*s.cfg.CaCertFile)
|
||||
if err != nil {
|
||||
@ -140,16 +153,32 @@ func (s *SPS) CheckArgs() (err error) {
|
||||
}
|
||||
s.udpLocalKey = s.LocalUDPKey()
|
||||
s.udpParentKey = s.ParentUDPKey()
|
||||
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 *SPS) InitService() (err error) {
|
||||
|
||||
if *s.cfg.DNSAddress != "" {
|
||||
(*s).domainResolver = dnsx.NewDomainResolver(*s.cfg.DNSAddress, *s.cfg.DNSTTL, s.log)
|
||||
s.domainResolver = dnsx.NewDomainResolver(*s.cfg.DNSAddress, *s.cfg.DNSTTL, s.log)
|
||||
}
|
||||
|
||||
if len(*s.cfg.Parent) > 0 {
|
||||
s.InitLB()
|
||||
err = s.InitLB()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
err = s.InitBasicAuth()
|
||||
@ -176,13 +205,14 @@ 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")
|
||||
}
|
||||
s.basicAuth = utils.BasicAuth{}
|
||||
s.cfg = SPSArgs{}
|
||||
s.domainResolver = dnsx.DomainResolver{}
|
||||
s.lb = nil
|
||||
s.localCipher = nil
|
||||
s.jumper = nil
|
||||
s.log = nil
|
||||
s.parentCipher = nil
|
||||
s.serverChannels = nil
|
||||
@ -190,6 +220,8 @@ func (s *SPS) StopService() {
|
||||
s.udpParentKey = nil
|
||||
s.udpRelatedPacketConns = nil
|
||||
s.userConns = nil
|
||||
s.parentAuthData = nil
|
||||
s.parentCipherData = nil
|
||||
s = nil
|
||||
}()
|
||||
for _, sc := range s.serverChannels {
|
||||
@ -230,15 +262,18 @@ func (s *SPS) Start(args interface{}, log *logger.Logger) (err error) {
|
||||
if addr != "" {
|
||||
host, port, _ := net.SplitHostPort(addr)
|
||||
p, _ := strconv.Atoi(port)
|
||||
sc := utils.NewServerChannel(host, p, s.log)
|
||||
sc := server.NewServerChannel(host, p, s.log)
|
||||
s.serverChannels = append(s.serverChannels, &sc)
|
||||
if *s.cfg.LocalType == "tcp" {
|
||||
err = sc.ListenTCP(s.callback)
|
||||
} else if *s.cfg.LocalType == "tls" {
|
||||
err = sc.ListenTls(s.cfg.CertBytes, s.cfg.KeyBytes, s.cfg.CaCertBytes, s.callback)
|
||||
} else if *s.cfg.LocalType == "tcp" {
|
||||
err = sc.ListenTLS(s.cfg.CertBytes, s.cfg.KeyBytes, s.cfg.CaCertBytes, s.callback)
|
||||
} else if *s.cfg.LocalType == "kcp" {
|
||||
err = sc.ListenKCP(s.cfg.KCP, s.callback, s.log)
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if *s.cfg.ParentServiceType == "socks" {
|
||||
err = s.RunSSUDP(addr)
|
||||
} else {
|
||||
@ -273,11 +308,7 @@ func (s *SPS) callback(inConn net.Conn) {
|
||||
var err error
|
||||
lbAddr := ""
|
||||
switch *s.cfg.ParentType {
|
||||
case "kcp":
|
||||
fallthrough
|
||||
case "tcp":
|
||||
fallthrough
|
||||
case "tls":
|
||||
case "kcp", "tcp", "tls":
|
||||
lbAddr, err = s.OutToTCP(&inConn)
|
||||
default:
|
||||
err = fmt.Errorf("unkown parent type %s", *s.cfg.ParentType)
|
||||
@ -363,7 +394,6 @@ func (s *SPS) OutToTCP(inConn *net.Conn) (lbAddr string, err error) {
|
||||
request.HTTPSReply()
|
||||
//s.log.Printf("https reply: %s", request.Host)
|
||||
} else {
|
||||
//forwardBytes = bytes.TrimRight(request.HeadBuf,"\r\n")
|
||||
forwardBytes = request.HeadBuf
|
||||
}
|
||||
address = request.Host
|
||||
@ -412,15 +442,14 @@ func (s *SPS) OutToTCP(inConn *net.Conn) (lbAddr string, err error) {
|
||||
selectAddr = address
|
||||
}
|
||||
lbAddr = s.lb.Select(selectAddr, *s.cfg.LoadBalanceOnlyHA)
|
||||
//lbAddr = s.lb.Select((*inConn).RemoteAddr().String())
|
||||
outConn, err = s.GetParentConn(lbAddr)
|
||||
if err != nil {
|
||||
s.log.Printf("connect to %s , err:%s", lbAddr, err)
|
||||
utils.CloseConn(inConn)
|
||||
return
|
||||
}
|
||||
|
||||
if *s.cfg.ParentAuth != "" || *s.cfg.ParentSSKey != "" || s.IsBasicAuth() {
|
||||
ParentAuth := s.getParentAuth(lbAddr)
|
||||
if ParentAuth != "" || *s.cfg.ParentSSKey != "" || s.IsBasicAuth() {
|
||||
forwardBytes = utils.RemoveProxyHeaders(forwardBytes)
|
||||
}
|
||||
|
||||
@ -440,8 +469,8 @@ func (s *SPS) OutToTCP(inConn *net.Conn) (lbAddr string, err error) {
|
||||
pb.WriteString("Connection: Keep-Alive\r\n")
|
||||
|
||||
u := ""
|
||||
if *s.cfg.ParentAuth != "" {
|
||||
a := strings.Split(*s.cfg.ParentAuth, ":")
|
||||
if ParentAuth != "" {
|
||||
a := strings.Split(ParentAuth, ":")
|
||||
if len(a) != 2 {
|
||||
err = fmt.Errorf("parent auth data format error")
|
||||
return
|
||||
@ -492,7 +521,7 @@ func (s *SPS) OutToTCP(inConn *net.Conn) (lbAddr string, err error) {
|
||||
s.log.Printf("connect %s", address)
|
||||
|
||||
//socks client
|
||||
_, err = s.HandshakeSocksParent(&outConn, "tcp", address, auth, false)
|
||||
_, err = s.HandshakeSocksParent(ParentAuth, &outConn, "tcp", address, auth, false)
|
||||
if err != nil {
|
||||
s.log.Printf("handshake fail, %s", err)
|
||||
return
|
||||
@ -505,7 +534,7 @@ func (s *SPS) OutToTCP(inConn *net.Conn) (lbAddr string, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
outConn, err = ss.DialWithRawAddr(&outConn, ra, "", s.parentCipher.Copy())
|
||||
outConn, err = ss.DialWithRawAddr(&outConn, ra, "", s.getParentCipher(lbAddr))
|
||||
if err != nil {
|
||||
err = fmt.Errorf("dial ss parent fail, err : %s", err)
|
||||
return
|
||||
@ -565,10 +594,41 @@ func (s *SPS) InitBasicAuth() (err error) {
|
||||
}
|
||||
return
|
||||
}
|
||||
func (s *SPS) InitLB() {
|
||||
func (s *SPS) InitLB() (err error) {
|
||||
configs := lb.BackendsConfig{}
|
||||
for _, addr := range *s.cfg.Parent {
|
||||
_addrInfo := strings.Split(addr, "@")
|
||||
var _addrInfo []string
|
||||
if strings.Contains(addr, "#") {
|
||||
_s := addr[:strings.Index(addr, "#")]
|
||||
_auth, err := cryptool.CryptTools.Base64Decode(_s)
|
||||
if err != nil {
|
||||
s.log.Printf("decoding parent auth data [ %s ] fail , error : %s", _s, err)
|
||||
return err
|
||||
}
|
||||
_addrInfo = strings.Split(addr[strings.Index(addr, "#")+1:], "@")
|
||||
if *s.cfg.ParentServiceType == "ss" {
|
||||
_s := strings.Split(_auth, ":")
|
||||
m := _s[0]
|
||||
k := _s[1]
|
||||
if m == "" {
|
||||
m = *s.cfg.ParentSSMethod
|
||||
}
|
||||
if k == "" {
|
||||
k = *s.cfg.ParentSSKey
|
||||
}
|
||||
cipher, err := ss.NewCipher(m, k)
|
||||
if err != nil {
|
||||
s.log.Printf("error generating cipher, ssMethod: %s, ssKey: %s, error : %s", m, k, err)
|
||||
return err
|
||||
}
|
||||
s.parentCipherData.Store(_addrInfo[0], cipher)
|
||||
} else {
|
||||
s.parentAuthData.Store(_addrInfo[0], _auth)
|
||||
}
|
||||
|
||||
} else {
|
||||
_addrInfo = strings.Split(addr, "@")
|
||||
}
|
||||
_addr := _addrInfo[0]
|
||||
weight := 1
|
||||
if len(_addrInfo) == 2 {
|
||||
@ -585,6 +645,19 @@ func (s *SPS) InitLB() {
|
||||
}
|
||||
LB := lb.NewGroup(utils.LBMethod(*s.cfg.LoadBalanceMethod), configs, &s.domainResolver, s.log, *s.cfg.Debug)
|
||||
s.lb = &LB
|
||||
return
|
||||
}
|
||||
func (s *SPS) getParentAuth(lbAddr string) string {
|
||||
if v, ok := s.parentAuthData.Load(lbAddr); ok {
|
||||
return v.(string)
|
||||
}
|
||||
return *s.cfg.ParentAuth
|
||||
}
|
||||
func (s *SPS) getParentCipher(lbAddr string) *ss.Cipher {
|
||||
if v, ok := s.parentCipherData.Load(lbAddr); ok {
|
||||
return v.(*ss.Cipher).Copy()
|
||||
}
|
||||
return s.parentCipher.Copy()
|
||||
}
|
||||
func (s *SPS) IsBasicAuth() bool {
|
||||
return *s.cfg.AuthFile != "" || len(*s.cfg.Auth) > 0 || *s.cfg.AuthURL != ""
|
||||
@ -640,15 +713,41 @@ func (s *SPS) Resolve(address string) string {
|
||||
}
|
||||
func (s *SPS) GetParentConn(address string) (conn net.Conn, err error) {
|
||||
if *s.cfg.ParentType == "tls" {
|
||||
if s.jumper == nil {
|
||||
var _conn tls.Conn
|
||||
if *s.cfg.ParentTLSSingle {
|
||||
_conn, err = utils.SingleTlsConnectHost(address, *s.cfg.Timeout, s.cfg.CaCertBytes)
|
||||
} else {
|
||||
_conn, err = utils.TlsConnectHost(address, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes, s.cfg.CaCertBytes)
|
||||
}
|
||||
if err == nil {
|
||||
conn = net.Conn(&_conn)
|
||||
}
|
||||
} else {
|
||||
var conf *tls.Config
|
||||
if *s.cfg.ParentTLSSingle {
|
||||
conf, err = utils.SingleTlsConfig(s.cfg.CaCertBytes)
|
||||
} else {
|
||||
conf, err = utils.TlsConfig(s.cfg.CertBytes, s.cfg.KeyBytes, s.cfg.CaCertBytes)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var _c net.Conn
|
||||
_c, err = s.jumper.Dial(address, 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(address, s.cfg.KCP)
|
||||
} else {
|
||||
if s.jumper == nil {
|
||||
conn, err = utils.ConnectHost(address, *s.cfg.Timeout)
|
||||
} else {
|
||||
conn, err = s.jumper.Dial(address, time.Millisecond*time.Duration(*s.cfg.Timeout))
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
if *s.cfg.ParentCompress {
|
||||
@ -662,9 +761,9 @@ func (s *SPS) GetParentConn(address string) (conn net.Conn, err error) {
|
||||
}
|
||||
return
|
||||
}
|
||||
func (s *SPS) HandshakeSocksParent(outconn *net.Conn, network, dstAddr string, auth socks.Auth, fromSS bool) (client *socks.ClientConn, err error) {
|
||||
if *s.cfg.ParentAuth != "" {
|
||||
a := strings.Split(*s.cfg.ParentAuth, ":")
|
||||
func (s *SPS) HandshakeSocksParent(parentAuth string, outconn *net.Conn, network, dstAddr string, auth socks.Auth, fromSS bool) (client *socks.ClientConn, err error) {
|
||||
if parentAuth != "" {
|
||||
a := strings.Split(parentAuth, ":")
|
||||
if len(a) != 2 {
|
||||
err = fmt.Errorf("parent auth data format error")
|
||||
return
|
||||
@ -688,7 +787,9 @@ func (s *SPS) ParentUDPKey() (key []byte) {
|
||||
return []byte(v)[:24]
|
||||
}
|
||||
case "tls":
|
||||
if s.cfg.KeyBytes != nil {
|
||||
return s.cfg.KeyBytes[:24]
|
||||
}
|
||||
case "kcp":
|
||||
v := fmt.Sprintf("%x", md5.Sum([]byte(*s.cfg.KCP.Key)))
|
||||
return []byte(v)[:24]
|
||||
|
||||
@ -27,9 +27,9 @@ func (s *SPS) RunSSUDP(addr string) (err error) {
|
||||
s.log.Printf("udp local->out io copy crashed:\n%s\n%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
for {
|
||||
buf := utils.LeakyBuffer.Get()
|
||||
defer utils.LeakyBuffer.Put(buf)
|
||||
for {
|
||||
n, srcAddr, err := listener.ReadFrom(buf)
|
||||
if err != nil {
|
||||
s.log.Printf("read from client error %s", err)
|
||||
@ -88,7 +88,7 @@ func (s *SPS) RunSSUDP(addr string) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
client, err := s.HandshakeSocksParent(&outconn, "udp", socksPacket.Addr(), socks.Auth{}, true)
|
||||
client, err := s.HandshakeSocksParent(s.getParentAuth(lbAddr), &outconn, "udp", socksPacket.Addr(), socks.Auth{}, true)
|
||||
if err != nil {
|
||||
clean("handshake fail", fmt.Sprintf("%s", err))
|
||||
return
|
||||
|
||||
@ -9,8 +9,9 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/snail007/goproxy/core/cs/server"
|
||||
"github.com/snail007/goproxy/core/lib/kcpcfg"
|
||||
"github.com/snail007/goproxy/services"
|
||||
"github.com/snail007/goproxy/services/kcpcfg"
|
||||
"github.com/snail007/goproxy/utils"
|
||||
"github.com/snail007/goproxy/utils/jumper"
|
||||
"github.com/snail007/goproxy/utils/mapx"
|
||||
@ -43,7 +44,7 @@ type UDPConnItem struct {
|
||||
}
|
||||
type TCP struct {
|
||||
cfg TCPArgs
|
||||
sc *utils.ServerChannel
|
||||
sc *server.ServerChannel
|
||||
isStop bool
|
||||
userConns mapx.ConcurrentMap
|
||||
log *logger.Logger
|
||||
@ -99,7 +100,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.cfg = TCPArgs{}
|
||||
s.jumper = nil
|
||||
@ -131,12 +132,12 @@ func (s *TCP) Start(args interface{}, log *logger.Logger) (err error) {
|
||||
s.log.Printf("use %s parent %v", *s.cfg.ParentType, *s.cfg.Parent)
|
||||
host, port, _ := net.SplitHostPort(*s.cfg.Local)
|
||||
p, _ := strconv.Atoi(port)
|
||||
sc := utils.NewServerChannel(host, p, s.log)
|
||||
sc := server.NewServerChannel(host, p, s.log)
|
||||
|
||||
if *s.cfg.LocalType == "tcp" {
|
||||
err = sc.ListenTCP(s.callback)
|
||||
} else if *s.cfg.LocalType == "tls" {
|
||||
err = sc.ListenTls(s.cfg.CertBytes, s.cfg.KeyBytes, nil, s.callback)
|
||||
err = sc.ListenTLS(s.cfg.CertBytes, s.cfg.KeyBytes, nil, s.callback)
|
||||
} else if *s.cfg.LocalType == "kcp" {
|
||||
err = sc.ListenKCP(s.cfg.KCP, s.callback, s.log)
|
||||
}
|
||||
@ -160,11 +161,7 @@ func (s *TCP) callback(inConn net.Conn) {
|
||||
var err error
|
||||
lbAddr := ""
|
||||
switch *s.cfg.ParentType {
|
||||
case "kcp":
|
||||
fallthrough
|
||||
case "tcp":
|
||||
fallthrough
|
||||
case "tls":
|
||||
case "kcp", "tcp", "tls":
|
||||
err = s.OutToTCP(&inConn)
|
||||
case "udp":
|
||||
s.OutToUDP(&inConn)
|
||||
@ -208,8 +205,8 @@ func (s *TCP) OutToUDP(inConn *net.Conn) (err error) {
|
||||
srcAddr := ""
|
||||
defer func() {
|
||||
if item != nil {
|
||||
(*(*item).conn).Close()
|
||||
(*item).udpConn.Close()
|
||||
(*item.conn).Close()
|
||||
item.udpConn.Close()
|
||||
s.udpConns.Remove(srcAddr)
|
||||
(*inConn).Close()
|
||||
}
|
||||
@ -252,15 +249,15 @@ func (s *TCP) OutToUDP(inConn *net.Conn) (err error) {
|
||||
} else {
|
||||
item = v.(*UDPConnItem)
|
||||
}
|
||||
(*item).touchtime = time.Now().Unix()
|
||||
go (*item).udpConn.Write(body)
|
||||
item.touchtime = time.Now().Unix()
|
||||
go item.udpConn.Write(body)
|
||||
}
|
||||
}
|
||||
func (s *TCP) UDPRevecive(key string) {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
s.log.Printf("udp conn %s connected", key)
|
||||
@ -290,7 +287,7 @@ func (s *TCP) UDPRevecive(key string) {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
(*cui.conn).SetWriteDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout)))
|
||||
@ -309,7 +306,7 @@ func (s *TCP) UDPGCDeamon() {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
if s.isStop {
|
||||
|
||||
@ -10,6 +10,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/snail007/goproxy/core/cs/server"
|
||||
"github.com/snail007/goproxy/services"
|
||||
"github.com/snail007/goproxy/utils"
|
||||
"github.com/snail007/goproxy/utils/mapx"
|
||||
@ -71,7 +72,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.cfg = TunnelBridgeArgs{}
|
||||
s.clientControlConns = nil
|
||||
@ -98,9 +99,9 @@ func (s *TunnelBridge) Start(args interface{}, log *logger.Logger) (err error) {
|
||||
}
|
||||
host, port, _ := net.SplitHostPort(*s.cfg.Local)
|
||||
p, _ := strconv.Atoi(port)
|
||||
sc := utils.NewServerChannel(host, p, s.log)
|
||||
sc := server.NewServerChannel(host, p, s.log)
|
||||
|
||||
err = sc.ListenTls(s.cfg.CertBytes, s.cfg.KeyBytes, nil, s.callback)
|
||||
err = sc.ListenTLS(s.cfg.CertBytes, s.cfg.KeyBytes, nil, s.callback)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@ -95,7 +95,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.cfg = TunnelClientArgs{}
|
||||
s.ctrlConn = nil
|
||||
@ -159,7 +159,7 @@ func (s *TunnelClient) Start(args interface{}, log *logger.Logger) (err error) {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:\n%s",e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
s.ServeUDP(localAddr, ID, serverID)
|
||||
@ -168,7 +168,7 @@ func (s *TunnelClient) Start(args interface{}, log *logger.Logger) (err error) {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:\n%s",e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
s.ServeConn(localAddr, ID, serverID)
|
||||
@ -324,7 +324,7 @@ func (s *TunnelClient) ServeUDP(localAddr, ID, serverID string) {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:\n%s",e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
(*item).udpConn.Write(body)
|
||||
@ -335,7 +335,7 @@ func (s *TunnelClient) UDPRevecive(key, ID string) {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:\n%s",e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
s.log.Printf("udp conn %s connected", ID)
|
||||
@ -365,7 +365,7 @@ func (s *TunnelClient) UDPRevecive(key, ID string) {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:\n%s",e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
(*cui.conn).SetWriteDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout)))
|
||||
@ -384,7 +384,7 @@ func (s *TunnelClient) UDPGCDeamon() {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:\n%s",e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
if s.isStop {
|
||||
|
||||
@ -12,6 +12,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/snail007/goproxy/core/cs/server"
|
||||
"github.com/snail007/goproxy/services"
|
||||
"github.com/snail007/goproxy/utils"
|
||||
"github.com/snail007/goproxy/utils/jumper"
|
||||
@ -38,7 +39,7 @@ type TunnelServerArgs struct {
|
||||
}
|
||||
type TunnelServer struct {
|
||||
cfg TunnelServerArgs
|
||||
sc utils.ServerChannel
|
||||
sc server.ServerChannel
|
||||
isStop bool
|
||||
udpConn *net.Conn
|
||||
userConns mapx.ConcurrentMap
|
||||
@ -175,12 +176,12 @@ 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.cfg = TunnelServerArgs{}
|
||||
s.jumper = nil
|
||||
s.log = nil
|
||||
s.sc = utils.ServerChannel{}
|
||||
s.sc = server.ServerChannel{}
|
||||
s.udpConn = nil
|
||||
s.udpConns = nil
|
||||
s.userConns = nil
|
||||
@ -233,7 +234,7 @@ func (s *TunnelServer) Start(args interface{}, log *logger.Logger) (err error) {
|
||||
}
|
||||
host, port, _ := net.SplitHostPort(*s.cfg.Local)
|
||||
p, _ := strconv.Atoi(port)
|
||||
s.sc = utils.NewServerChannel(host, p, s.log)
|
||||
s.sc = server.NewServerChannel(host, p, s.log)
|
||||
if *s.cfg.IsUDP {
|
||||
err = s.sc.ListenUDP(func(listener *net.UDPConn, packet []byte, localAddr, srcAddr *net.UDPAddr) {
|
||||
s.UDPSend(packet, localAddr, srcAddr)
|
||||
@ -368,7 +369,7 @@ func (s *TunnelServer) UDPGCDeamon() {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:\n%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
if s.isStop {
|
||||
@ -439,7 +440,7 @@ func (s *TunnelServer) UDPRevecive(key, ID string) {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:\n%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
s.log.Printf("udp conn %s connected", ID)
|
||||
@ -472,7 +473,7 @@ func (s *TunnelServer) UDPRevecive(key, ID string) {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:\n%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
s.sc.UDPListener.WriteToUDP(body, uc.srcAddr)
|
||||
|
||||
@ -11,6 +11,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/snail007/goproxy/core/cs/server"
|
||||
"github.com/snail007/goproxy/services"
|
||||
"github.com/snail007/goproxy/utils"
|
||||
"github.com/snail007/goproxy/utils/mapx"
|
||||
@ -30,7 +31,7 @@ type UDPArgs struct {
|
||||
type UDP struct {
|
||||
p mapx.ConcurrentMap
|
||||
cfg UDPArgs
|
||||
sc *utils.ServerChannel
|
||||
sc *server.ServerChannel
|
||||
isStop bool
|
||||
log *logger.Logger
|
||||
outUDPConnCtxMap mapx.ConcurrentMap
|
||||
@ -93,7 +94,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.cfg = UDPArgs{}
|
||||
s.log = nil
|
||||
@ -121,7 +122,7 @@ func (s *UDP) Start(args interface{}, log *logger.Logger) (err error) {
|
||||
}
|
||||
host, port, _ := net.SplitHostPort(*s.cfg.Local)
|
||||
p, _ := strconv.Atoi(port)
|
||||
sc := utils.NewServerChannel(host, p, s.log)
|
||||
sc := server.NewServerChannel(host, p, s.log)
|
||||
s.sc = &sc
|
||||
err = sc.ListenUDP(s.callback)
|
||||
if err != nil {
|
||||
@ -141,9 +142,7 @@ func (s *UDP) callback(listener *net.UDPConn, packet []byte, localAddr, srcAddr
|
||||
}
|
||||
}()
|
||||
switch *s.cfg.ParentType {
|
||||
case "tcp":
|
||||
fallthrough
|
||||
case "tls":
|
||||
case "tcp", "tls":
|
||||
s.OutToTCP(packet, localAddr, srcAddr)
|
||||
case "udp":
|
||||
s.OutToUDP(packet, localAddr, srcAddr)
|
||||
@ -175,7 +174,7 @@ func (s *UDP) OutToUDPGCDeamon() {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:\n%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
if s.isStop {
|
||||
@ -217,7 +216,7 @@ func (s *UDP) OutToUDP(packet []byte, localAddr, srcAddr *net.UDPAddr) {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:\n%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
s.log.Printf("udp conn %s <--> %s connected", srcAddr.String(), localAddr.String())
|
||||
@ -239,7 +238,7 @@ func (s *UDP) OutToUDP(packet []byte, localAddr, srcAddr *net.UDPAddr) {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:\n%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
(*(s.sc).UDPListener).SetWriteDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout)))
|
||||
@ -276,7 +275,7 @@ func (s *UDP) UDPGCDeamon() {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:\n%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
if s.isStop {
|
||||
@ -353,7 +352,7 @@ func (s *UDP) UDPRevecive(key string) {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:\n%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
s.log.Printf("udp conn %s connected", key)
|
||||
@ -367,7 +366,7 @@ func (s *UDP) UDPRevecive(key string) {
|
||||
}()
|
||||
v, ok := s.udpConns.Get(key)
|
||||
if !ok {
|
||||
s.log.Printf("[warn] udp conn not exists for %s, connid : %s", key)
|
||||
s.log.Printf("[warn] udp conn not exists for %s", key)
|
||||
return
|
||||
}
|
||||
uc = v.(*UDPConnItem)
|
||||
@ -386,7 +385,7 @@ func (s *UDP) UDPRevecive(key string) {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:\n%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
s.sc.UDPListener.WriteToUDP(body, uc.srcAddr)
|
||||
|
||||
38
utils/crypt/misc.go
Normal file
38
utils/crypt/misc.go
Normal file
@ -0,0 +1,38 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
)
|
||||
|
||||
type CryptTool struct{}
|
||||
|
||||
var CryptTools = NewCryptTool()
|
||||
|
||||
func NewCryptTool() *CryptTool {
|
||||
return &CryptTool{}
|
||||
}
|
||||
|
||||
func (encrypt *CryptTool) Base64Encode(str string) string {
|
||||
return string([]byte(base64.StdEncoding.EncodeToString([]byte(str))))
|
||||
}
|
||||
|
||||
func (encrypt *CryptTool) Base64EncodeBytes(bytes []byte) []byte {
|
||||
return []byte(base64.StdEncoding.EncodeToString(bytes))
|
||||
}
|
||||
|
||||
func (encrypt *CryptTool) Base64Decode(str string) (string, error) {
|
||||
by, err := base64.StdEncoding.DecodeString(str)
|
||||
return string(by), err
|
||||
}
|
||||
|
||||
func (encrypt *CryptTool) Base64DecodeBytes(str string) ([]byte, error) {
|
||||
return base64.StdEncoding.DecodeString(str)
|
||||
}
|
||||
|
||||
func (encrypt *CryptTool) MD5(str string) string {
|
||||
hash := md5.New()
|
||||
hash.Write([]byte(str))
|
||||
return hex.EncodeToString(hash.Sum(nil))
|
||||
}
|
||||
@ -20,10 +20,9 @@ import (
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/snail007/goproxy/services/kcpcfg"
|
||||
"github.com/snail007/goproxy/core/lib/kcpcfg"
|
||||
"github.com/snail007/goproxy/utils/lb"
|
||||
|
||||
"golang.org/x/crypto/pbkdf2"
|
||||
@ -123,12 +122,55 @@ func ioCopy(dst io.ReadWriter, src io.ReadWriter) (err error) {
|
||||
}
|
||||
}
|
||||
}
|
||||
func SingleTlsConnectHost(host string, timeout int, caCertBytes []byte) (conn tls.Conn, err error) {
|
||||
h := strings.Split(host, ":")
|
||||
port, _ := strconv.Atoi(h[1])
|
||||
return SingleTlsConnect(h[0], port, timeout, caCertBytes)
|
||||
}
|
||||
func SingleTlsConnect(host string, port, timeout int, caCertBytes []byte) (conn tls.Conn, err error) {
|
||||
conf, err := getRequestSingleTlsConfig(caCertBytes)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
_conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", host, port), time.Duration(timeout)*time.Millisecond)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return *tls.Client(_conn, conf), err
|
||||
}
|
||||
func SingleTlsConfig(caCertBytes []byte) (conf *tls.Config, err error) {
|
||||
return getRequestSingleTlsConfig(caCertBytes)
|
||||
}
|
||||
func getRequestSingleTlsConfig(caCertBytes []byte) (conf *tls.Config, err error) {
|
||||
conf = &tls.Config{InsecureSkipVerify: true}
|
||||
serverCertPool := x509.NewCertPool()
|
||||
if caCertBytes != nil {
|
||||
ok := serverCertPool.AppendCertsFromPEM(caCertBytes)
|
||||
if !ok {
|
||||
err = errors.New("failed to parse root certificate")
|
||||
}
|
||||
conf.RootCAs = serverCertPool
|
||||
conf.VerifyPeerCertificate = func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
|
||||
opts := x509.VerifyOptions{
|
||||
Roots: serverCertPool,
|
||||
}
|
||||
for _, rawCert := range rawCerts {
|
||||
cert, _ := x509.ParseCertificate(rawCert)
|
||||
_, err := cert.Verify(opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
func TlsConnectHost(host string, timeout int, certBytes, keyBytes, caCertBytes []byte) (conn tls.Conn, err error) {
|
||||
h := strings.Split(host, ":")
|
||||
port, _ := strconv.Atoi(h[1])
|
||||
return TlsConnect(h[0], port, timeout, certBytes, keyBytes, caCertBytes)
|
||||
}
|
||||
|
||||
func TlsConnect(host string, port, timeout int, certBytes, keyBytes, caCertBytes []byte) (conn tls.Conn, err error) {
|
||||
conf, err := getRequestTlsConfig(certBytes, keyBytes, caCertBytes)
|
||||
if err != nil {
|
||||
@ -245,98 +287,6 @@ func CloseConn(conn *net.Conn) {
|
||||
(*conn).Close()
|
||||
}
|
||||
}
|
||||
func Keygen() (err error) {
|
||||
CList := []string{"AD", "AE", "AF", "AG", "AI", "AL", "AM", "AO", "AR", "AT", "AU", "AZ", "BB", "BD", "BE", "BF", "BG", "BH", "BI", "BJ", "BL", "BM", "BN", "BO", "BR", "BS", "BW", "BY", "BZ", "CA", "CF", "CG", "CH", "CK", "CL", "CM", "CN", "CO", "CR", "CS", "CU", "CY", "CZ", "DE", "DJ", "DK", "DO", "DZ", "EC", "EE", "EG", "ES", "ET", "FI", "FJ", "FR", "GA", "GB", "GD", "GE", "GF", "GH", "GI", "GM", "GN", "GR", "GT", "GU", "GY", "HK", "HN", "HT", "HU", "ID", "IE", "IL", "IN", "IQ", "IR", "IS", "IT", "JM", "JO", "JP", "KE", "KG", "KH", "KP", "KR", "KT", "KW", "KZ", "LA", "LB", "LC", "LI", "LK", "LR", "LS", "LT", "LU", "LV", "LY", "MA", "MC", "MD", "MG", "ML", "MM", "MN", "MO", "MS", "MT", "MU", "MV", "MW", "MX", "MY", "MZ", "NA", "NE", "NG", "NI", "NL", "NO", "NP", "NR", "NZ", "OM", "PA", "PE", "PF", "PG", "PH", "PK", "PL", "PR", "PT", "PY", "QA", "RO", "RU", "SA", "SB", "SC", "SD", "SE", "SG", "SI", "SK", "SL", "SM", "SN", "SO", "SR", "ST", "SV", "SY", "SZ", "TD", "TG", "TH", "TJ", "TM", "TN", "TO", "TR", "TT", "TW", "TZ", "UA", "UG", "US", "UY", "UZ", "VC", "VE", "VN", "YE", "YU", "ZA", "ZM", "ZR", "ZW"}
|
||||
domainSubfixList := []string{".com", ".edu", ".gov", ".int", ".mil", ".net", ".org", ".biz", ".info", ".pro", ".name", ".museum", ".coop", ".aero", ".xxx", ".idv", ".ac", ".ad", ".ae", ".af", ".ag", ".ai", ".al", ".am", ".an", ".ao", ".aq", ".ar", ".as", ".at", ".au", ".aw", ".az", ".ba", ".bb", ".bd", ".be", ".bf", ".bg", ".bh", ".bi", ".bj", ".bm", ".bn", ".bo", ".br", ".bs", ".bt", ".bv", ".bw", ".by", ".bz", ".ca", ".cc", ".cd", ".cf", ".cg", ".ch", ".ci", ".ck", ".cl", ".cm", ".cn", ".co", ".cr", ".cu", ".cv", ".cx", ".cy", ".cz", ".de", ".dj", ".dk", ".dm", ".do", ".dz", ".ec", ".ee", ".eg", ".eh", ".er", ".es", ".et", ".eu", ".fi", ".fj", ".fk", ".fm", ".fo", ".fr", ".ga", ".gd", ".ge", ".gf", ".gg", ".gh", ".gi", ".gl", ".gm", ".gn", ".gp", ".gq", ".gr", ".gs", ".gt", ".gu", ".gw", ".gy", ".hk", ".hm", ".hn", ".hr", ".ht", ".hu", ".id", ".ie", ".il", ".im", ".in", ".io", ".iq", ".ir", ".is", ".it", ".je", ".jm", ".jo", ".jp", ".ke", ".kg", ".kh", ".ki", ".km", ".kn", ".kp", ".kr", ".kw", ".ky", ".kz", ".la", ".lb", ".lc", ".li", ".lk", ".lr", ".ls", ".lt", ".lu", ".lv", ".ly", ".ma", ".mc", ".md", ".mg", ".mh", ".mk", ".ml", ".mm", ".mn", ".mo", ".mp", ".mq", ".mr", ".ms", ".mt", ".mu", ".mv", ".mw", ".mx", ".my", ".mz", ".na", ".nc", ".ne", ".nf", ".ng", ".ni", ".nl", ".no", ".np", ".nr", ".nu", ".nz", ".om", ".pa", ".pe", ".pf", ".pg", ".ph", ".pk", ".pl", ".pm", ".pn", ".pr", ".ps", ".pt", ".pw", ".py", ".qa", ".re", ".ro", ".ru", ".rw", ".sa", ".sb", ".sc", ".sd", ".se", ".sg", ".sh", ".si", ".sj", ".sk", ".sl", ".sm", ".sn", ".so", ".sr", ".st", ".sv", ".sy", ".sz", ".tc", ".td", ".tf", ".tg", ".th", ".tj", ".tk", ".tl", ".tm", ".tn", ".to", ".tp", ".tr", ".tt", ".tv", ".tw", ".tz", ".ua", ".ug", ".uk", ".um", ".us", ".uy", ".uz", ".va", ".vc", ".ve", ".vg", ".vi", ".vn", ".vu", ".wf", ".ws", ".ye", ".yt", ".yu", ".yr", ".za", ".zm", ".zw"}
|
||||
C := CList[int(RandInt(4))%len(CList)]
|
||||
ST := RandString(int(RandInt(4) % 10))
|
||||
O := RandString(int(RandInt(4) % 10))
|
||||
CN := strings.ToLower(RandString(int(RandInt(4)%10)) + domainSubfixList[int(RandInt(4))%len(domainSubfixList)])
|
||||
//log.Printf("C: %s, ST: %s, O: %s, CN: %s", C, ST, O, CN)
|
||||
var out []byte
|
||||
if len(os.Args) == 3 && os.Args[2] == "ca" {
|
||||
cmd := exec.Command("sh", "-c", "openssl genrsa -out ca.key 2048")
|
||||
out, err = cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
logger.Printf("err:%s", err)
|
||||
return
|
||||
}
|
||||
fmt.Println(string(out))
|
||||
|
||||
cmdStr := fmt.Sprintf("openssl req -new -key ca.key -x509 -days 36500 -out ca.crt -subj /C=%s/ST=%s/O=%s/CN=%s", C, ST, O, "*."+CN)
|
||||
cmd = exec.Command("sh", "-c", cmdStr)
|
||||
out, err = cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
logger.Printf("err:%s", err)
|
||||
return
|
||||
}
|
||||
fmt.Println(string(out))
|
||||
} else if len(os.Args) == 5 && os.Args[2] == "ca" && os.Args[3] != "" && os.Args[4] != "" {
|
||||
certBytes, _ := ioutil.ReadFile("ca.crt")
|
||||
block, _ := pem.Decode(certBytes)
|
||||
if block == nil || certBytes == nil {
|
||||
panic("failed to parse ca certificate PEM")
|
||||
}
|
||||
x509Cert, _ := x509.ParseCertificate(block.Bytes)
|
||||
if x509Cert == nil {
|
||||
panic("failed to parse block")
|
||||
}
|
||||
name := os.Args[3]
|
||||
days := os.Args[4]
|
||||
cmd := exec.Command("sh", "-c", "openssl genrsa -out "+name+".key 2048")
|
||||
out, err = cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
logger.Printf("err:%s", err)
|
||||
return
|
||||
}
|
||||
fmt.Println(string(out))
|
||||
|
||||
cmdStr := fmt.Sprintf("openssl req -new -key %s.key -out %s.csr -subj /C=%s/ST=%s/O=%s/CN=%s", name, name, C, ST, O, CN)
|
||||
fmt.Printf("%s", cmdStr)
|
||||
cmd = exec.Command("sh", "-c", cmdStr)
|
||||
out, err = cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
logger.Printf("err:%s", err)
|
||||
return
|
||||
}
|
||||
fmt.Println(string(out))
|
||||
|
||||
cmdStr = fmt.Sprintf("openssl x509 -req -days %s -in %s.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out %s.crt", days, name, name)
|
||||
fmt.Printf("%s", cmdStr)
|
||||
cmd = exec.Command("sh", "-c", cmdStr)
|
||||
out, err = cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
logger.Printf("err:%s", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(string(out))
|
||||
} else if len(os.Args) == 3 && os.Args[2] == "usage" {
|
||||
fmt.Println(`proxy keygen //generate proxy.crt and proxy.key
|
||||
proxy keygen ca //generate ca.crt and ca.key
|
||||
proxy keygen ca client0 30 //generate client0.crt client0.key and use ca.crt sign it with 30 days
|
||||
`)
|
||||
} else if len(os.Args) == 2 {
|
||||
cmd := exec.Command("sh", "-c", "openssl genrsa -out proxy.key 2048")
|
||||
out, err = cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
logger.Printf("err:%s", err)
|
||||
return
|
||||
}
|
||||
fmt.Println(string(out))
|
||||
|
||||
cmdStr := fmt.Sprintf("openssl req -new -key proxy.key -x509 -days 36500 -out proxy.crt -subj /C=%s/ST=%s/O=%s/CN=%s", C, ST, O, CN)
|
||||
cmd = exec.Command("sh", "-c", cmdStr)
|
||||
out, err = cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
logger.Printf("err:%s", err)
|
||||
return
|
||||
}
|
||||
fmt.Println(string(out))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
var allInterfaceAddrCache []net.IP
|
||||
|
||||
@ -464,11 +414,20 @@ func RandInt(strLen int) int64 {
|
||||
return i
|
||||
}
|
||||
func ReadBytes(r io.Reader) (data []byte, err error) {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
err = fmt.Errorf("read bytes fail ,err : %s", e)
|
||||
}
|
||||
}()
|
||||
var len uint64
|
||||
err = binary.Read(r, binary.LittleEndian, &len)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if len == 0 || len > ^uint64(0) {
|
||||
err = fmt.Errorf("data len out of range, %d", len)
|
||||
return
|
||||
}
|
||||
var n int
|
||||
data = make([]byte, len)
|
||||
n, err = r.Read(data)
|
||||
|
||||
@ -102,6 +102,19 @@ func (s *conn) Write(p []byte) (int, error) {
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
func (s *conn) Close() error {
|
||||
if s.Conn != nil {
|
||||
e := s.Conn.Close()
|
||||
s.Conn = nil
|
||||
s.r = nil
|
||||
s.w = nil
|
||||
s.readLimiter = nil
|
||||
s.writeLimiter = nil
|
||||
s.ctx = nil
|
||||
return e
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewReader returns a reader that implements io.Reader with rate limiting.
|
||||
func NewReader(r io.Reader) *Reader {
|
||||
|
||||
@ -24,8 +24,9 @@ func (s socks5Dialer) Dial(network, addr string) (net.Conn, error) {
|
||||
}
|
||||
|
||||
func New(proxyURL string, timeout time.Duration) (j Jumper, err error) {
|
||||
u, err := url.Parse(proxyURL)
|
||||
if err != nil {
|
||||
u, e := url.Parse(proxyURL)
|
||||
if e != nil {
|
||||
err = e
|
||||
return
|
||||
}
|
||||
j = Jumper{
|
||||
@ -34,7 +35,7 @@ func New(proxyURL string, timeout time.Duration) (j Jumper, err error) {
|
||||
}
|
||||
return
|
||||
}
|
||||
func (j *Jumper) Dial(address string, timeout time.Duration) (conn net.Conn, err error) {
|
||||
func (j *Jumper) Dial(address string, timeout time.Duration) (net.Conn, error) {
|
||||
switch j.proxyURL.Scheme {
|
||||
case "https":
|
||||
return j.dialHTTPS(address, timeout)
|
||||
@ -70,10 +71,10 @@ func (j *Jumper) dialHTTPS(address string, timeout time.Duration) (conn net.Conn
|
||||
}
|
||||
reply := make([]byte, 1024)
|
||||
conn.SetDeadline(time.Now().Add(timeout))
|
||||
n, err := conn.Read(reply)
|
||||
n, e := conn.Read(reply)
|
||||
conn.SetDeadline(time.Time{})
|
||||
if err != nil {
|
||||
err = fmt.Errorf("error read reply from proxy: %s", err)
|
||||
if e != nil {
|
||||
err = fmt.Errorf("error read reply from proxy: %s", e)
|
||||
conn.Close()
|
||||
conn = nil
|
||||
return
|
||||
@ -94,9 +95,9 @@ func (j *Jumper) dialSOCKS5(address string, timeout time.Duration) (conn net.Con
|
||||
} 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)
|
||||
dialSocksProxy, e := proxy.SOCKS5("tcp", j.proxyURL.Host, auth, socks5Dialer{timeout: timeout})
|
||||
if e != nil {
|
||||
err = fmt.Errorf("error connecting to proxy: %s", e)
|
||||
return
|
||||
}
|
||||
return dialSocksProxy.Dial("tcp", address)
|
||||
|
||||
@ -116,7 +116,7 @@ func (b *Backend) startMuxHeartCheck() {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:\n%s",e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
for {
|
||||
@ -151,7 +151,7 @@ func (b *Backend) startTCPHeartCheck() {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:\n%s",e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
for {
|
||||
|
||||
@ -36,6 +36,7 @@ type Group struct {
|
||||
lock *sync.Mutex
|
||||
last *Backend
|
||||
debug bool
|
||||
bks []*Backend
|
||||
}
|
||||
|
||||
func NewGroup(selectType int, configs BackendsConfig, dr *dnsx.DomainResolver, log *log.Logger, debug bool) Group {
|
||||
@ -68,9 +69,14 @@ func NewGroup(selectType int, configs BackendsConfig, dr *dnsx.DomainResolver, l
|
||||
dr: dr,
|
||||
lock: &sync.Mutex{},
|
||||
debug: debug,
|
||||
bks: bks,
|
||||
}
|
||||
}
|
||||
func (g *Group) Select(srcAddr string, onlyHa bool) (addr string) {
|
||||
addr=""
|
||||
if len(g.bks) == 1 {
|
||||
return g.bks[0].Address
|
||||
}
|
||||
if onlyHa {
|
||||
g.lock.Lock()
|
||||
defer g.lock.Unlock()
|
||||
@ -121,6 +127,7 @@ func (g *Group) Reset(addrs []string) {
|
||||
configs = append(configs, &c)
|
||||
}
|
||||
(*g.selector).Reset(configs, g.dr, g.log)
|
||||
g.bks = (*g.selector).Backends()
|
||||
}
|
||||
func (g *Group) Backends() []*Backend {
|
||||
return (*g.selector).Backends()
|
||||
|
||||
@ -152,14 +152,7 @@ type Tuple struct {
|
||||
func (m ConcurrentMap) Iter() <-chan Tuple {
|
||||
chans := snapshot(m)
|
||||
ch := make(chan Tuple)
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
fanIn(chans, ch)
|
||||
}()
|
||||
go fanIn(chans, ch)
|
||||
return ch
|
||||
}
|
||||
|
||||
@ -171,14 +164,7 @@ func (m ConcurrentMap) IterBuffered() <-chan Tuple {
|
||||
total += cap(c)
|
||||
}
|
||||
ch := make(chan Tuple, total)
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
fanIn(chans, ch)
|
||||
}()
|
||||
go fanIn(chans, ch)
|
||||
return ch
|
||||
}
|
||||
|
||||
@ -193,11 +179,6 @@ func snapshot(m ConcurrentMap) (chans []chan Tuple) {
|
||||
// Foreach shard.
|
||||
for index, shard := range m {
|
||||
go func(index int, shard *ConcurrentMapShared) {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
// Foreach key, value pair.
|
||||
shard.RLock()
|
||||
chans[index] = make(chan Tuple, len(shard.items))
|
||||
@ -215,22 +196,25 @@ func snapshot(m ConcurrentMap) (chans []chan Tuple) {
|
||||
|
||||
// fanIn reads elements from channels `chans` into channel `out`
|
||||
func fanIn(chans []chan Tuple, out chan Tuple) {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed, err: %s\nstack:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(len(chans))
|
||||
for _, ch := range chans {
|
||||
go func() {
|
||||
go func(ch chan Tuple) {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
func(ch chan Tuple) {
|
||||
for t := range ch {
|
||||
out <- t
|
||||
}
|
||||
wg.Done()
|
||||
}(ch)
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
close(out)
|
||||
@ -274,20 +258,19 @@ func (m ConcurrentMap) Keys() []string {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
// Foreach shard.
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(SHARD_COUNT)
|
||||
for _, shard := range m {
|
||||
go func() {
|
||||
go func(shard *ConcurrentMapShared) {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
func(shard *ConcurrentMapShared) {
|
||||
// Foreach key, value pair.
|
||||
shard.RLock()
|
||||
for key := range shard.items {
|
||||
@ -296,7 +279,6 @@ func (m ConcurrentMap) Keys() []string {
|
||||
shard.RUnlock()
|
||||
wg.Done()
|
||||
}(shard)
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
close(ch)
|
||||
|
||||
@ -1,230 +0,0 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"fmt"
|
||||
logger "log"
|
||||
"net"
|
||||
"runtime/debug"
|
||||
"strconv"
|
||||
|
||||
"github.com/snail007/goproxy/services/kcpcfg"
|
||||
|
||||
kcp "github.com/xtaci/kcp-go"
|
||||
)
|
||||
|
||||
type ServerChannel struct {
|
||||
ip string
|
||||
port int
|
||||
Listener *net.Listener
|
||||
UDPListener *net.UDPConn
|
||||
errAcceptHandler func(err error)
|
||||
log *logger.Logger
|
||||
}
|
||||
|
||||
func NewServerChannel(ip string, port int, log *logger.Logger) ServerChannel {
|
||||
return ServerChannel{
|
||||
ip: ip,
|
||||
port: port,
|
||||
log: log,
|
||||
errAcceptHandler: func(err error) {
|
||||
log.Printf("accept error , ERR:%s", err)
|
||||
},
|
||||
}
|
||||
}
|
||||
func NewServerChannelHost(host string, log *logger.Logger) ServerChannel {
|
||||
h, port, _ := net.SplitHostPort(host)
|
||||
p, _ := strconv.Atoi(port)
|
||||
return ServerChannel{
|
||||
ip: h,
|
||||
port: p,
|
||||
log: log,
|
||||
errAcceptHandler: func(err error) {
|
||||
log.Printf("accept error , ERR:%s", err)
|
||||
},
|
||||
}
|
||||
}
|
||||
func (sc *ServerChannel) SetErrAcceptHandler(fn func(err error)) {
|
||||
sc.errAcceptHandler = fn
|
||||
}
|
||||
func (sc *ServerChannel) ListenTls(certBytes, keyBytes, caCertBytes []byte, fn func(conn net.Conn)) (err error) {
|
||||
sc.Listener, err = sc.listenTls(sc.ip, sc.port, certBytes, keyBytes, caCertBytes)
|
||||
if err == nil {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
sc.log.Printf("ListenTls crashed , err : %s , \ntrace:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
for {
|
||||
var conn net.Conn
|
||||
conn, err = (*sc.Listener).Accept()
|
||||
if err == nil {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
sc.log.Printf("tls connection handler crashed , err : %s , \ntrace:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
fn(conn)
|
||||
}()
|
||||
} else {
|
||||
sc.errAcceptHandler(err)
|
||||
(*sc.Listener).Close()
|
||||
break
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
return
|
||||
}
|
||||
func (sc *ServerChannel) listenTls(ip string, port int, certBytes, keyBytes, caCertBytes []byte) (ln *net.Listener, err error) {
|
||||
|
||||
var cert tls.Certificate
|
||||
cert, err = tls.X509KeyPair(certBytes, keyBytes)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
clientCertPool := x509.NewCertPool()
|
||||
caBytes := certBytes
|
||||
if caCertBytes != nil {
|
||||
caBytes = caCertBytes
|
||||
}
|
||||
ok := clientCertPool.AppendCertsFromPEM(caBytes)
|
||||
if !ok {
|
||||
err = errors.New("failed to parse root certificate")
|
||||
}
|
||||
config := &tls.Config{
|
||||
ClientCAs: clientCertPool,
|
||||
Certificates: []tls.Certificate{cert},
|
||||
ClientAuth: tls.RequireAndVerifyClientCert,
|
||||
}
|
||||
_ln, err := tls.Listen("tcp", fmt.Sprintf("%s:%d", ip, port), config)
|
||||
if err == nil {
|
||||
ln = &_ln
|
||||
}
|
||||
return
|
||||
}
|
||||
func (sc *ServerChannel) ListenTCP(fn func(conn net.Conn)) (err error) {
|
||||
var l net.Listener
|
||||
l, err = net.Listen("tcp", fmt.Sprintf("%s:%d", sc.ip, sc.port))
|
||||
if err == nil {
|
||||
sc.Listener = &l
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
sc.log.Printf("ListenTCP crashed , err : %s , \ntrace:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
for {
|
||||
var conn net.Conn
|
||||
conn, err = (*sc.Listener).Accept()
|
||||
if err == nil {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
sc.log.Printf("tcp connection handler crashed , err : %s , \ntrace:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
fn(conn)
|
||||
}()
|
||||
} else {
|
||||
sc.errAcceptHandler(err)
|
||||
break
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
return
|
||||
}
|
||||
func (sc *ServerChannel) ListenUDP(fn func(listener *net.UDPConn, packet []byte, localAddr, srcAddr *net.UDPAddr)) (err error) {
|
||||
addr := &net.UDPAddr{IP: net.ParseIP(sc.ip), Port: sc.port}
|
||||
l, err := net.ListenUDP("udp", addr)
|
||||
if err == nil {
|
||||
sc.UDPListener = l
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
sc.log.Printf("ListenUDP crashed , err : %s , \ntrace:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
for {
|
||||
var buf = make([]byte, 2048)
|
||||
n, srcAddr, err := (*sc.UDPListener).ReadFromUDP(buf)
|
||||
if err == nil {
|
||||
packet := buf[0:n]
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
sc.log.Printf("udp data handler crashed , err : %s , \ntrace:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
fn(l, packet, addr, srcAddr)
|
||||
}()
|
||||
} else {
|
||||
sc.errAcceptHandler(err)
|
||||
break
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (sc *ServerChannel) ListenKCP(config kcpcfg.KCPConfigArgs, fn func(conn net.Conn), log *logger.Logger) (err error) {
|
||||
lis, err := kcp.ListenWithOptions(fmt.Sprintf("%s:%d", sc.ip, sc.port), config.Block, *config.DataShard, *config.ParityShard)
|
||||
if err == nil {
|
||||
if err = lis.SetDSCP(*config.DSCP); err != nil {
|
||||
log.Println("SetDSCP:", err)
|
||||
return
|
||||
}
|
||||
if err = lis.SetReadBuffer(*config.SockBuf); err != nil {
|
||||
log.Println("SetReadBuffer:", err)
|
||||
return
|
||||
}
|
||||
if err = lis.SetWriteBuffer(*config.SockBuf); err != nil {
|
||||
log.Println("SetWriteBuffer:", err)
|
||||
return
|
||||
}
|
||||
sc.Listener = new(net.Listener)
|
||||
*sc.Listener = lis
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
sc.log.Printf("ListenKCP crashed , err : %s , \ntrace:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
for {
|
||||
//var conn net.Conn
|
||||
conn, err := lis.AcceptKCP()
|
||||
if err == nil {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
sc.log.Printf("kcp connection handler crashed , err : %s , \ntrace:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
conn.SetStreamMode(true)
|
||||
conn.SetWriteDelay(true)
|
||||
conn.SetNoDelay(*config.NoDelay, *config.Interval, *config.Resend, *config.NoCongestion)
|
||||
conn.SetMtu(*config.MTU)
|
||||
conn.SetWindowSize(*config.SndWnd, *config.RcvWnd)
|
||||
conn.SetACKNoDelay(*config.AckNodelay)
|
||||
if *config.NoComp {
|
||||
fn(conn)
|
||||
} else {
|
||||
cconn := NewCompStream(conn)
|
||||
fn(cconn)
|
||||
}
|
||||
}()
|
||||
} else {
|
||||
sc.errAcceptHandler(err)
|
||||
break
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -106,15 +106,16 @@ func (s *ServerConn) Port() string {
|
||||
}
|
||||
func (s *ServerConn) Handshake() (err error) {
|
||||
remoteAddr := (*s.conn).RemoteAddr()
|
||||
localAddr := (*s.conn).LocalAddr()
|
||||
//协商开始
|
||||
//method select request
|
||||
var methodReq MethodsRequest
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(time.Second * s.timeout))
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(s.timeout))
|
||||
|
||||
methodReq, e := NewMethodsRequest((*s.conn), s.header)
|
||||
(*s.conn).SetReadDeadline(time.Time{})
|
||||
if e != nil {
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(time.Second * s.timeout))
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(s.timeout))
|
||||
methodReq.Reply(Method_NONE_ACCEPTABLE)
|
||||
(*s.conn).SetReadDeadline(time.Time{})
|
||||
err = fmt.Errorf("new methods request fail,ERR: %s", e)
|
||||
@ -123,7 +124,7 @@ func (s *ServerConn) Handshake() (err error) {
|
||||
//log.Printf("%v,s.auth == %v && methodReq.Select(Method_NO_AUTH) %v", methodReq.methods, s.auth, methodReq.Select(Method_NO_AUTH))
|
||||
if s.auth == nil && methodReq.Select(Method_NO_AUTH) && !methodReq.Select(Method_USER_PASS) {
|
||||
// if !methodReq.Select(Method_NO_AUTH) {
|
||||
// (*s.conn).SetReadDeadline(time.Now().Add(time.Second * s.timeout))
|
||||
// (*s.conn).SetReadDeadline(time.Now().Add(s.timeout))
|
||||
// methodReq.Reply(Method_NONE_ACCEPTABLE)
|
||||
// (*s.conn).SetReadDeadline(time.Time{})
|
||||
// err = fmt.Errorf("none method found : Method_NO_AUTH")
|
||||
@ -131,7 +132,7 @@ func (s *ServerConn) Handshake() (err error) {
|
||||
// }
|
||||
s.method = Method_NO_AUTH
|
||||
//method select reply
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(time.Second * s.timeout))
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(s.timeout))
|
||||
err = methodReq.Reply(Method_NO_AUTH)
|
||||
(*s.conn).SetReadDeadline(time.Time{})
|
||||
if err != nil {
|
||||
@ -142,7 +143,7 @@ func (s *ServerConn) Handshake() (err error) {
|
||||
} else {
|
||||
//auth
|
||||
if !methodReq.Select(Method_USER_PASS) {
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(time.Second * s.timeout))
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(s.timeout))
|
||||
methodReq.Reply(Method_NONE_ACCEPTABLE)
|
||||
(*s.conn).SetReadDeadline(time.Time{})
|
||||
err = fmt.Errorf("none method found : Method_USER_PASS")
|
||||
@ -150,7 +151,7 @@ func (s *ServerConn) Handshake() (err error) {
|
||||
}
|
||||
s.method = Method_USER_PASS
|
||||
//method reply need auth
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(time.Second * s.timeout))
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(s.timeout))
|
||||
err = methodReq.Reply(Method_USER_PASS)
|
||||
(*s.conn).SetReadDeadline(time.Time{})
|
||||
if err != nil {
|
||||
@ -160,7 +161,7 @@ func (s *ServerConn) Handshake() (err error) {
|
||||
//read auth
|
||||
buf := make([]byte, 500)
|
||||
var n int
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(time.Second * s.timeout))
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(s.timeout))
|
||||
n, err = (*s.conn).Read(buf)
|
||||
(*s.conn).SetReadDeadline(time.Time{})
|
||||
if err != nil {
|
||||
@ -172,9 +173,10 @@ func (s *ServerConn) Handshake() (err error) {
|
||||
s.password = string(r[2+r[1]+1:])
|
||||
//err = fmt.Errorf("user:%s,pass:%s", user, pass)
|
||||
//auth
|
||||
_addr := strings.Split(remoteAddr.String(), ":")
|
||||
if s.auth == nil || s.auth.CheckUserPass(s.user, s.password, _addr[0], "") {
|
||||
(*s.conn).SetDeadline(time.Now().Add(time.Millisecond * time.Duration(s.timeout)))
|
||||
_userAddr := strings.Split(remoteAddr.String(), ":")
|
||||
_localAddr := strings.Split(localAddr.String(), ":")
|
||||
if s.auth == nil || s.auth.CheckUserPass(s.user, s.password, _userAddr[0], _localAddr[0], "") {
|
||||
(*s.conn).SetDeadline(time.Now().Add(s.timeout))
|
||||
_, err = (*s.conn).Write([]byte{0x01, 0x00})
|
||||
(*s.conn).SetDeadline(time.Time{})
|
||||
if err != nil {
|
||||
@ -182,7 +184,7 @@ func (s *ServerConn) Handshake() (err error) {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
(*s.conn).SetDeadline(time.Now().Add(time.Millisecond * time.Duration(s.timeout)))
|
||||
(*s.conn).SetDeadline(time.Now().Add(s.timeout))
|
||||
_, err = (*s.conn).Write([]byte{0x01, 0x01})
|
||||
(*s.conn).SetDeadline(time.Time{})
|
||||
if err != nil {
|
||||
@ -194,7 +196,7 @@ func (s *ServerConn) Handshake() (err error) {
|
||||
}
|
||||
}
|
||||
//request detail
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(time.Second * s.timeout))
|
||||
(*s.conn).SetReadDeadline(time.Now().Add(s.timeout))
|
||||
request, e := NewRequest(*s.conn)
|
||||
(*s.conn).SetReadDeadline(time.Time{})
|
||||
if e != nil {
|
||||
|
||||
@ -30,6 +30,7 @@ type Checker struct {
|
||||
interval int64
|
||||
timeout int
|
||||
isStop bool
|
||||
intelligent string
|
||||
log *logger.Logger
|
||||
}
|
||||
type CheckerItem struct {
|
||||
@ -43,12 +44,13 @@ type CheckerItem struct {
|
||||
//NewChecker args:
|
||||
//timeout : tcp timeout milliseconds ,connect to host
|
||||
//interval: recheck domain interval seconds
|
||||
func NewChecker(timeout int, interval int64, blockedFile, directFile string, log *logger.Logger) Checker {
|
||||
func NewChecker(timeout int, interval int64, blockedFile, directFile string, log *logger.Logger, intelligent string) Checker {
|
||||
ch := Checker{
|
||||
data: mapx.NewConcurrentMap(),
|
||||
interval: interval,
|
||||
timeout: timeout,
|
||||
isStop: false,
|
||||
intelligent: intelligent,
|
||||
log: log,
|
||||
}
|
||||
ch.blockedMap = ch.loadMap(blockedFile)
|
||||
@ -90,7 +92,7 @@ func (c *Checker) start() {
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
//log.Printf("checker started")
|
||||
@ -100,7 +102,7 @@ func (c *Checker) start() {
|
||||
go func(item CheckerItem) {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
fmt.Printf("crashed:%s", string(debug.Stack()))
|
||||
fmt.Printf("crashed, err: %s\nstack:%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
if c.isNeedCheck(item) {
|
||||
@ -164,10 +166,19 @@ func (c *Checker) IsBlocked(domain string) (blocked, isInMap bool, failN, succes
|
||||
//log.Printf("%s not in map, blocked true", address)
|
||||
return true, false, 0, 0
|
||||
}
|
||||
switch c.intelligent {
|
||||
case "direct":
|
||||
return false, true, 0, 0
|
||||
case "parent":
|
||||
return true, true, 0, 0
|
||||
case "intelligent":
|
||||
fallthrough
|
||||
default:
|
||||
item := _item.(CheckerItem)
|
||||
|
||||
return (item.FailCount >= item.SuccessCount) && (time.Now().Unix()-item.Lasttime < 1800), true, item.FailCount, item.SuccessCount
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Checker) domainIsInMap(address string, blockedMap bool) bool {
|
||||
u, err := url.Parse("http://" + address)
|
||||
if err != nil {
|
||||
@ -176,11 +187,9 @@ func (c *Checker) domainIsInMap(address string, blockedMap bool) bool {
|
||||
}
|
||||
domainSlice := strings.Split(u.Hostname(), ".")
|
||||
if len(domainSlice) > 1 {
|
||||
subSlice := domainSlice[:len(domainSlice)-1]
|
||||
topDomain := strings.Join(domainSlice[len(domainSlice)-1:], ".")
|
||||
checkDomain := topDomain
|
||||
for i := len(subSlice) - 1; i >= 0; i-- {
|
||||
checkDomain = subSlice[i] + "." + checkDomain
|
||||
checkDomain := ""
|
||||
for i := len(domainSlice) - 1; i >= 0; i-- {
|
||||
checkDomain = strings.Join(domainSlice[i:], ".")
|
||||
if !blockedMap && c.directMap.Has(checkDomain) {
|
||||
return true
|
||||
}
|
||||
@ -237,7 +246,7 @@ func (ba *BasicAuth) AddFromFile(file string) (n int, err error) {
|
||||
}
|
||||
userpassArr := strings.Split(strings.Replace(string(_content), "\r", "", -1), "\n")
|
||||
for _, userpass := range userpassArr {
|
||||
if strings.HasPrefix("#", userpass) {
|
||||
if strings.HasPrefix(userpass, "#") {
|
||||
continue
|
||||
}
|
||||
u := strings.Split(strings.Trim(userpass, " "), ":")
|
||||
@ -259,18 +268,23 @@ func (ba *BasicAuth) Add(userpassArr []string) (n int) {
|
||||
}
|
||||
return
|
||||
}
|
||||
func (ba *BasicAuth) CheckUserPass(user, pass, ip, target string) (ok bool) {
|
||||
|
||||
return ba.Check(user+":"+pass, ip, target)
|
||||
func (ba *BasicAuth) Delete(userArr []string) {
|
||||
for _, u := range userArr {
|
||||
ba.data.Remove(u)
|
||||
}
|
||||
func (ba *BasicAuth) Check(userpass string, ip, target string) (ok bool) {
|
||||
}
|
||||
func (ba *BasicAuth) CheckUserPass(user, pass, userIP, localIP, target string) (ok bool) {
|
||||
|
||||
return ba.Check(user+":"+pass, userIP, localIP, target)
|
||||
}
|
||||
func (ba *BasicAuth) Check(userpass string, userIP, localIP, target string) (ok bool) {
|
||||
u := strings.Split(strings.Trim(userpass, " "), ":")
|
||||
if len(u) == 2 {
|
||||
if p, _ok := ba.data.Get(u[0]); _ok {
|
||||
return p.(string) == u[1]
|
||||
}
|
||||
if ba.authURL != "" {
|
||||
err := ba.checkFromURL(userpass, ip, target)
|
||||
err := ba.checkFromURL(userpass, userIP, localIP, target)
|
||||
if err == nil {
|
||||
return true
|
||||
}
|
||||
@ -280,7 +294,7 @@ func (ba *BasicAuth) Check(userpass string, ip, target string) (ok bool) {
|
||||
}
|
||||
return
|
||||
}
|
||||
func (ba *BasicAuth) checkFromURL(userpass, ip, target string) (err error) {
|
||||
func (ba *BasicAuth) checkFromURL(userpass, userIP, localIP, target string) (err error) {
|
||||
u := strings.Split(strings.Trim(userpass, " "), ":")
|
||||
if len(u) != 2 {
|
||||
return
|
||||
@ -292,7 +306,7 @@ func (ba *BasicAuth) checkFromURL(userpass, ip, target string) (err error) {
|
||||
} else {
|
||||
URL += "?"
|
||||
}
|
||||
URL += fmt.Sprintf("user=%s&pass=%s&ip=%s&target=%s", u[0], u[1], ip, url.QueryEscape(target))
|
||||
URL += fmt.Sprintf("user=%s&pass=%s&ip=%s&local_ip=%s&target=%s", u[0], u[1], userIP, localIP, url.QueryEscape(target))
|
||||
getURL := URL
|
||||
var domain string
|
||||
if ba.dns != nil {
|
||||
@ -309,7 +323,7 @@ func (ba *BasicAuth) checkFromURL(userpass, ip, target string) (err error) {
|
||||
if err == nil && code == ba.authOkCode {
|
||||
break
|
||||
} else if err != nil {
|
||||
err = fmt.Errorf("auth fail from url %s,resonse err:%s , %s", URL, err, ip)
|
||||
err = fmt.Errorf("auth fail from url %s,resonse err:%s , %s -> %s", URL, err, userIP, localIP)
|
||||
} else {
|
||||
if len(body) > 0 {
|
||||
err = fmt.Errorf(string(body[0:100]))
|
||||
@ -320,7 +334,7 @@ func (ba *BasicAuth) checkFromURL(userpass, ip, target string) (err error) {
|
||||
if len(b) > 50 {
|
||||
b = b[:50]
|
||||
}
|
||||
err = fmt.Errorf("auth fail from url %s,resonse code: %d, except: %d , %s , %s", URL, code, ba.authOkCode, ip, b)
|
||||
err = fmt.Errorf("auth fail from url %s,resonse code: %d, except: %d , %s -> %s, %s", URL, code, ba.authOkCode, userIP, localIP, b)
|
||||
}
|
||||
if err != nil && tryCount < ba.authRetry {
|
||||
ba.log.Print(err)
|
||||
@ -474,7 +488,8 @@ func (req *HTTPRequest) GetAuthDataStr() (basicInfo string, err error) {
|
||||
return
|
||||
}
|
||||
func (req *HTTPRequest) BasicAuth() (err error) {
|
||||
addr := strings.Split((*req.conn).RemoteAddr().String(), ":")
|
||||
userIP := strings.Split((*req.conn).RemoteAddr().String(), ":")
|
||||
localIP := strings.Split((*req.conn).LocalAddr().String(), ":")
|
||||
URL := ""
|
||||
if req.IsHTTPS() {
|
||||
URL = "https://" + req.Host
|
||||
@ -485,7 +500,7 @@ func (req *HTTPRequest) BasicAuth() (err error) {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
authOk := (*req.basicAuth).Check(string(user), addr[0], URL)
|
||||
authOk := (*req.basicAuth).Check(string(user), userIP[0], localIP[0], URL)
|
||||
//log.Printf("auth %s,%v", string(user), authOk)
|
||||
if !authOk {
|
||||
fmt.Fprintf((*req.conn), "HTTP/1.1 %s Proxy Authentication Required\r\n\r\nProxy Authentication Required", "407")
|
||||
|
||||
122
vendor/github.com/Yawning/chacha20/LICENSE
generated
vendored
Normal file
122
vendor/github.com/Yawning/chacha20/LICENSE
generated
vendored
Normal file
@ -0,0 +1,122 @@
|
||||
Creative Commons Legal Code
|
||||
|
||||
CC0 1.0 Universal
|
||||
|
||||
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
|
||||
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
|
||||
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
|
||||
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
|
||||
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
|
||||
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
|
||||
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
|
||||
HEREUNDER.
|
||||
|
||||
Statement of Purpose
|
||||
|
||||
The laws of most jurisdictions throughout the world automatically confer
|
||||
exclusive Copyright and Related Rights (defined below) upon the creator
|
||||
and subsequent owner(s) (each and all, an "owner") of an original work of
|
||||
authorship and/or a database (each, a "Work").
|
||||
|
||||
Certain owners wish to permanently relinquish those rights to a Work for
|
||||
the purpose of contributing to a commons of creative, cultural and
|
||||
scientific works ("Commons") that the public can reliably and without fear
|
||||
of later claims of infringement build upon, modify, incorporate in other
|
||||
works, reuse and redistribute as freely as possible in any form whatsoever
|
||||
and for any purposes, including without limitation commercial purposes.
|
||||
These owners may contribute to the Commons to promote the ideal of a free
|
||||
culture and the further production of creative, cultural and scientific
|
||||
works, or to gain reputation or greater distribution for their Work in
|
||||
part through the use and efforts of others.
|
||||
|
||||
For these and/or other purposes and motivations, and without any
|
||||
expectation of additional consideration or compensation, the person
|
||||
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
|
||||
is an owner of Copyright and Related Rights in the Work, voluntarily
|
||||
elects to apply CC0 to the Work and publicly distribute the Work under its
|
||||
terms, with knowledge of his or her Copyright and Related Rights in the
|
||||
Work and the meaning and intended legal effect of CC0 on those rights.
|
||||
|
||||
1. Copyright and Related Rights. A Work made available under CC0 may be
|
||||
protected by copyright and related or neighboring rights ("Copyright and
|
||||
Related Rights"). Copyright and Related Rights include, but are not
|
||||
limited to, the following:
|
||||
|
||||
i. the right to reproduce, adapt, distribute, perform, display,
|
||||
communicate, and translate a Work;
|
||||
ii. moral rights retained by the original author(s) and/or performer(s);
|
||||
iii. publicity and privacy rights pertaining to a person's image or
|
||||
likeness depicted in a Work;
|
||||
iv. rights protecting against unfair competition in regards to a Work,
|
||||
subject to the limitations in paragraph 4(a), below;
|
||||
v. rights protecting the extraction, dissemination, use and reuse of data
|
||||
in a Work;
|
||||
vi. database rights (such as those arising under Directive 96/9/EC of the
|
||||
European Parliament and of the Council of 11 March 1996 on the legal
|
||||
protection of databases, and under any national implementation
|
||||
thereof, including any amended or successor version of such
|
||||
directive); and
|
||||
vii. other similar, equivalent or corresponding rights throughout the
|
||||
world based on applicable law or treaty, and any national
|
||||
implementations thereof.
|
||||
|
||||
2. Waiver. To the greatest extent permitted by, but not in contravention
|
||||
of, applicable law, Affirmer hereby overtly, fully, permanently,
|
||||
irrevocably and unconditionally waives, abandons, and surrenders all of
|
||||
Affirmer's Copyright and Related Rights and associated claims and causes
|
||||
of action, whether now known or unknown (including existing as well as
|
||||
future claims and causes of action), in the Work (i) in all territories
|
||||
worldwide, (ii) for the maximum duration provided by applicable law or
|
||||
treaty (including future time extensions), (iii) in any current or future
|
||||
medium and for any number of copies, and (iv) for any purpose whatsoever,
|
||||
including without limitation commercial, advertising or promotional
|
||||
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
|
||||
member of the public at large and to the detriment of Affirmer's heirs and
|
||||
successors, fully intending that such Waiver shall not be subject to
|
||||
revocation, rescission, cancellation, termination, or any other legal or
|
||||
equitable action to disrupt the quiet enjoyment of the Work by the public
|
||||
as contemplated by Affirmer's express Statement of Purpose.
|
||||
|
||||
3. Public License Fallback. Should any part of the Waiver for any reason
|
||||
be judged legally invalid or ineffective under applicable law, then the
|
||||
Waiver shall be preserved to the maximum extent permitted taking into
|
||||
account Affirmer's express Statement of Purpose. In addition, to the
|
||||
extent the Waiver is so judged Affirmer hereby grants to each affected
|
||||
person a royalty-free, non transferable, non sublicensable, non exclusive,
|
||||
irrevocable and unconditional license to exercise Affirmer's Copyright and
|
||||
Related Rights in the Work (i) in all territories worldwide, (ii) for the
|
||||
maximum duration provided by applicable law or treaty (including future
|
||||
time extensions), (iii) in any current or future medium and for any number
|
||||
of copies, and (iv) for any purpose whatsoever, including without
|
||||
limitation commercial, advertising or promotional purposes (the
|
||||
"License"). The License shall be deemed effective as of the date CC0 was
|
||||
applied by Affirmer to the Work. Should any part of the License for any
|
||||
reason be judged legally invalid or ineffective under applicable law, such
|
||||
partial invalidity or ineffectiveness shall not invalidate the remainder
|
||||
of the License, and in such case Affirmer hereby affirms that he or she
|
||||
will not (i) exercise any of his or her remaining Copyright and Related
|
||||
Rights in the Work or (ii) assert any associated claims and causes of
|
||||
action with respect to the Work, in either case contrary to Affirmer's
|
||||
express Statement of Purpose.
|
||||
|
||||
4. Limitations and Disclaimers.
|
||||
|
||||
a. No trademark or patent rights held by Affirmer are waived, abandoned,
|
||||
surrendered, licensed or otherwise affected by this document.
|
||||
b. Affirmer offers the Work as-is and makes no representations or
|
||||
warranties of any kind concerning the Work, express, implied,
|
||||
statutory or otherwise, including without limitation warranties of
|
||||
title, merchantability, fitness for a particular purpose, non
|
||||
infringement, or the absence of latent or other defects, accuracy, or
|
||||
the present or absence of errors, whether or not discoverable, all to
|
||||
the greatest extent permissible under applicable law.
|
||||
c. Affirmer disclaims responsibility for clearing rights of other persons
|
||||
that may apply to the Work or any use thereof, including without
|
||||
limitation any person's Copyright and Related Rights in the Work.
|
||||
Further, Affirmer disclaims responsibility for obtaining any necessary
|
||||
consents, permissions or other rights required for any use of the
|
||||
Work.
|
||||
d. Affirmer understands and acknowledges that Creative Commons is not a
|
||||
party to this document and has no duty or obligation with respect to
|
||||
this CC0 or use of the Work.
|
||||
|
||||
14
vendor/github.com/Yawning/chacha20/README.md
generated
vendored
Normal file
14
vendor/github.com/Yawning/chacha20/README.md
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
### chacha20 - ChaCha20
|
||||
#### Yawning Angel (yawning at schwanenlied dot me)
|
||||
|
||||
Yet another Go ChaCha20 implementation. Everything else I found was slow,
|
||||
didn't support all the variants I need to use, or relied on cgo to go fast.
|
||||
|
||||
Features:
|
||||
|
||||
* 20 round, 256 bit key only. Everything else is pointless and stupid.
|
||||
* IETF 96 bit nonce variant.
|
||||
* XChaCha 24 byte nonce variant.
|
||||
* SSE2 and AVX2 support on amd64 targets.
|
||||
* Incremental encrypt/decrypt support, unlike golang.org/x/crypto/salsa20.
|
||||
|
||||
273
vendor/github.com/Yawning/chacha20/chacha20.go
generated
vendored
Normal file
273
vendor/github.com/Yawning/chacha20/chacha20.go
generated
vendored
Normal file
@ -0,0 +1,273 @@
|
||||
// chacha20.go - A ChaCha stream cipher implementation.
|
||||
//
|
||||
// To the extent possible under law, Yawning Angel has waived all copyright
|
||||
// and related or neighboring rights to chacha20, using the Creative
|
||||
// Commons "CC0" public domain dedication. See LICENSE or
|
||||
// <http://creativecommons.org/publicdomain/zero/1.0/> for full details.
|
||||
|
||||
package chacha20
|
||||
|
||||
import (
|
||||
"crypto/cipher"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"math"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
const (
|
||||
// KeySize is the ChaCha20 key size in bytes.
|
||||
KeySize = 32
|
||||
|
||||
// NonceSize is the ChaCha20 nonce size in bytes.
|
||||
NonceSize = 8
|
||||
|
||||
// INonceSize is the IETF ChaCha20 nonce size in bytes.
|
||||
INonceSize = 12
|
||||
|
||||
// XNonceSize is the XChaCha20 nonce size in bytes.
|
||||
XNonceSize = 24
|
||||
|
||||
// HNonceSize is the HChaCha20 nonce size in bytes.
|
||||
HNonceSize = 16
|
||||
|
||||
// BlockSize is the ChaCha20 block size in bytes.
|
||||
BlockSize = 64
|
||||
|
||||
stateSize = 16
|
||||
chachaRounds = 20
|
||||
|
||||
// The constant "expand 32-byte k" as little endian uint32s.
|
||||
sigma0 = uint32(0x61707865)
|
||||
sigma1 = uint32(0x3320646e)
|
||||
sigma2 = uint32(0x79622d32)
|
||||
sigma3 = uint32(0x6b206574)
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrInvalidKey is the error returned when the key is invalid.
|
||||
ErrInvalidKey = errors.New("key length must be KeySize bytes")
|
||||
|
||||
// ErrInvalidNonce is the error returned when the nonce is invalid.
|
||||
ErrInvalidNonce = errors.New("nonce length must be NonceSize/INonceSize/XNonceSize bytes")
|
||||
|
||||
// ErrInvalidCounter is the error returned when the counter is invalid.
|
||||
ErrInvalidCounter = errors.New("block counter is invalid (out of range)")
|
||||
|
||||
useUnsafe = false
|
||||
usingVectors = false
|
||||
blocksFn = blocksRef
|
||||
)
|
||||
|
||||
// A Cipher is an instance of ChaCha20/XChaCha20 using a particular key and
|
||||
// nonce.
|
||||
type Cipher struct {
|
||||
state [stateSize]uint32
|
||||
|
||||
buf [BlockSize]byte
|
||||
off int
|
||||
ietf bool
|
||||
}
|
||||
|
||||
// Reset zeros the key data so that it will no longer appear in the process's
|
||||
// memory.
|
||||
func (c *Cipher) Reset() {
|
||||
for i := range c.state {
|
||||
c.state[i] = 0
|
||||
}
|
||||
for i := range c.buf {
|
||||
c.buf[i] = 0
|
||||
}
|
||||
}
|
||||
|
||||
// XORKeyStream sets dst to the result of XORing src with the key stream. Dst
|
||||
// and src may be the same slice but otherwise should not overlap.
|
||||
func (c *Cipher) XORKeyStream(dst, src []byte) {
|
||||
if len(dst) < len(src) {
|
||||
src = src[:len(dst)]
|
||||
}
|
||||
|
||||
for remaining := len(src); remaining > 0; {
|
||||
// Process multiple blocks at once.
|
||||
if c.off == BlockSize {
|
||||
nrBlocks := remaining / BlockSize
|
||||
directBytes := nrBlocks * BlockSize
|
||||
if nrBlocks > 0 {
|
||||
blocksFn(&c.state, src, dst, nrBlocks, c.ietf)
|
||||
remaining -= directBytes
|
||||
if remaining == 0 {
|
||||
return
|
||||
}
|
||||
dst = dst[directBytes:]
|
||||
src = src[directBytes:]
|
||||
}
|
||||
|
||||
// If there's a partial block, generate 1 block of keystream into
|
||||
// the internal buffer.
|
||||
blocksFn(&c.state, nil, c.buf[:], 1, c.ietf)
|
||||
c.off = 0
|
||||
}
|
||||
|
||||
// Process partial blocks from the buffered keystream.
|
||||
toXor := BlockSize - c.off
|
||||
if remaining < toXor {
|
||||
toXor = remaining
|
||||
}
|
||||
if toXor > 0 {
|
||||
for i, v := range src[:toXor] {
|
||||
dst[i] = v ^ c.buf[c.off+i]
|
||||
}
|
||||
dst = dst[toXor:]
|
||||
src = src[toXor:]
|
||||
|
||||
remaining -= toXor
|
||||
c.off += toXor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// KeyStream sets dst to the raw keystream.
|
||||
func (c *Cipher) KeyStream(dst []byte) {
|
||||
for remaining := len(dst); remaining > 0; {
|
||||
// Process multiple blocks at once.
|
||||
if c.off == BlockSize {
|
||||
nrBlocks := remaining / BlockSize
|
||||
directBytes := nrBlocks * BlockSize
|
||||
if nrBlocks > 0 {
|
||||
blocksFn(&c.state, nil, dst, nrBlocks, c.ietf)
|
||||
remaining -= directBytes
|
||||
if remaining == 0 {
|
||||
return
|
||||
}
|
||||
dst = dst[directBytes:]
|
||||
}
|
||||
|
||||
// If there's a partial block, generate 1 block of keystream into
|
||||
// the internal buffer.
|
||||
blocksFn(&c.state, nil, c.buf[:], 1, c.ietf)
|
||||
c.off = 0
|
||||
}
|
||||
|
||||
// Process partial blocks from the buffered keystream.
|
||||
toCopy := BlockSize - c.off
|
||||
if remaining < toCopy {
|
||||
toCopy = remaining
|
||||
}
|
||||
if toCopy > 0 {
|
||||
copy(dst[:toCopy], c.buf[c.off:c.off+toCopy])
|
||||
dst = dst[toCopy:]
|
||||
remaining -= toCopy
|
||||
c.off += toCopy
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ReKey reinitializes the ChaCha20/XChaCha20 instance with the provided key
|
||||
// and nonce.
|
||||
func (c *Cipher) ReKey(key, nonce []byte) error {
|
||||
if len(key) != KeySize {
|
||||
return ErrInvalidKey
|
||||
}
|
||||
|
||||
switch len(nonce) {
|
||||
case NonceSize:
|
||||
case INonceSize:
|
||||
case XNonceSize:
|
||||
var subkey [KeySize]byte
|
||||
var subnonce [HNonceSize]byte
|
||||
copy(subnonce[:], nonce[0:16])
|
||||
HChaCha(key, &subnonce, &subkey)
|
||||
key = subkey[:]
|
||||
nonce = nonce[16:24]
|
||||
defer func() {
|
||||
for i := range subkey {
|
||||
subkey[i] = 0
|
||||
}
|
||||
}()
|
||||
default:
|
||||
return ErrInvalidNonce
|
||||
}
|
||||
|
||||
c.Reset()
|
||||
c.state[0] = sigma0
|
||||
c.state[1] = sigma1
|
||||
c.state[2] = sigma2
|
||||
c.state[3] = sigma3
|
||||
c.state[4] = binary.LittleEndian.Uint32(key[0:4])
|
||||
c.state[5] = binary.LittleEndian.Uint32(key[4:8])
|
||||
c.state[6] = binary.LittleEndian.Uint32(key[8:12])
|
||||
c.state[7] = binary.LittleEndian.Uint32(key[12:16])
|
||||
c.state[8] = binary.LittleEndian.Uint32(key[16:20])
|
||||
c.state[9] = binary.LittleEndian.Uint32(key[20:24])
|
||||
c.state[10] = binary.LittleEndian.Uint32(key[24:28])
|
||||
c.state[11] = binary.LittleEndian.Uint32(key[28:32])
|
||||
c.state[12] = 0
|
||||
if len(nonce) == INonceSize {
|
||||
c.state[13] = binary.LittleEndian.Uint32(nonce[0:4])
|
||||
c.state[14] = binary.LittleEndian.Uint32(nonce[4:8])
|
||||
c.state[15] = binary.LittleEndian.Uint32(nonce[8:12])
|
||||
c.ietf = true
|
||||
} else {
|
||||
c.state[13] = 0
|
||||
c.state[14] = binary.LittleEndian.Uint32(nonce[0:4])
|
||||
c.state[15] = binary.LittleEndian.Uint32(nonce[4:8])
|
||||
c.ietf = false
|
||||
}
|
||||
c.off = BlockSize
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
// Seek sets the block counter to a given offset.
|
||||
func (c *Cipher) Seek(blockCounter uint64) error {
|
||||
if c.ietf {
|
||||
if blockCounter > math.MaxUint32 {
|
||||
return ErrInvalidCounter
|
||||
}
|
||||
c.state[12] = uint32(blockCounter)
|
||||
} else {
|
||||
c.state[12] = uint32(blockCounter)
|
||||
c.state[13] = uint32(blockCounter >> 32)
|
||||
}
|
||||
c.off = BlockSize
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewCipher returns a new ChaCha20/XChaCha20 instance.
|
||||
func NewCipher(key, nonce []byte) (*Cipher, error) {
|
||||
c := new(Cipher)
|
||||
if err := c.ReKey(key, nonce); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// HChaCha is the HChaCha20 hash function used to make XChaCha.
|
||||
func HChaCha(key []byte, nonce *[HNonceSize]byte, out *[32]byte) {
|
||||
var x [stateSize]uint32 // Last 4 slots unused, sigma hardcoded.
|
||||
x[0] = binary.LittleEndian.Uint32(key[0:4])
|
||||
x[1] = binary.LittleEndian.Uint32(key[4:8])
|
||||
x[2] = binary.LittleEndian.Uint32(key[8:12])
|
||||
x[3] = binary.LittleEndian.Uint32(key[12:16])
|
||||
x[4] = binary.LittleEndian.Uint32(key[16:20])
|
||||
x[5] = binary.LittleEndian.Uint32(key[20:24])
|
||||
x[6] = binary.LittleEndian.Uint32(key[24:28])
|
||||
x[7] = binary.LittleEndian.Uint32(key[28:32])
|
||||
x[8] = binary.LittleEndian.Uint32(nonce[0:4])
|
||||
x[9] = binary.LittleEndian.Uint32(nonce[4:8])
|
||||
x[10] = binary.LittleEndian.Uint32(nonce[8:12])
|
||||
x[11] = binary.LittleEndian.Uint32(nonce[12:16])
|
||||
hChaChaRef(&x, out)
|
||||
}
|
||||
|
||||
func init() {
|
||||
switch runtime.GOARCH {
|
||||
case "386", "amd64":
|
||||
// Abuse unsafe to skip calling binary.LittleEndian.PutUint32
|
||||
// in the critical path. This is a big boost on systems that are
|
||||
// little endian and not overly picky about alignment.
|
||||
useUnsafe = true
|
||||
}
|
||||
}
|
||||
|
||||
var _ cipher.Stream = (*Cipher)(nil)
|
||||
95
vendor/github.com/Yawning/chacha20/chacha20_amd64.go
generated
vendored
Normal file
95
vendor/github.com/Yawning/chacha20/chacha20_amd64.go
generated
vendored
Normal file
@ -0,0 +1,95 @@
|
||||
// chacha20_amd64.go - AMD64 optimized chacha20.
|
||||
//
|
||||
// To the extent possible under law, Yawning Angel has waived all copyright
|
||||
// and related or neighboring rights to chacha20, using the Creative
|
||||
// Commons "CC0" public domain dedication. See LICENSE or
|
||||
// <http://creativecommons.org/publicdomain/zero/1.0/> for full details.
|
||||
|
||||
// +build amd64,!gccgo,!appengine
|
||||
|
||||
package chacha20
|
||||
|
||||
import (
|
||||
"math"
|
||||
)
|
||||
|
||||
var usingAVX2 = false
|
||||
|
||||
func blocksAmd64SSE2(x *uint32, inp, outp *byte, nrBlocks uint)
|
||||
|
||||
func blocksAmd64AVX2(x *uint32, inp, outp *byte, nrBlocks uint)
|
||||
|
||||
func cpuidAmd64(cpuidParams *uint32)
|
||||
|
||||
func xgetbv0Amd64(xcrVec *uint32)
|
||||
|
||||
func blocksAmd64(x *[stateSize]uint32, in []byte, out []byte, nrBlocks int, isIetf bool) {
|
||||
// Probably unneeded, but stating this explicitly simplifies the assembly.
|
||||
if nrBlocks == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if isIetf {
|
||||
var totalBlocks uint64
|
||||
totalBlocks = uint64(x[12]) + uint64(nrBlocks)
|
||||
if totalBlocks > math.MaxUint32 {
|
||||
panic("chacha20: Exceeded keystream per nonce limit")
|
||||
}
|
||||
}
|
||||
|
||||
if in == nil {
|
||||
for i := range out {
|
||||
out[i] = 0
|
||||
}
|
||||
in = out
|
||||
}
|
||||
|
||||
// Pointless to call the AVX2 code for just a single block, since half of
|
||||
// the output gets discarded...
|
||||
if usingAVX2 && nrBlocks > 1 {
|
||||
blocksAmd64AVX2(&x[0], &in[0], &out[0], uint(nrBlocks))
|
||||
} else {
|
||||
blocksAmd64SSE2(&x[0], &in[0], &out[0], uint(nrBlocks))
|
||||
}
|
||||
}
|
||||
|
||||
func supportsAVX2() bool {
|
||||
// https://software.intel.com/en-us/articles/how-to-detect-new-instruction-support-in-the-4th-generation-intel-core-processor-family
|
||||
const (
|
||||
osXsaveBit = 1 << 27
|
||||
avx2Bit = 1 << 5
|
||||
)
|
||||
|
||||
// Check to see if CPUID actually supports the leaf that indicates AVX2.
|
||||
// CPUID.(EAX=0H, ECX=0H) >= 7
|
||||
regs := [4]uint32{0x00}
|
||||
cpuidAmd64(®s[0])
|
||||
if regs[0] < 7 {
|
||||
return false
|
||||
}
|
||||
|
||||
// Check to see if the OS knows how to save/restore XMM/YMM state.
|
||||
// CPUID.(EAX=01H, ECX=0H):ECX.OSXSAVE[bit 27]==1
|
||||
regs = [4]uint32{0x01}
|
||||
cpuidAmd64(®s[0])
|
||||
if regs[2]&osXsaveBit == 0 {
|
||||
return false
|
||||
}
|
||||
xcrRegs := [2]uint32{}
|
||||
xgetbv0Amd64(&xcrRegs[0])
|
||||
if xcrRegs[0]&6 != 6 {
|
||||
return false
|
||||
}
|
||||
|
||||
// Check for AVX2 support.
|
||||
// CPUID.(EAX=07H, ECX=0H):EBX.AVX2[bit 5]==1
|
||||
regs = [4]uint32{0x07}
|
||||
cpuidAmd64(®s[0])
|
||||
return regs[1]&avx2Bit != 0
|
||||
}
|
||||
|
||||
func init() {
|
||||
blocksFn = blocksAmd64
|
||||
usingVectors = true
|
||||
usingAVX2 = supportsAVX2()
|
||||
}
|
||||
1295
vendor/github.com/Yawning/chacha20/chacha20_amd64.py
generated
vendored
Normal file
1295
vendor/github.com/Yawning/chacha20/chacha20_amd64.py
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1180
vendor/github.com/Yawning/chacha20/chacha20_amd64.s
generated
vendored
Normal file
1180
vendor/github.com/Yawning/chacha20/chacha20_amd64.s
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
394
vendor/github.com/Yawning/chacha20/chacha20_ref.go
generated
vendored
Normal file
394
vendor/github.com/Yawning/chacha20/chacha20_ref.go
generated
vendored
Normal file
@ -0,0 +1,394 @@
|
||||
// chacha20_ref.go - Reference ChaCha20.
|
||||
//
|
||||
// To the extent possible under law, Yawning Angel has waived all copyright
|
||||
// and related or neighboring rights to chacha20, using the Creative
|
||||
// Commons "CC0" public domain dedication. See LICENSE or
|
||||
// <http://creativecommons.org/publicdomain/zero/1.0/> for full details.
|
||||
|
||||
// +build !go1.9
|
||||
|
||||
package chacha20
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"math"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func blocksRef(x *[stateSize]uint32, in []byte, out []byte, nrBlocks int, isIetf bool) {
|
||||
if isIetf {
|
||||
var totalBlocks uint64
|
||||
totalBlocks = uint64(x[12]) + uint64(nrBlocks)
|
||||
if totalBlocks > math.MaxUint32 {
|
||||
panic("chacha20: Exceeded keystream per nonce limit")
|
||||
}
|
||||
}
|
||||
|
||||
// This routine ignores x[0]...x[4] in favor the const values since it's
|
||||
// ever so slightly faster.
|
||||
|
||||
for n := 0; n < nrBlocks; n++ {
|
||||
x0, x1, x2, x3 := sigma0, sigma1, sigma2, sigma3
|
||||
x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15 := x[4], x[5], x[6], x[7], x[8], x[9], x[10], x[11], x[12], x[13], x[14], x[15]
|
||||
|
||||
for i := chachaRounds; i > 0; i -= 2 {
|
||||
// quarterround(x, 0, 4, 8, 12)
|
||||
x0 += x4
|
||||
x12 ^= x0
|
||||
x12 = (x12 << 16) | (x12 >> 16)
|
||||
x8 += x12
|
||||
x4 ^= x8
|
||||
x4 = (x4 << 12) | (x4 >> 20)
|
||||
x0 += x4
|
||||
x12 ^= x0
|
||||
x12 = (x12 << 8) | (x12 >> 24)
|
||||
x8 += x12
|
||||
x4 ^= x8
|
||||
x4 = (x4 << 7) | (x4 >> 25)
|
||||
|
||||
// quarterround(x, 1, 5, 9, 13)
|
||||
x1 += x5
|
||||
x13 ^= x1
|
||||
x13 = (x13 << 16) | (x13 >> 16)
|
||||
x9 += x13
|
||||
x5 ^= x9
|
||||
x5 = (x5 << 12) | (x5 >> 20)
|
||||
x1 += x5
|
||||
x13 ^= x1
|
||||
x13 = (x13 << 8) | (x13 >> 24)
|
||||
x9 += x13
|
||||
x5 ^= x9
|
||||
x5 = (x5 << 7) | (x5 >> 25)
|
||||
|
||||
// quarterround(x, 2, 6, 10, 14)
|
||||
x2 += x6
|
||||
x14 ^= x2
|
||||
x14 = (x14 << 16) | (x14 >> 16)
|
||||
x10 += x14
|
||||
x6 ^= x10
|
||||
x6 = (x6 << 12) | (x6 >> 20)
|
||||
x2 += x6
|
||||
x14 ^= x2
|
||||
x14 = (x14 << 8) | (x14 >> 24)
|
||||
x10 += x14
|
||||
x6 ^= x10
|
||||
x6 = (x6 << 7) | (x6 >> 25)
|
||||
|
||||
// quarterround(x, 3, 7, 11, 15)
|
||||
x3 += x7
|
||||
x15 ^= x3
|
||||
x15 = (x15 << 16) | (x15 >> 16)
|
||||
x11 += x15
|
||||
x7 ^= x11
|
||||
x7 = (x7 << 12) | (x7 >> 20)
|
||||
x3 += x7
|
||||
x15 ^= x3
|
||||
x15 = (x15 << 8) | (x15 >> 24)
|
||||
x11 += x15
|
||||
x7 ^= x11
|
||||
x7 = (x7 << 7) | (x7 >> 25)
|
||||
|
||||
// quarterround(x, 0, 5, 10, 15)
|
||||
x0 += x5
|
||||
x15 ^= x0
|
||||
x15 = (x15 << 16) | (x15 >> 16)
|
||||
x10 += x15
|
||||
x5 ^= x10
|
||||
x5 = (x5 << 12) | (x5 >> 20)
|
||||
x0 += x5
|
||||
x15 ^= x0
|
||||
x15 = (x15 << 8) | (x15 >> 24)
|
||||
x10 += x15
|
||||
x5 ^= x10
|
||||
x5 = (x5 << 7) | (x5 >> 25)
|
||||
|
||||
// quarterround(x, 1, 6, 11, 12)
|
||||
x1 += x6
|
||||
x12 ^= x1
|
||||
x12 = (x12 << 16) | (x12 >> 16)
|
||||
x11 += x12
|
||||
x6 ^= x11
|
||||
x6 = (x6 << 12) | (x6 >> 20)
|
||||
x1 += x6
|
||||
x12 ^= x1
|
||||
x12 = (x12 << 8) | (x12 >> 24)
|
||||
x11 += x12
|
||||
x6 ^= x11
|
||||
x6 = (x6 << 7) | (x6 >> 25)
|
||||
|
||||
// quarterround(x, 2, 7, 8, 13)
|
||||
x2 += x7
|
||||
x13 ^= x2
|
||||
x13 = (x13 << 16) | (x13 >> 16)
|
||||
x8 += x13
|
||||
x7 ^= x8
|
||||
x7 = (x7 << 12) | (x7 >> 20)
|
||||
x2 += x7
|
||||
x13 ^= x2
|
||||
x13 = (x13 << 8) | (x13 >> 24)
|
||||
x8 += x13
|
||||
x7 ^= x8
|
||||
x7 = (x7 << 7) | (x7 >> 25)
|
||||
|
||||
// quarterround(x, 3, 4, 9, 14)
|
||||
x3 += x4
|
||||
x14 ^= x3
|
||||
x14 = (x14 << 16) | (x14 >> 16)
|
||||
x9 += x14
|
||||
x4 ^= x9
|
||||
x4 = (x4 << 12) | (x4 >> 20)
|
||||
x3 += x4
|
||||
x14 ^= x3
|
||||
x14 = (x14 << 8) | (x14 >> 24)
|
||||
x9 += x14
|
||||
x4 ^= x9
|
||||
x4 = (x4 << 7) | (x4 >> 25)
|
||||
}
|
||||
|
||||
// On amd64 at least, this is a rather big boost.
|
||||
if useUnsafe {
|
||||
if in != nil {
|
||||
inArr := (*[16]uint32)(unsafe.Pointer(&in[n*BlockSize]))
|
||||
outArr := (*[16]uint32)(unsafe.Pointer(&out[n*BlockSize]))
|
||||
outArr[0] = inArr[0] ^ (x0 + sigma0)
|
||||
outArr[1] = inArr[1] ^ (x1 + sigma1)
|
||||
outArr[2] = inArr[2] ^ (x2 + sigma2)
|
||||
outArr[3] = inArr[3] ^ (x3 + sigma3)
|
||||
outArr[4] = inArr[4] ^ (x4 + x[4])
|
||||
outArr[5] = inArr[5] ^ (x5 + x[5])
|
||||
outArr[6] = inArr[6] ^ (x6 + x[6])
|
||||
outArr[7] = inArr[7] ^ (x7 + x[7])
|
||||
outArr[8] = inArr[8] ^ (x8 + x[8])
|
||||
outArr[9] = inArr[9] ^ (x9 + x[9])
|
||||
outArr[10] = inArr[10] ^ (x10 + x[10])
|
||||
outArr[11] = inArr[11] ^ (x11 + x[11])
|
||||
outArr[12] = inArr[12] ^ (x12 + x[12])
|
||||
outArr[13] = inArr[13] ^ (x13 + x[13])
|
||||
outArr[14] = inArr[14] ^ (x14 + x[14])
|
||||
outArr[15] = inArr[15] ^ (x15 + x[15])
|
||||
} else {
|
||||
outArr := (*[16]uint32)(unsafe.Pointer(&out[n*BlockSize]))
|
||||
outArr[0] = x0 + sigma0
|
||||
outArr[1] = x1 + sigma1
|
||||
outArr[2] = x2 + sigma2
|
||||
outArr[3] = x3 + sigma3
|
||||
outArr[4] = x4 + x[4]
|
||||
outArr[5] = x5 + x[5]
|
||||
outArr[6] = x6 + x[6]
|
||||
outArr[7] = x7 + x[7]
|
||||
outArr[8] = x8 + x[8]
|
||||
outArr[9] = x9 + x[9]
|
||||
outArr[10] = x10 + x[10]
|
||||
outArr[11] = x11 + x[11]
|
||||
outArr[12] = x12 + x[12]
|
||||
outArr[13] = x13 + x[13]
|
||||
outArr[14] = x14 + x[14]
|
||||
outArr[15] = x15 + x[15]
|
||||
}
|
||||
} else {
|
||||
// Slow path, either the architecture cares about alignment, or is not little endian.
|
||||
x0 += sigma0
|
||||
x1 += sigma1
|
||||
x2 += sigma2
|
||||
x3 += sigma3
|
||||
x4 += x[4]
|
||||
x5 += x[5]
|
||||
x6 += x[6]
|
||||
x7 += x[7]
|
||||
x8 += x[8]
|
||||
x9 += x[9]
|
||||
x10 += x[10]
|
||||
x11 += x[11]
|
||||
x12 += x[12]
|
||||
x13 += x[13]
|
||||
x14 += x[14]
|
||||
x15 += x[15]
|
||||
if in != nil {
|
||||
binary.LittleEndian.PutUint32(out[0:4], binary.LittleEndian.Uint32(in[0:4])^x0)
|
||||
binary.LittleEndian.PutUint32(out[4:8], binary.LittleEndian.Uint32(in[4:8])^x1)
|
||||
binary.LittleEndian.PutUint32(out[8:12], binary.LittleEndian.Uint32(in[8:12])^x2)
|
||||
binary.LittleEndian.PutUint32(out[12:16], binary.LittleEndian.Uint32(in[12:16])^x3)
|
||||
binary.LittleEndian.PutUint32(out[16:20], binary.LittleEndian.Uint32(in[16:20])^x4)
|
||||
binary.LittleEndian.PutUint32(out[20:24], binary.LittleEndian.Uint32(in[20:24])^x5)
|
||||
binary.LittleEndian.PutUint32(out[24:28], binary.LittleEndian.Uint32(in[24:28])^x6)
|
||||
binary.LittleEndian.PutUint32(out[28:32], binary.LittleEndian.Uint32(in[28:32])^x7)
|
||||
binary.LittleEndian.PutUint32(out[32:36], binary.LittleEndian.Uint32(in[32:36])^x8)
|
||||
binary.LittleEndian.PutUint32(out[36:40], binary.LittleEndian.Uint32(in[36:40])^x9)
|
||||
binary.LittleEndian.PutUint32(out[40:44], binary.LittleEndian.Uint32(in[40:44])^x10)
|
||||
binary.LittleEndian.PutUint32(out[44:48], binary.LittleEndian.Uint32(in[44:48])^x11)
|
||||
binary.LittleEndian.PutUint32(out[48:52], binary.LittleEndian.Uint32(in[48:52])^x12)
|
||||
binary.LittleEndian.PutUint32(out[52:56], binary.LittleEndian.Uint32(in[52:56])^x13)
|
||||
binary.LittleEndian.PutUint32(out[56:60], binary.LittleEndian.Uint32(in[56:60])^x14)
|
||||
binary.LittleEndian.PutUint32(out[60:64], binary.LittleEndian.Uint32(in[60:64])^x15)
|
||||
in = in[BlockSize:]
|
||||
} else {
|
||||
binary.LittleEndian.PutUint32(out[0:4], x0)
|
||||
binary.LittleEndian.PutUint32(out[4:8], x1)
|
||||
binary.LittleEndian.PutUint32(out[8:12], x2)
|
||||
binary.LittleEndian.PutUint32(out[12:16], x3)
|
||||
binary.LittleEndian.PutUint32(out[16:20], x4)
|
||||
binary.LittleEndian.PutUint32(out[20:24], x5)
|
||||
binary.LittleEndian.PutUint32(out[24:28], x6)
|
||||
binary.LittleEndian.PutUint32(out[28:32], x7)
|
||||
binary.LittleEndian.PutUint32(out[32:36], x8)
|
||||
binary.LittleEndian.PutUint32(out[36:40], x9)
|
||||
binary.LittleEndian.PutUint32(out[40:44], x10)
|
||||
binary.LittleEndian.PutUint32(out[44:48], x11)
|
||||
binary.LittleEndian.PutUint32(out[48:52], x12)
|
||||
binary.LittleEndian.PutUint32(out[52:56], x13)
|
||||
binary.LittleEndian.PutUint32(out[56:60], x14)
|
||||
binary.LittleEndian.PutUint32(out[60:64], x15)
|
||||
}
|
||||
out = out[BlockSize:]
|
||||
}
|
||||
|
||||
// Stoping at 2^70 bytes per nonce is the user's responsibility.
|
||||
ctr := uint64(x[13])<<32 | uint64(x[12])
|
||||
ctr++
|
||||
x[12] = uint32(ctr)
|
||||
x[13] = uint32(ctr >> 32)
|
||||
}
|
||||
}
|
||||
|
||||
func hChaChaRef(x *[stateSize]uint32, out *[32]byte) {
|
||||
x0, x1, x2, x3 := sigma0, sigma1, sigma2, sigma3
|
||||
x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15 := x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9], x[10], x[11]
|
||||
|
||||
for i := chachaRounds; i > 0; i -= 2 {
|
||||
// quarterround(x, 0, 4, 8, 12)
|
||||
x0 += x4
|
||||
x12 ^= x0
|
||||
x12 = (x12 << 16) | (x12 >> 16)
|
||||
x8 += x12
|
||||
x4 ^= x8
|
||||
x4 = (x4 << 12) | (x4 >> 20)
|
||||
x0 += x4
|
||||
x12 ^= x0
|
||||
x12 = (x12 << 8) | (x12 >> 24)
|
||||
x8 += x12
|
||||
x4 ^= x8
|
||||
x4 = (x4 << 7) | (x4 >> 25)
|
||||
|
||||
// quarterround(x, 1, 5, 9, 13)
|
||||
x1 += x5
|
||||
x13 ^= x1
|
||||
x13 = (x13 << 16) | (x13 >> 16)
|
||||
x9 += x13
|
||||
x5 ^= x9
|
||||
x5 = (x5 << 12) | (x5 >> 20)
|
||||
x1 += x5
|
||||
x13 ^= x1
|
||||
x13 = (x13 << 8) | (x13 >> 24)
|
||||
x9 += x13
|
||||
x5 ^= x9
|
||||
x5 = (x5 << 7) | (x5 >> 25)
|
||||
|
||||
// quarterround(x, 2, 6, 10, 14)
|
||||
x2 += x6
|
||||
x14 ^= x2
|
||||
x14 = (x14 << 16) | (x14 >> 16)
|
||||
x10 += x14
|
||||
x6 ^= x10
|
||||
x6 = (x6 << 12) | (x6 >> 20)
|
||||
x2 += x6
|
||||
x14 ^= x2
|
||||
x14 = (x14 << 8) | (x14 >> 24)
|
||||
x10 += x14
|
||||
x6 ^= x10
|
||||
x6 = (x6 << 7) | (x6 >> 25)
|
||||
|
||||
// quarterround(x, 3, 7, 11, 15)
|
||||
x3 += x7
|
||||
x15 ^= x3
|
||||
x15 = (x15 << 16) | (x15 >> 16)
|
||||
x11 += x15
|
||||
x7 ^= x11
|
||||
x7 = (x7 << 12) | (x7 >> 20)
|
||||
x3 += x7
|
||||
x15 ^= x3
|
||||
x15 = (x15 << 8) | (x15 >> 24)
|
||||
x11 += x15
|
||||
x7 ^= x11
|
||||
x7 = (x7 << 7) | (x7 >> 25)
|
||||
|
||||
// quarterround(x, 0, 5, 10, 15)
|
||||
x0 += x5
|
||||
x15 ^= x0
|
||||
x15 = (x15 << 16) | (x15 >> 16)
|
||||
x10 += x15
|
||||
x5 ^= x10
|
||||
x5 = (x5 << 12) | (x5 >> 20)
|
||||
x0 += x5
|
||||
x15 ^= x0
|
||||
x15 = (x15 << 8) | (x15 >> 24)
|
||||
x10 += x15
|
||||
x5 ^= x10
|
||||
x5 = (x5 << 7) | (x5 >> 25)
|
||||
|
||||
// quarterround(x, 1, 6, 11, 12)
|
||||
x1 += x6
|
||||
x12 ^= x1
|
||||
x12 = (x12 << 16) | (x12 >> 16)
|
||||
x11 += x12
|
||||
x6 ^= x11
|
||||
x6 = (x6 << 12) | (x6 >> 20)
|
||||
x1 += x6
|
||||
x12 ^= x1
|
||||
x12 = (x12 << 8) | (x12 >> 24)
|
||||
x11 += x12
|
||||
x6 ^= x11
|
||||
x6 = (x6 << 7) | (x6 >> 25)
|
||||
|
||||
// quarterround(x, 2, 7, 8, 13)
|
||||
x2 += x7
|
||||
x13 ^= x2
|
||||
x13 = (x13 << 16) | (x13 >> 16)
|
||||
x8 += x13
|
||||
x7 ^= x8
|
||||
x7 = (x7 << 12) | (x7 >> 20)
|
||||
x2 += x7
|
||||
x13 ^= x2
|
||||
x13 = (x13 << 8) | (x13 >> 24)
|
||||
x8 += x13
|
||||
x7 ^= x8
|
||||
x7 = (x7 << 7) | (x7 >> 25)
|
||||
|
||||
// quarterround(x, 3, 4, 9, 14)
|
||||
x3 += x4
|
||||
x14 ^= x3
|
||||
x14 = (x14 << 16) | (x14 >> 16)
|
||||
x9 += x14
|
||||
x4 ^= x9
|
||||
x4 = (x4 << 12) | (x4 >> 20)
|
||||
x3 += x4
|
||||
x14 ^= x3
|
||||
x14 = (x14 << 8) | (x14 >> 24)
|
||||
x9 += x14
|
||||
x4 ^= x9
|
||||
x4 = (x4 << 7) | (x4 >> 25)
|
||||
}
|
||||
|
||||
// HChaCha returns x0...x3 | x12...x15, which corresponds to the
|
||||
// indexes of the ChaCha constant and the indexes of the IV.
|
||||
if useUnsafe {
|
||||
outArr := (*[16]uint32)(unsafe.Pointer(&out[0]))
|
||||
outArr[0] = x0
|
||||
outArr[1] = x1
|
||||
outArr[2] = x2
|
||||
outArr[3] = x3
|
||||
outArr[4] = x12
|
||||
outArr[5] = x13
|
||||
outArr[6] = x14
|
||||
outArr[7] = x15
|
||||
} else {
|
||||
binary.LittleEndian.PutUint32(out[0:4], x0)
|
||||
binary.LittleEndian.PutUint32(out[4:8], x1)
|
||||
binary.LittleEndian.PutUint32(out[8:12], x2)
|
||||
binary.LittleEndian.PutUint32(out[12:16], x3)
|
||||
binary.LittleEndian.PutUint32(out[16:20], x12)
|
||||
binary.LittleEndian.PutUint32(out[20:24], x13)
|
||||
binary.LittleEndian.PutUint32(out[24:28], x14)
|
||||
binary.LittleEndian.PutUint32(out[28:32], x15)
|
||||
}
|
||||
return
|
||||
}
|
||||
395
vendor/github.com/Yawning/chacha20/chacha20_ref_go19.go
generated
vendored
Normal file
395
vendor/github.com/Yawning/chacha20/chacha20_ref_go19.go
generated
vendored
Normal file
@ -0,0 +1,395 @@
|
||||
// chacha20_ref.go - Reference ChaCha20.
|
||||
//
|
||||
// To the extent possible under law, Yawning Angel has waived all copyright
|
||||
// and related or neighboring rights to chacha20, using the Creative
|
||||
// Commons "CC0" public domain dedication. See LICENSE or
|
||||
// <http://creativecommons.org/publicdomain/zero/1.0/> for full details.
|
||||
|
||||
// +build go1.9
|
||||
|
||||
package chacha20
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"math"
|
||||
"math/bits"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func blocksRef(x *[stateSize]uint32, in []byte, out []byte, nrBlocks int, isIetf bool) {
|
||||
if isIetf {
|
||||
var totalBlocks uint64
|
||||
totalBlocks = uint64(x[12]) + uint64(nrBlocks)
|
||||
if totalBlocks > math.MaxUint32 {
|
||||
panic("chacha20: Exceeded keystream per nonce limit")
|
||||
}
|
||||
}
|
||||
|
||||
// This routine ignores x[0]...x[4] in favor the const values since it's
|
||||
// ever so slightly faster.
|
||||
|
||||
for n := 0; n < nrBlocks; n++ {
|
||||
x0, x1, x2, x3 := sigma0, sigma1, sigma2, sigma3
|
||||
x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15 := x[4], x[5], x[6], x[7], x[8], x[9], x[10], x[11], x[12], x[13], x[14], x[15]
|
||||
|
||||
for i := chachaRounds; i > 0; i -= 2 {
|
||||
// quarterround(x, 0, 4, 8, 12)
|
||||
x0 += x4
|
||||
x12 ^= x0
|
||||
x12 = bits.RotateLeft32(x12, 16)
|
||||
x8 += x12
|
||||
x4 ^= x8
|
||||
x4 = bits.RotateLeft32(x4, 12)
|
||||
x0 += x4
|
||||
x12 ^= x0
|
||||
x12 = bits.RotateLeft32(x12, 8)
|
||||
x8 += x12
|
||||
x4 ^= x8
|
||||
x4 = bits.RotateLeft32(x4, 7)
|
||||
|
||||
// quarterround(x, 1, 5, 9, 13)
|
||||
x1 += x5
|
||||
x13 ^= x1
|
||||
x13 = bits.RotateLeft32(x13, 16)
|
||||
x9 += x13
|
||||
x5 ^= x9
|
||||
x5 = bits.RotateLeft32(x5, 12)
|
||||
x1 += x5
|
||||
x13 ^= x1
|
||||
x13 = bits.RotateLeft32(x13, 8)
|
||||
x9 += x13
|
||||
x5 ^= x9
|
||||
x5 = bits.RotateLeft32(x5, 7)
|
||||
|
||||
// quarterround(x, 2, 6, 10, 14)
|
||||
x2 += x6
|
||||
x14 ^= x2
|
||||
x14 = bits.RotateLeft32(x14, 16)
|
||||
x10 += x14
|
||||
x6 ^= x10
|
||||
x6 = bits.RotateLeft32(x6, 12)
|
||||
x2 += x6
|
||||
x14 ^= x2
|
||||
x14 = bits.RotateLeft32(x14, 8)
|
||||
x10 += x14
|
||||
x6 ^= x10
|
||||
x6 = bits.RotateLeft32(x6, 7)
|
||||
|
||||
// quarterround(x, 3, 7, 11, 15)
|
||||
x3 += x7
|
||||
x15 ^= x3
|
||||
x15 = bits.RotateLeft32(x15, 16)
|
||||
x11 += x15
|
||||
x7 ^= x11
|
||||
x7 = bits.RotateLeft32(x7, 12)
|
||||
x3 += x7
|
||||
x15 ^= x3
|
||||
x15 = bits.RotateLeft32(x15, 8)
|
||||
x11 += x15
|
||||
x7 ^= x11
|
||||
x7 = bits.RotateLeft32(x7, 7)
|
||||
|
||||
// quarterround(x, 0, 5, 10, 15)
|
||||
x0 += x5
|
||||
x15 ^= x0
|
||||
x15 = bits.RotateLeft32(x15, 16)
|
||||
x10 += x15
|
||||
x5 ^= x10
|
||||
x5 = bits.RotateLeft32(x5, 12)
|
||||
x0 += x5
|
||||
x15 ^= x0
|
||||
x15 = bits.RotateLeft32(x15, 8)
|
||||
x10 += x15
|
||||
x5 ^= x10
|
||||
x5 = bits.RotateLeft32(x5, 7)
|
||||
|
||||
// quarterround(x, 1, 6, 11, 12)
|
||||
x1 += x6
|
||||
x12 ^= x1
|
||||
x12 = bits.RotateLeft32(x12, 16)
|
||||
x11 += x12
|
||||
x6 ^= x11
|
||||
x6 = bits.RotateLeft32(x6, 12)
|
||||
x1 += x6
|
||||
x12 ^= x1
|
||||
x12 = bits.RotateLeft32(x12, 8)
|
||||
x11 += x12
|
||||
x6 ^= x11
|
||||
x6 = bits.RotateLeft32(x6, 7)
|
||||
|
||||
// quarterround(x, 2, 7, 8, 13)
|
||||
x2 += x7
|
||||
x13 ^= x2
|
||||
x13 = bits.RotateLeft32(x13, 16)
|
||||
x8 += x13
|
||||
x7 ^= x8
|
||||
x7 = bits.RotateLeft32(x7, 12)
|
||||
x2 += x7
|
||||
x13 ^= x2
|
||||
x13 = bits.RotateLeft32(x13, 8)
|
||||
x8 += x13
|
||||
x7 ^= x8
|
||||
x7 = bits.RotateLeft32(x7, 7)
|
||||
|
||||
// quarterround(x, 3, 4, 9, 14)
|
||||
x3 += x4
|
||||
x14 ^= x3
|
||||
x14 = bits.RotateLeft32(x14, 16)
|
||||
x9 += x14
|
||||
x4 ^= x9
|
||||
x4 = bits.RotateLeft32(x4, 12)
|
||||
x3 += x4
|
||||
x14 ^= x3
|
||||
x14 = bits.RotateLeft32(x14, 8)
|
||||
x9 += x14
|
||||
x4 ^= x9
|
||||
x4 = bits.RotateLeft32(x4, 7)
|
||||
}
|
||||
|
||||
// On amd64 at least, this is a rather big boost.
|
||||
if useUnsafe {
|
||||
if in != nil {
|
||||
inArr := (*[16]uint32)(unsafe.Pointer(&in[n*BlockSize]))
|
||||
outArr := (*[16]uint32)(unsafe.Pointer(&out[n*BlockSize]))
|
||||
outArr[0] = inArr[0] ^ (x0 + sigma0)
|
||||
outArr[1] = inArr[1] ^ (x1 + sigma1)
|
||||
outArr[2] = inArr[2] ^ (x2 + sigma2)
|
||||
outArr[3] = inArr[3] ^ (x3 + sigma3)
|
||||
outArr[4] = inArr[4] ^ (x4 + x[4])
|
||||
outArr[5] = inArr[5] ^ (x5 + x[5])
|
||||
outArr[6] = inArr[6] ^ (x6 + x[6])
|
||||
outArr[7] = inArr[7] ^ (x7 + x[7])
|
||||
outArr[8] = inArr[8] ^ (x8 + x[8])
|
||||
outArr[9] = inArr[9] ^ (x9 + x[9])
|
||||
outArr[10] = inArr[10] ^ (x10 + x[10])
|
||||
outArr[11] = inArr[11] ^ (x11 + x[11])
|
||||
outArr[12] = inArr[12] ^ (x12 + x[12])
|
||||
outArr[13] = inArr[13] ^ (x13 + x[13])
|
||||
outArr[14] = inArr[14] ^ (x14 + x[14])
|
||||
outArr[15] = inArr[15] ^ (x15 + x[15])
|
||||
} else {
|
||||
outArr := (*[16]uint32)(unsafe.Pointer(&out[n*BlockSize]))
|
||||
outArr[0] = x0 + sigma0
|
||||
outArr[1] = x1 + sigma1
|
||||
outArr[2] = x2 + sigma2
|
||||
outArr[3] = x3 + sigma3
|
||||
outArr[4] = x4 + x[4]
|
||||
outArr[5] = x5 + x[5]
|
||||
outArr[6] = x6 + x[6]
|
||||
outArr[7] = x7 + x[7]
|
||||
outArr[8] = x8 + x[8]
|
||||
outArr[9] = x9 + x[9]
|
||||
outArr[10] = x10 + x[10]
|
||||
outArr[11] = x11 + x[11]
|
||||
outArr[12] = x12 + x[12]
|
||||
outArr[13] = x13 + x[13]
|
||||
outArr[14] = x14 + x[14]
|
||||
outArr[15] = x15 + x[15]
|
||||
}
|
||||
} else {
|
||||
// Slow path, either the architecture cares about alignment, or is not little endian.
|
||||
x0 += sigma0
|
||||
x1 += sigma1
|
||||
x2 += sigma2
|
||||
x3 += sigma3
|
||||
x4 += x[4]
|
||||
x5 += x[5]
|
||||
x6 += x[6]
|
||||
x7 += x[7]
|
||||
x8 += x[8]
|
||||
x9 += x[9]
|
||||
x10 += x[10]
|
||||
x11 += x[11]
|
||||
x12 += x[12]
|
||||
x13 += x[13]
|
||||
x14 += x[14]
|
||||
x15 += x[15]
|
||||
if in != nil {
|
||||
binary.LittleEndian.PutUint32(out[0:4], binary.LittleEndian.Uint32(in[0:4])^x0)
|
||||
binary.LittleEndian.PutUint32(out[4:8], binary.LittleEndian.Uint32(in[4:8])^x1)
|
||||
binary.LittleEndian.PutUint32(out[8:12], binary.LittleEndian.Uint32(in[8:12])^x2)
|
||||
binary.LittleEndian.PutUint32(out[12:16], binary.LittleEndian.Uint32(in[12:16])^x3)
|
||||
binary.LittleEndian.PutUint32(out[16:20], binary.LittleEndian.Uint32(in[16:20])^x4)
|
||||
binary.LittleEndian.PutUint32(out[20:24], binary.LittleEndian.Uint32(in[20:24])^x5)
|
||||
binary.LittleEndian.PutUint32(out[24:28], binary.LittleEndian.Uint32(in[24:28])^x6)
|
||||
binary.LittleEndian.PutUint32(out[28:32], binary.LittleEndian.Uint32(in[28:32])^x7)
|
||||
binary.LittleEndian.PutUint32(out[32:36], binary.LittleEndian.Uint32(in[32:36])^x8)
|
||||
binary.LittleEndian.PutUint32(out[36:40], binary.LittleEndian.Uint32(in[36:40])^x9)
|
||||
binary.LittleEndian.PutUint32(out[40:44], binary.LittleEndian.Uint32(in[40:44])^x10)
|
||||
binary.LittleEndian.PutUint32(out[44:48], binary.LittleEndian.Uint32(in[44:48])^x11)
|
||||
binary.LittleEndian.PutUint32(out[48:52], binary.LittleEndian.Uint32(in[48:52])^x12)
|
||||
binary.LittleEndian.PutUint32(out[52:56], binary.LittleEndian.Uint32(in[52:56])^x13)
|
||||
binary.LittleEndian.PutUint32(out[56:60], binary.LittleEndian.Uint32(in[56:60])^x14)
|
||||
binary.LittleEndian.PutUint32(out[60:64], binary.LittleEndian.Uint32(in[60:64])^x15)
|
||||
in = in[BlockSize:]
|
||||
} else {
|
||||
binary.LittleEndian.PutUint32(out[0:4], x0)
|
||||
binary.LittleEndian.PutUint32(out[4:8], x1)
|
||||
binary.LittleEndian.PutUint32(out[8:12], x2)
|
||||
binary.LittleEndian.PutUint32(out[12:16], x3)
|
||||
binary.LittleEndian.PutUint32(out[16:20], x4)
|
||||
binary.LittleEndian.PutUint32(out[20:24], x5)
|
||||
binary.LittleEndian.PutUint32(out[24:28], x6)
|
||||
binary.LittleEndian.PutUint32(out[28:32], x7)
|
||||
binary.LittleEndian.PutUint32(out[32:36], x8)
|
||||
binary.LittleEndian.PutUint32(out[36:40], x9)
|
||||
binary.LittleEndian.PutUint32(out[40:44], x10)
|
||||
binary.LittleEndian.PutUint32(out[44:48], x11)
|
||||
binary.LittleEndian.PutUint32(out[48:52], x12)
|
||||
binary.LittleEndian.PutUint32(out[52:56], x13)
|
||||
binary.LittleEndian.PutUint32(out[56:60], x14)
|
||||
binary.LittleEndian.PutUint32(out[60:64], x15)
|
||||
}
|
||||
out = out[BlockSize:]
|
||||
}
|
||||
|
||||
// Stoping at 2^70 bytes per nonce is the user's responsibility.
|
||||
ctr := uint64(x[13])<<32 | uint64(x[12])
|
||||
ctr++
|
||||
x[12] = uint32(ctr)
|
||||
x[13] = uint32(ctr >> 32)
|
||||
}
|
||||
}
|
||||
|
||||
func hChaChaRef(x *[stateSize]uint32, out *[32]byte) {
|
||||
x0, x1, x2, x3 := sigma0, sigma1, sigma2, sigma3
|
||||
x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15 := x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9], x[10], x[11]
|
||||
|
||||
for i := chachaRounds; i > 0; i -= 2 {
|
||||
// quarterround(x, 0, 4, 8, 12)
|
||||
x0 += x4
|
||||
x12 ^= x0
|
||||
x12 = bits.RotateLeft32(x12, 16)
|
||||
x8 += x12
|
||||
x4 ^= x8
|
||||
x4 = bits.RotateLeft32(x4, 12)
|
||||
x0 += x4
|
||||
x12 ^= x0
|
||||
x12 = bits.RotateLeft32(x12, 8)
|
||||
x8 += x12
|
||||
x4 ^= x8
|
||||
x4 = bits.RotateLeft32(x4, 7)
|
||||
|
||||
// quarterround(x, 1, 5, 9, 13)
|
||||
x1 += x5
|
||||
x13 ^= x1
|
||||
x13 = bits.RotateLeft32(x13, 16)
|
||||
x9 += x13
|
||||
x5 ^= x9
|
||||
x5 = bits.RotateLeft32(x5, 12)
|
||||
x1 += x5
|
||||
x13 ^= x1
|
||||
x13 = bits.RotateLeft32(x13, 8)
|
||||
x9 += x13
|
||||
x5 ^= x9
|
||||
x5 = bits.RotateLeft32(x5, 7)
|
||||
|
||||
// quarterround(x, 2, 6, 10, 14)
|
||||
x2 += x6
|
||||
x14 ^= x2
|
||||
x14 = bits.RotateLeft32(x14, 16)
|
||||
x10 += x14
|
||||
x6 ^= x10
|
||||
x6 = bits.RotateLeft32(x6, 12)
|
||||
x2 += x6
|
||||
x14 ^= x2
|
||||
x14 = bits.RotateLeft32(x14, 8)
|
||||
x10 += x14
|
||||
x6 ^= x10
|
||||
x6 = bits.RotateLeft32(x6, 7)
|
||||
|
||||
// quarterround(x, 3, 7, 11, 15)
|
||||
x3 += x7
|
||||
x15 ^= x3
|
||||
x15 = bits.RotateLeft32(x15, 16)
|
||||
x11 += x15
|
||||
x7 ^= x11
|
||||
x7 = bits.RotateLeft32(x7, 12)
|
||||
x3 += x7
|
||||
x15 ^= x3
|
||||
x15 = bits.RotateLeft32(x15, 8)
|
||||
x11 += x15
|
||||
x7 ^= x11
|
||||
x7 = bits.RotateLeft32(x7, 7)
|
||||
|
||||
// quarterround(x, 0, 5, 10, 15)
|
||||
x0 += x5
|
||||
x15 ^= x0
|
||||
x15 = bits.RotateLeft32(x15, 16)
|
||||
x10 += x15
|
||||
x5 ^= x10
|
||||
x5 = bits.RotateLeft32(x5, 12)
|
||||
x0 += x5
|
||||
x15 ^= x0
|
||||
x15 = bits.RotateLeft32(x15, 8)
|
||||
x10 += x15
|
||||
x5 ^= x10
|
||||
x5 = bits.RotateLeft32(x5, 7)
|
||||
|
||||
// quarterround(x, 1, 6, 11, 12)
|
||||
x1 += x6
|
||||
x12 ^= x1
|
||||
x12 = bits.RotateLeft32(x12, 16)
|
||||
x11 += x12
|
||||
x6 ^= x11
|
||||
x6 = bits.RotateLeft32(x6, 12)
|
||||
x1 += x6
|
||||
x12 ^= x1
|
||||
x12 = bits.RotateLeft32(x12, 8)
|
||||
x11 += x12
|
||||
x6 ^= x11
|
||||
x6 = bits.RotateLeft32(x6, 7)
|
||||
|
||||
// quarterround(x, 2, 7, 8, 13)
|
||||
x2 += x7
|
||||
x13 ^= x2
|
||||
x13 = bits.RotateLeft32(x13, 16)
|
||||
x8 += x13
|
||||
x7 ^= x8
|
||||
x7 = bits.RotateLeft32(x7, 12)
|
||||
x2 += x7
|
||||
x13 ^= x2
|
||||
x13 = bits.RotateLeft32(x13, 8)
|
||||
x8 += x13
|
||||
x7 ^= x8
|
||||
x7 = bits.RotateLeft32(x7, 7)
|
||||
|
||||
// quarterround(x, 3, 4, 9, 14)
|
||||
x3 += x4
|
||||
x14 ^= x3
|
||||
x14 = bits.RotateLeft32(x14, 16)
|
||||
x9 += x14
|
||||
x4 ^= x9
|
||||
x4 = bits.RotateLeft32(x4, 12)
|
||||
x3 += x4
|
||||
x14 ^= x3
|
||||
x14 = bits.RotateLeft32(x14, 8)
|
||||
x9 += x14
|
||||
x4 ^= x9
|
||||
x4 = bits.RotateLeft32(x4, 7)
|
||||
}
|
||||
|
||||
// HChaCha returns x0...x3 | x12...x15, which corresponds to the
|
||||
// indexes of the ChaCha constant and the indexes of the IV.
|
||||
if useUnsafe {
|
||||
outArr := (*[16]uint32)(unsafe.Pointer(&out[0]))
|
||||
outArr[0] = x0
|
||||
outArr[1] = x1
|
||||
outArr[2] = x2
|
||||
outArr[3] = x3
|
||||
outArr[4] = x12
|
||||
outArr[5] = x13
|
||||
outArr[6] = x14
|
||||
outArr[7] = x15
|
||||
} else {
|
||||
binary.LittleEndian.PutUint32(out[0:4], x0)
|
||||
binary.LittleEndian.PutUint32(out[4:8], x1)
|
||||
binary.LittleEndian.PutUint32(out[8:12], x2)
|
||||
binary.LittleEndian.PutUint32(out[12:16], x3)
|
||||
binary.LittleEndian.PutUint32(out[16:20], x12)
|
||||
binary.LittleEndian.PutUint32(out[20:24], x13)
|
||||
binary.LittleEndian.PutUint32(out[24:28], x14)
|
||||
binary.LittleEndian.PutUint32(out[28:32], x15)
|
||||
}
|
||||
return
|
||||
}
|
||||
191
vendor/github.com/juju/ratelimit/LICENSE
generated
vendored
Normal file
191
vendor/github.com/juju/ratelimit/LICENSE
generated
vendored
Normal file
@ -0,0 +1,191 @@
|
||||
All files in this repository are licensed as follows. If you contribute
|
||||
to this repository, it is assumed that you license your contribution
|
||||
under the same license unless you state otherwise.
|
||||
|
||||
All files Copyright (C) 2015 Canonical Ltd. unless otherwise specified in the file.
|
||||
|
||||
This software is licensed under the LGPLv3, included below.
|
||||
|
||||
As a special exception to the GNU Lesser General Public License version 3
|
||||
("LGPL3"), the copyright holders of this Library give you permission to
|
||||
convey to a third party a Combined Work that links statically or dynamically
|
||||
to this Library without providing any Minimal Corresponding Source or
|
||||
Minimal Application Code as set out in 4d or providing the installation
|
||||
information set out in section 4e, provided that you comply with the other
|
||||
provisions of LGPL3 and provided that you meet, for the Application the
|
||||
terms and conditions of the license(s) which apply to the Application.
|
||||
|
||||
Except as stated in this special exception, the provisions of LGPL3 will
|
||||
continue to comply in full to this Library. If you modify this Library, you
|
||||
may apply this exception to your version of this Library, but you are not
|
||||
obliged to do so. If you do not wish to do so, delete this exception
|
||||
statement from your version. This exception does not (and cannot) modify any
|
||||
license terms which apply to the Application, with which you must still
|
||||
comply.
|
||||
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
||||
117
vendor/github.com/juju/ratelimit/README.md
generated
vendored
Normal file
117
vendor/github.com/juju/ratelimit/README.md
generated
vendored
Normal file
@ -0,0 +1,117 @@
|
||||
# ratelimit
|
||||
--
|
||||
import "github.com/juju/ratelimit"
|
||||
|
||||
The ratelimit package provides an efficient token bucket implementation. See
|
||||
http://en.wikipedia.org/wiki/Token_bucket.
|
||||
|
||||
## Usage
|
||||
|
||||
#### func Reader
|
||||
|
||||
```go
|
||||
func Reader(r io.Reader, bucket *Bucket) io.Reader
|
||||
```
|
||||
Reader returns a reader that is rate limited by the given token bucket. Each
|
||||
token in the bucket represents one byte.
|
||||
|
||||
#### func Writer
|
||||
|
||||
```go
|
||||
func Writer(w io.Writer, bucket *Bucket) io.Writer
|
||||
```
|
||||
Writer returns a writer that is rate limited by the given token bucket. Each
|
||||
token in the bucket represents one byte.
|
||||
|
||||
#### type Bucket
|
||||
|
||||
```go
|
||||
type Bucket struct {
|
||||
}
|
||||
```
|
||||
|
||||
Bucket represents a token bucket that fills at a predetermined rate. Methods on
|
||||
Bucket may be called concurrently.
|
||||
|
||||
#### func NewBucket
|
||||
|
||||
```go
|
||||
func NewBucket(fillInterval time.Duration, capacity int64) *Bucket
|
||||
```
|
||||
NewBucket returns a new token bucket that fills at the rate of one token every
|
||||
fillInterval, up to the given maximum capacity. Both arguments must be positive.
|
||||
The bucket is initially full.
|
||||
|
||||
#### func NewBucketWithQuantum
|
||||
|
||||
```go
|
||||
func NewBucketWithQuantum(fillInterval time.Duration, capacity, quantum int64) *Bucket
|
||||
```
|
||||
NewBucketWithQuantum is similar to NewBucket, but allows the specification of
|
||||
the quantum size - quantum tokens are added every fillInterval.
|
||||
|
||||
#### func NewBucketWithRate
|
||||
|
||||
```go
|
||||
func NewBucketWithRate(rate float64, capacity int64) *Bucket
|
||||
```
|
||||
NewBucketWithRate returns a token bucket that fills the bucket at the rate of
|
||||
rate tokens per second up to the given maximum capacity. Because of limited
|
||||
clock resolution, at high rates, the actual rate may be up to 1% different from
|
||||
the specified rate.
|
||||
|
||||
#### func (*Bucket) Rate
|
||||
|
||||
```go
|
||||
func (tb *Bucket) Rate() float64
|
||||
```
|
||||
Rate returns the fill rate of the bucket, in tokens per second.
|
||||
|
||||
#### func (*Bucket) Take
|
||||
|
||||
```go
|
||||
func (tb *Bucket) Take(count int64) time.Duration
|
||||
```
|
||||
Take takes count tokens from the bucket without blocking. It returns the time
|
||||
that the caller should wait until the tokens are actually available.
|
||||
|
||||
Note that if the request is irrevocable - there is no way to return tokens to
|
||||
the bucket once this method commits us to taking them.
|
||||
|
||||
#### func (*Bucket) TakeAvailable
|
||||
|
||||
```go
|
||||
func (tb *Bucket) TakeAvailable(count int64) int64
|
||||
```
|
||||
TakeAvailable takes up to count immediately available tokens from the bucket. It
|
||||
returns the number of tokens removed, or zero if there are no available tokens.
|
||||
It does not block.
|
||||
|
||||
#### func (*Bucket) TakeMaxDuration
|
||||
|
||||
```go
|
||||
func (tb *Bucket) TakeMaxDuration(count int64, maxWait time.Duration) (time.Duration, bool)
|
||||
```
|
||||
TakeMaxDuration is like Take, except that it will only take tokens from the
|
||||
bucket if the wait time for the tokens is no greater than maxWait.
|
||||
|
||||
If it would take longer than maxWait for the tokens to become available, it does
|
||||
nothing and reports false, otherwise it returns the time that the caller should
|
||||
wait until the tokens are actually available, and reports true.
|
||||
|
||||
#### func (*Bucket) Wait
|
||||
|
||||
```go
|
||||
func (tb *Bucket) Wait(count int64)
|
||||
```
|
||||
Wait takes count tokens from the bucket, waiting until they are available.
|
||||
|
||||
#### func (*Bucket) WaitMaxDuration
|
||||
|
||||
```go
|
||||
func (tb *Bucket) WaitMaxDuration(count int64, maxWait time.Duration) bool
|
||||
```
|
||||
WaitMaxDuration is like Wait except that it will only take tokens from the
|
||||
bucket if it needs to wait for no greater than maxWait. It reports whether any
|
||||
tokens have been removed from the bucket If no tokens have been removed, it
|
||||
returns immediately.
|
||||
344
vendor/github.com/juju/ratelimit/ratelimit.go
generated
vendored
Normal file
344
vendor/github.com/juju/ratelimit/ratelimit.go
generated
vendored
Normal file
@ -0,0 +1,344 @@
|
||||
// Copyright 2014 Canonical Ltd.
|
||||
// Licensed under the LGPLv3 with static-linking exception.
|
||||
// See LICENCE file for details.
|
||||
|
||||
// Package ratelimit provides an efficient token bucket implementation
|
||||
// that can be used to limit the rate of arbitrary things.
|
||||
// See http://en.wikipedia.org/wiki/Token_bucket.
|
||||
package ratelimit
|
||||
|
||||
import (
|
||||
"math"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// The algorithm that this implementation uses does computational work
|
||||
// only when tokens are removed from the bucket, and that work completes
|
||||
// in short, bounded-constant time (Bucket.Wait benchmarks at 175ns on
|
||||
// my laptop).
|
||||
//
|
||||
// Time is measured in equal measured ticks, a given interval
|
||||
// (fillInterval) apart. On each tick a number of tokens (quantum) are
|
||||
// added to the bucket.
|
||||
//
|
||||
// When any of the methods are called the bucket updates the number of
|
||||
// tokens that are in the bucket, and it records the current tick
|
||||
// number too. Note that it doesn't record the current time - by
|
||||
// keeping things in units of whole ticks, it's easy to dish out tokens
|
||||
// at exactly the right intervals as measured from the start time.
|
||||
//
|
||||
// This allows us to calculate the number of tokens that will be
|
||||
// available at some time in the future with a few simple arithmetic
|
||||
// operations.
|
||||
//
|
||||
// The main reason for being able to transfer multiple tokens on each tick
|
||||
// is so that we can represent rates greater than 1e9 (the resolution of the Go
|
||||
// time package) tokens per second, but it's also useful because
|
||||
// it means we can easily represent situations like "a person gets
|
||||
// five tokens an hour, replenished on the hour".
|
||||
|
||||
// Bucket represents a token bucket that fills at a predetermined rate.
|
||||
// Methods on Bucket may be called concurrently.
|
||||
type Bucket struct {
|
||||
clock Clock
|
||||
|
||||
// startTime holds the moment when the bucket was
|
||||
// first created and ticks began.
|
||||
startTime time.Time
|
||||
|
||||
// capacity holds the overall capacity of the bucket.
|
||||
capacity int64
|
||||
|
||||
// quantum holds how many tokens are added on
|
||||
// each tick.
|
||||
quantum int64
|
||||
|
||||
// fillInterval holds the interval between each tick.
|
||||
fillInterval time.Duration
|
||||
|
||||
// mu guards the fields below it.
|
||||
mu sync.Mutex
|
||||
|
||||
// availableTokens holds the number of available
|
||||
// tokens as of the associated latestTick.
|
||||
// It will be negative when there are consumers
|
||||
// waiting for tokens.
|
||||
availableTokens int64
|
||||
|
||||
// latestTick holds the latest tick for which
|
||||
// we know the number of tokens in the bucket.
|
||||
latestTick int64
|
||||
}
|
||||
|
||||
// NewBucket returns a new token bucket that fills at the
|
||||
// rate of one token every fillInterval, up to the given
|
||||
// maximum capacity. Both arguments must be
|
||||
// positive. The bucket is initially full.
|
||||
func NewBucket(fillInterval time.Duration, capacity int64) *Bucket {
|
||||
return NewBucketWithClock(fillInterval, capacity, nil)
|
||||
}
|
||||
|
||||
// NewBucketWithClock is identical to NewBucket but injects a testable clock
|
||||
// interface.
|
||||
func NewBucketWithClock(fillInterval time.Duration, capacity int64, clock Clock) *Bucket {
|
||||
return NewBucketWithQuantumAndClock(fillInterval, capacity, 1, clock)
|
||||
}
|
||||
|
||||
// rateMargin specifes the allowed variance of actual
|
||||
// rate from specified rate. 1% seems reasonable.
|
||||
const rateMargin = 0.01
|
||||
|
||||
// NewBucketWithRate returns a token bucket that fills the bucket
|
||||
// at the rate of rate tokens per second up to the given
|
||||
// maximum capacity. Because of limited clock resolution,
|
||||
// at high rates, the actual rate may be up to 1% different from the
|
||||
// specified rate.
|
||||
func NewBucketWithRate(rate float64, capacity int64) *Bucket {
|
||||
return NewBucketWithRateAndClock(rate, capacity, nil)
|
||||
}
|
||||
|
||||
// NewBucketWithRateAndClock is identical to NewBucketWithRate but injects a
|
||||
// testable clock interface.
|
||||
func NewBucketWithRateAndClock(rate float64, capacity int64, clock Clock) *Bucket {
|
||||
// Use the same bucket each time through the loop
|
||||
// to save allocations.
|
||||
tb := NewBucketWithQuantumAndClock(1, capacity, 1, clock)
|
||||
for quantum := int64(1); quantum < 1<<50; quantum = nextQuantum(quantum) {
|
||||
fillInterval := time.Duration(1e9 * float64(quantum) / rate)
|
||||
if fillInterval <= 0 {
|
||||
continue
|
||||
}
|
||||
tb.fillInterval = fillInterval
|
||||
tb.quantum = quantum
|
||||
if diff := math.Abs(tb.Rate() - rate); diff/rate <= rateMargin {
|
||||
return tb
|
||||
}
|
||||
}
|
||||
panic("cannot find suitable quantum for " + strconv.FormatFloat(rate, 'g', -1, 64))
|
||||
}
|
||||
|
||||
// nextQuantum returns the next quantum to try after q.
|
||||
// We grow the quantum exponentially, but slowly, so we
|
||||
// get a good fit in the lower numbers.
|
||||
func nextQuantum(q int64) int64 {
|
||||
q1 := q * 11 / 10
|
||||
if q1 == q {
|
||||
q1++
|
||||
}
|
||||
return q1
|
||||
}
|
||||
|
||||
// NewBucketWithQuantum is similar to NewBucket, but allows
|
||||
// the specification of the quantum size - quantum tokens
|
||||
// are added every fillInterval.
|
||||
func NewBucketWithQuantum(fillInterval time.Duration, capacity, quantum int64) *Bucket {
|
||||
return NewBucketWithQuantumAndClock(fillInterval, capacity, quantum, nil)
|
||||
}
|
||||
|
||||
// NewBucketWithQuantumAndClock is like NewBucketWithQuantum, but
|
||||
// also has a clock argument that allows clients to fake the passing
|
||||
// of time. If clock is nil, the system clock will be used.
|
||||
func NewBucketWithQuantumAndClock(fillInterval time.Duration, capacity, quantum int64, clock Clock) *Bucket {
|
||||
if clock == nil {
|
||||
clock = realClock{}
|
||||
}
|
||||
if fillInterval <= 0 {
|
||||
panic("token bucket fill interval is not > 0")
|
||||
}
|
||||
if capacity <= 0 {
|
||||
panic("token bucket capacity is not > 0")
|
||||
}
|
||||
if quantum <= 0 {
|
||||
panic("token bucket quantum is not > 0")
|
||||
}
|
||||
return &Bucket{
|
||||
clock: clock,
|
||||
startTime: clock.Now(),
|
||||
latestTick: 0,
|
||||
fillInterval: fillInterval,
|
||||
capacity: capacity,
|
||||
quantum: quantum,
|
||||
availableTokens: capacity,
|
||||
}
|
||||
}
|
||||
|
||||
// Wait takes count tokens from the bucket, waiting until they are
|
||||
// available.
|
||||
func (tb *Bucket) Wait(count int64) {
|
||||
if d := tb.Take(count); d > 0 {
|
||||
tb.clock.Sleep(d)
|
||||
}
|
||||
}
|
||||
|
||||
// WaitMaxDuration is like Wait except that it will
|
||||
// only take tokens from the bucket if it needs to wait
|
||||
// for no greater than maxWait. It reports whether
|
||||
// any tokens have been removed from the bucket
|
||||
// If no tokens have been removed, it returns immediately.
|
||||
func (tb *Bucket) WaitMaxDuration(count int64, maxWait time.Duration) bool {
|
||||
d, ok := tb.TakeMaxDuration(count, maxWait)
|
||||
if d > 0 {
|
||||
tb.clock.Sleep(d)
|
||||
}
|
||||
return ok
|
||||
}
|
||||
|
||||
const infinityDuration time.Duration = 0x7fffffffffffffff
|
||||
|
||||
// Take takes count tokens from the bucket without blocking. It returns
|
||||
// the time that the caller should wait until the tokens are actually
|
||||
// available.
|
||||
//
|
||||
// Note that if the request is irrevocable - there is no way to return
|
||||
// tokens to the bucket once this method commits us to taking them.
|
||||
func (tb *Bucket) Take(count int64) time.Duration {
|
||||
tb.mu.Lock()
|
||||
defer tb.mu.Unlock()
|
||||
d, _ := tb.take(tb.clock.Now(), count, infinityDuration)
|
||||
return d
|
||||
}
|
||||
|
||||
// TakeMaxDuration is like Take, except that
|
||||
// it will only take tokens from the bucket if the wait
|
||||
// time for the tokens is no greater than maxWait.
|
||||
//
|
||||
// If it would take longer than maxWait for the tokens
|
||||
// to become available, it does nothing and reports false,
|
||||
// otherwise it returns the time that the caller should
|
||||
// wait until the tokens are actually available, and reports
|
||||
// true.
|
||||
func (tb *Bucket) TakeMaxDuration(count int64, maxWait time.Duration) (time.Duration, bool) {
|
||||
tb.mu.Lock()
|
||||
defer tb.mu.Unlock()
|
||||
return tb.take(tb.clock.Now(), count, maxWait)
|
||||
}
|
||||
|
||||
// TakeAvailable takes up to count immediately available tokens from the
|
||||
// bucket. It returns the number of tokens removed, or zero if there are
|
||||
// no available tokens. It does not block.
|
||||
func (tb *Bucket) TakeAvailable(count int64) int64 {
|
||||
tb.mu.Lock()
|
||||
defer tb.mu.Unlock()
|
||||
return tb.takeAvailable(tb.clock.Now(), count)
|
||||
}
|
||||
|
||||
// takeAvailable is the internal version of TakeAvailable - it takes the
|
||||
// current time as an argument to enable easy testing.
|
||||
func (tb *Bucket) takeAvailable(now time.Time, count int64) int64 {
|
||||
if count <= 0 {
|
||||
return 0
|
||||
}
|
||||
tb.adjustavailableTokens(tb.currentTick(now))
|
||||
if tb.availableTokens <= 0 {
|
||||
return 0
|
||||
}
|
||||
if count > tb.availableTokens {
|
||||
count = tb.availableTokens
|
||||
}
|
||||
tb.availableTokens -= count
|
||||
return count
|
||||
}
|
||||
|
||||
// Available returns the number of available tokens. It will be negative
|
||||
// when there are consumers waiting for tokens. Note that if this
|
||||
// returns greater than zero, it does not guarantee that calls that take
|
||||
// tokens from the buffer will succeed, as the number of available
|
||||
// tokens could have changed in the meantime. This method is intended
|
||||
// primarily for metrics reporting and debugging.
|
||||
func (tb *Bucket) Available() int64 {
|
||||
return tb.available(tb.clock.Now())
|
||||
}
|
||||
|
||||
// available is the internal version of available - it takes the current time as
|
||||
// an argument to enable easy testing.
|
||||
func (tb *Bucket) available(now time.Time) int64 {
|
||||
tb.mu.Lock()
|
||||
defer tb.mu.Unlock()
|
||||
tb.adjustavailableTokens(tb.currentTick(now))
|
||||
return tb.availableTokens
|
||||
}
|
||||
|
||||
// Capacity returns the capacity that the bucket was created with.
|
||||
func (tb *Bucket) Capacity() int64 {
|
||||
return tb.capacity
|
||||
}
|
||||
|
||||
// Rate returns the fill rate of the bucket, in tokens per second.
|
||||
func (tb *Bucket) Rate() float64 {
|
||||
return 1e9 * float64(tb.quantum) / float64(tb.fillInterval)
|
||||
}
|
||||
|
||||
// take is the internal version of Take - it takes the current time as
|
||||
// an argument to enable easy testing.
|
||||
func (tb *Bucket) take(now time.Time, count int64, maxWait time.Duration) (time.Duration, bool) {
|
||||
if count <= 0 {
|
||||
return 0, true
|
||||
}
|
||||
|
||||
tick := tb.currentTick(now)
|
||||
tb.adjustavailableTokens(tick)
|
||||
avail := tb.availableTokens - count
|
||||
if avail >= 0 {
|
||||
tb.availableTokens = avail
|
||||
return 0, true
|
||||
}
|
||||
// Round up the missing tokens to the nearest multiple
|
||||
// of quantum - the tokens won't be available until
|
||||
// that tick.
|
||||
|
||||
// endTick holds the tick when all the requested tokens will
|
||||
// become available.
|
||||
endTick := tick + (-avail+tb.quantum-1)/tb.quantum
|
||||
endTime := tb.startTime.Add(time.Duration(endTick) * tb.fillInterval)
|
||||
waitTime := endTime.Sub(now)
|
||||
if waitTime > maxWait {
|
||||
return 0, false
|
||||
}
|
||||
tb.availableTokens = avail
|
||||
return waitTime, true
|
||||
}
|
||||
|
||||
// currentTick returns the current time tick, measured
|
||||
// from tb.startTime.
|
||||
func (tb *Bucket) currentTick(now time.Time) int64 {
|
||||
return int64(now.Sub(tb.startTime) / tb.fillInterval)
|
||||
}
|
||||
|
||||
// adjustavailableTokens adjusts the current number of tokens
|
||||
// available in the bucket at the given time, which must
|
||||
// be in the future (positive) with respect to tb.latestTick.
|
||||
func (tb *Bucket) adjustavailableTokens(tick int64) {
|
||||
if tb.availableTokens >= tb.capacity {
|
||||
return
|
||||
}
|
||||
tb.availableTokens += (tick - tb.latestTick) * tb.quantum
|
||||
if tb.availableTokens > tb.capacity {
|
||||
tb.availableTokens = tb.capacity
|
||||
}
|
||||
tb.latestTick = tick
|
||||
return
|
||||
}
|
||||
|
||||
// Clock represents the passage of time in a way that
|
||||
// can be faked out for tests.
|
||||
type Clock interface {
|
||||
// Now returns the current time.
|
||||
Now() time.Time
|
||||
// Sleep sleeps for at least the given duration.
|
||||
Sleep(d time.Duration)
|
||||
}
|
||||
|
||||
// realClock implements Clock in terms of standard time functions.
|
||||
type realClock struct{}
|
||||
|
||||
// Now implements Clock.Now by calling time.Now.
|
||||
func (realClock) Now() time.Time {
|
||||
return time.Now()
|
||||
}
|
||||
|
||||
// Now implements Clock.Sleep by calling time.Sleep.
|
||||
func (realClock) Sleep(d time.Duration) {
|
||||
time.Sleep(d)
|
||||
}
|
||||
51
vendor/github.com/juju/ratelimit/reader.go
generated
vendored
Normal file
51
vendor/github.com/juju/ratelimit/reader.go
generated
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
// Copyright 2014 Canonical Ltd.
|
||||
// Licensed under the LGPLv3 with static-linking exception.
|
||||
// See LICENCE file for details.
|
||||
|
||||
package ratelimit
|
||||
|
||||
import "io"
|
||||
|
||||
type reader struct {
|
||||
r io.Reader
|
||||
bucket *Bucket
|
||||
}
|
||||
|
||||
// Reader returns a reader that is rate limited by
|
||||
// the given token bucket. Each token in the bucket
|
||||
// represents one byte.
|
||||
func Reader(r io.Reader, bucket *Bucket) io.Reader {
|
||||
return &reader{
|
||||
r: r,
|
||||
bucket: bucket,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *reader) Read(buf []byte) (int, error) {
|
||||
n, err := r.r.Read(buf)
|
||||
if n <= 0 {
|
||||
return n, err
|
||||
}
|
||||
r.bucket.Wait(int64(n))
|
||||
return n, err
|
||||
}
|
||||
|
||||
type writer struct {
|
||||
w io.Writer
|
||||
bucket *Bucket
|
||||
}
|
||||
|
||||
// Writer returns a reader that is rate limited by
|
||||
// the given token bucket. Each token in the bucket
|
||||
// represents one byte.
|
||||
func Writer(w io.Writer, bucket *Bucket) io.Writer {
|
||||
return &writer{
|
||||
w: w,
|
||||
bucket: bucket,
|
||||
}
|
||||
}
|
||||
|
||||
func (w *writer) Write(buf []byte) (int, error) {
|
||||
w.bucket.Wait(int64(len(buf)))
|
||||
return w.w.Write(buf)
|
||||
}
|
||||
3
vendor/golang.org/x/sys/AUTHORS
generated
vendored
Normal file
3
vendor/golang.org/x/sys/AUTHORS
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
# This source code refers to The Go Authors for copyright purposes.
|
||||
# The master list of authors is in the main Go distribution,
|
||||
# visible at http://tip.golang.org/AUTHORS.
|
||||
3
vendor/golang.org/x/sys/CONTRIBUTORS
generated
vendored
Normal file
3
vendor/golang.org/x/sys/CONTRIBUTORS
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
# This source code was written by the Go contributors.
|
||||
# The master list of contributors is in the main Go distribution,
|
||||
# visible at http://tip.golang.org/CONTRIBUTORS.
|
||||
27
vendor/golang.org/x/sys/LICENSE
generated
vendored
Normal file
27
vendor/golang.org/x/sys/LICENSE
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
22
vendor/golang.org/x/sys/PATENTS
generated
vendored
Normal file
22
vendor/golang.org/x/sys/PATENTS
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
Additional IP Rights Grant (Patents)
|
||||
|
||||
"This implementation" means the copyrightable works distributed by
|
||||
Google as part of the Go project.
|
||||
|
||||
Google hereby grants to You a perpetual, worldwide, non-exclusive,
|
||||
no-charge, royalty-free, irrevocable (except as stated in this section)
|
||||
patent license to make, have made, use, offer to sell, sell, import,
|
||||
transfer and otherwise run, modify and propagate the contents of this
|
||||
implementation of Go, where such license applies only to those patent
|
||||
claims, both currently owned or controlled by Google and acquired in
|
||||
the future, licensable by Google that are necessarily infringed by this
|
||||
implementation of Go. This grant does not include claims that would be
|
||||
infringed only as a consequence of further modification of this
|
||||
implementation. If you or your agent or exclusive licensee institute or
|
||||
order or agree to the institution of patent litigation against any
|
||||
entity (including a cross-claim or counterclaim in a lawsuit) alleging
|
||||
that this implementation of Go or any code incorporated within this
|
||||
implementation of Go constitutes direct or contributory patent
|
||||
infringement, or inducement of patent infringement, then any patent
|
||||
rights granted to you under this License for this implementation of Go
|
||||
shall terminate as of the date such litigation is filed.
|
||||
2
vendor/golang.org/x/sys/unix/.gitignore
generated
vendored
Normal file
2
vendor/golang.org/x/sys/unix/.gitignore
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
_obj/
|
||||
unix.test
|
||||
173
vendor/golang.org/x/sys/unix/README.md
generated
vendored
Normal file
173
vendor/golang.org/x/sys/unix/README.md
generated
vendored
Normal file
@ -0,0 +1,173 @@
|
||||
# Building `sys/unix`
|
||||
|
||||
The sys/unix package provides access to the raw system call interface of the
|
||||
underlying operating system. See: https://godoc.org/golang.org/x/sys/unix
|
||||
|
||||
Porting Go to a new architecture/OS combination or adding syscalls, types, or
|
||||
constants to an existing architecture/OS pair requires some manual effort;
|
||||
however, there are tools that automate much of the process.
|
||||
|
||||
## Build Systems
|
||||
|
||||
There are currently two ways we generate the necessary files. We are currently
|
||||
migrating the build system to use containers so the builds are reproducible.
|
||||
This is being done on an OS-by-OS basis. Please update this documentation as
|
||||
components of the build system change.
|
||||
|
||||
### Old Build System (currently for `GOOS != "Linux" || GOARCH == "sparc64"`)
|
||||
|
||||
The old build system generates the Go files based on the C header files
|
||||
present on your system. This means that files
|
||||
for a given GOOS/GOARCH pair must be generated on a system with that OS and
|
||||
architecture. This also means that the generated code can differ from system
|
||||
to system, based on differences in the header files.
|
||||
|
||||
To avoid this, if you are using the old build system, only generate the Go
|
||||
files on an installation with unmodified header files. It is also important to
|
||||
keep track of which version of the OS the files were generated from (ex.
|
||||
Darwin 14 vs Darwin 15). This makes it easier to track the progress of changes
|
||||
and have each OS upgrade correspond to a single change.
|
||||
|
||||
To build the files for your current OS and architecture, make sure GOOS and
|
||||
GOARCH are set correctly and run `mkall.sh`. This will generate the files for
|
||||
your specific system. Running `mkall.sh -n` shows the commands that will be run.
|
||||
|
||||
Requirements: bash, perl, go
|
||||
|
||||
### New Build System (currently for `GOOS == "Linux" && GOARCH != "sparc64"`)
|
||||
|
||||
The new build system uses a Docker container to generate the go files directly
|
||||
from source checkouts of the kernel and various system libraries. This means
|
||||
that on any platform that supports Docker, all the files using the new build
|
||||
system can be generated at once, and generated files will not change based on
|
||||
what the person running the scripts has installed on their computer.
|
||||
|
||||
The OS specific files for the new build system are located in the `${GOOS}`
|
||||
directory, and the build is coordinated by the `${GOOS}/mkall.go` program. When
|
||||
the kernel or system library updates, modify the Dockerfile at
|
||||
`${GOOS}/Dockerfile` to checkout the new release of the source.
|
||||
|
||||
To build all the files under the new build system, you must be on an amd64/Linux
|
||||
system and have your GOOS and GOARCH set accordingly. Running `mkall.sh` will
|
||||
then generate all of the files for all of the GOOS/GOARCH pairs in the new build
|
||||
system. Running `mkall.sh -n` shows the commands that will be run.
|
||||
|
||||
Requirements: bash, perl, go, docker
|
||||
|
||||
## Component files
|
||||
|
||||
This section describes the various files used in the code generation process.
|
||||
It also contains instructions on how to modify these files to add a new
|
||||
architecture/OS or to add additional syscalls, types, or constants. Note that
|
||||
if you are using the new build system, the scripts cannot be called normally.
|
||||
They must be called from within the docker container.
|
||||
|
||||
### asm files
|
||||
|
||||
The hand-written assembly file at `asm_${GOOS}_${GOARCH}.s` implements system
|
||||
call dispatch. There are three entry points:
|
||||
```
|
||||
func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
|
||||
func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
|
||||
func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
|
||||
```
|
||||
The first and second are the standard ones; they differ only in how many
|
||||
arguments can be passed to the kernel. The third is for low-level use by the
|
||||
ForkExec wrapper. Unlike the first two, it does not call into the scheduler to
|
||||
let it know that a system call is running.
|
||||
|
||||
When porting Go to an new architecture/OS, this file must be implemented for
|
||||
each GOOS/GOARCH pair.
|
||||
|
||||
### mksysnum
|
||||
|
||||
Mksysnum is a script located at `${GOOS}/mksysnum.pl` (or `mksysnum_${GOOS}.pl`
|
||||
for the old system). This script takes in a list of header files containing the
|
||||
syscall number declarations and parses them to produce the corresponding list of
|
||||
Go numeric constants. See `zsysnum_${GOOS}_${GOARCH}.go` for the generated
|
||||
constants.
|
||||
|
||||
Adding new syscall numbers is mostly done by running the build on a sufficiently
|
||||
new installation of the target OS (or updating the source checkouts for the
|
||||
new build system). However, depending on the OS, you make need to update the
|
||||
parsing in mksysnum.
|
||||
|
||||
### mksyscall.pl
|
||||
|
||||
The `syscall.go`, `syscall_${GOOS}.go`, `syscall_${GOOS}_${GOARCH}.go` are
|
||||
hand-written Go files which implement system calls (for unix, the specific OS,
|
||||
or the specific OS/Architecture pair respectively) that need special handling
|
||||
and list `//sys` comments giving prototypes for ones that can be generated.
|
||||
|
||||
The mksyscall.pl script takes the `//sys` and `//sysnb` comments and converts
|
||||
them into syscalls. This requires the name of the prototype in the comment to
|
||||
match a syscall number in the `zsysnum_${GOOS}_${GOARCH}.go` file. The function
|
||||
prototype can be exported (capitalized) or not.
|
||||
|
||||
Adding a new syscall often just requires adding a new `//sys` function prototype
|
||||
with the desired arguments and a capitalized name so it is exported. However, if
|
||||
you want the interface to the syscall to be different, often one will make an
|
||||
unexported `//sys` prototype, an then write a custom wrapper in
|
||||
`syscall_${GOOS}.go`.
|
||||
|
||||
### types files
|
||||
|
||||
For each OS, there is a hand-written Go file at `${GOOS}/types.go` (or
|
||||
`types_${GOOS}.go` on the old system). This file includes standard C headers and
|
||||
creates Go type aliases to the corresponding C types. The file is then fed
|
||||
through godef to get the Go compatible definitions. Finally, the generated code
|
||||
is fed though mkpost.go to format the code correctly and remove any hidden or
|
||||
private identifiers. This cleaned-up code is written to
|
||||
`ztypes_${GOOS}_${GOARCH}.go`.
|
||||
|
||||
The hardest part about preparing this file is figuring out which headers to
|
||||
include and which symbols need to be `#define`d to get the actual data
|
||||
structures that pass through to the kernel system calls. Some C libraries
|
||||
preset alternate versions for binary compatibility and translate them on the
|
||||
way in and out of system calls, but there is almost always a `#define` that can
|
||||
get the real ones.
|
||||
See `types_darwin.go` and `linux/types.go` for examples.
|
||||
|
||||
To add a new type, add in the necessary include statement at the top of the
|
||||
file (if it is not already there) and add in a type alias line. Note that if
|
||||
your type is significantly different on different architectures, you may need
|
||||
some `#if/#elif` macros in your include statements.
|
||||
|
||||
### mkerrors.sh
|
||||
|
||||
This script is used to generate the system's various constants. This doesn't
|
||||
just include the error numbers and error strings, but also the signal numbers
|
||||
an a wide variety of miscellaneous constants. The constants come from the list
|
||||
of include files in the `includes_${uname}` variable. A regex then picks out
|
||||
the desired `#define` statements, and generates the corresponding Go constants.
|
||||
The error numbers and strings are generated from `#include <errno.h>`, and the
|
||||
signal numbers and strings are generated from `#include <signal.h>`. All of
|
||||
these constants are written to `zerrors_${GOOS}_${GOARCH}.go` via a C program,
|
||||
`_errors.c`, which prints out all the constants.
|
||||
|
||||
To add a constant, add the header that includes it to the appropriate variable.
|
||||
Then, edit the regex (if necessary) to match the desired constant. Avoid making
|
||||
the regex too broad to avoid matching unintended constants.
|
||||
|
||||
|
||||
## Generated files
|
||||
|
||||
### `zerror_${GOOS}_${GOARCH}.go`
|
||||
|
||||
A file containing all of the system's generated error numbers, error strings,
|
||||
signal numbers, and constants. Generated by `mkerrors.sh` (see above).
|
||||
|
||||
### `zsyscall_${GOOS}_${GOARCH}.go`
|
||||
|
||||
A file containing all the generated syscalls for a specific GOOS and GOARCH.
|
||||
Generated by `mksyscall.pl` (see above).
|
||||
|
||||
### `zsysnum_${GOOS}_${GOARCH}.go`
|
||||
|
||||
A list of numeric constants for all the syscall number of the specific GOOS
|
||||
and GOARCH. Generated by mksysnum (see above).
|
||||
|
||||
### `ztypes_${GOOS}_${GOARCH}.go`
|
||||
|
||||
A file containing Go types for passing into (or returning from) syscalls.
|
||||
Generated by godefs and the types file (see above).
|
||||
124
vendor/golang.org/x/sys/unix/affinity_linux.go
generated
vendored
Normal file
124
vendor/golang.org/x/sys/unix/affinity_linux.go
generated
vendored
Normal file
@ -0,0 +1,124 @@
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// CPU affinity functions
|
||||
|
||||
package unix
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const cpuSetSize = _CPU_SETSIZE / _NCPUBITS
|
||||
|
||||
// CPUSet represents a CPU affinity mask.
|
||||
type CPUSet [cpuSetSize]cpuMask
|
||||
|
||||
func schedAffinity(trap uintptr, pid int, set *CPUSet) error {
|
||||
_, _, e := RawSyscall(trap, uintptr(pid), uintptr(unsafe.Sizeof(*set)), uintptr(unsafe.Pointer(set)))
|
||||
if e != 0 {
|
||||
return errnoErr(e)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SchedGetaffinity gets the CPU affinity mask of the thread specified by pid.
|
||||
// If pid is 0 the calling thread is used.
|
||||
func SchedGetaffinity(pid int, set *CPUSet) error {
|
||||
return schedAffinity(SYS_SCHED_GETAFFINITY, pid, set)
|
||||
}
|
||||
|
||||
// SchedSetaffinity sets the CPU affinity mask of the thread specified by pid.
|
||||
// If pid is 0 the calling thread is used.
|
||||
func SchedSetaffinity(pid int, set *CPUSet) error {
|
||||
return schedAffinity(SYS_SCHED_SETAFFINITY, pid, set)
|
||||
}
|
||||
|
||||
// Zero clears the set s, so that it contains no CPUs.
|
||||
func (s *CPUSet) Zero() {
|
||||
for i := range s {
|
||||
s[i] = 0
|
||||
}
|
||||
}
|
||||
|
||||
func cpuBitsIndex(cpu int) int {
|
||||
return cpu / _NCPUBITS
|
||||
}
|
||||
|
||||
func cpuBitsMask(cpu int) cpuMask {
|
||||
return cpuMask(1 << (uint(cpu) % _NCPUBITS))
|
||||
}
|
||||
|
||||
// Set adds cpu to the set s.
|
||||
func (s *CPUSet) Set(cpu int) {
|
||||
i := cpuBitsIndex(cpu)
|
||||
if i < len(s) {
|
||||
s[i] |= cpuBitsMask(cpu)
|
||||
}
|
||||
}
|
||||
|
||||
// Clear removes cpu from the set s.
|
||||
func (s *CPUSet) Clear(cpu int) {
|
||||
i := cpuBitsIndex(cpu)
|
||||
if i < len(s) {
|
||||
s[i] &^= cpuBitsMask(cpu)
|
||||
}
|
||||
}
|
||||
|
||||
// IsSet reports whether cpu is in the set s.
|
||||
func (s *CPUSet) IsSet(cpu int) bool {
|
||||
i := cpuBitsIndex(cpu)
|
||||
if i < len(s) {
|
||||
return s[i]&cpuBitsMask(cpu) != 0
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Count returns the number of CPUs in the set s.
|
||||
func (s *CPUSet) Count() int {
|
||||
c := 0
|
||||
for _, b := range s {
|
||||
c += onesCount64(uint64(b))
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// onesCount64 is a copy of Go 1.9's math/bits.OnesCount64.
|
||||
// Once this package can require Go 1.9, we can delete this
|
||||
// and update the caller to use bits.OnesCount64.
|
||||
func onesCount64(x uint64) int {
|
||||
const m0 = 0x5555555555555555 // 01010101 ...
|
||||
const m1 = 0x3333333333333333 // 00110011 ...
|
||||
const m2 = 0x0f0f0f0f0f0f0f0f // 00001111 ...
|
||||
const m3 = 0x00ff00ff00ff00ff // etc.
|
||||
const m4 = 0x0000ffff0000ffff
|
||||
|
||||
// Implementation: Parallel summing of adjacent bits.
|
||||
// See "Hacker's Delight", Chap. 5: Counting Bits.
|
||||
// The following pattern shows the general approach:
|
||||
//
|
||||
// x = x>>1&(m0&m) + x&(m0&m)
|
||||
// x = x>>2&(m1&m) + x&(m1&m)
|
||||
// x = x>>4&(m2&m) + x&(m2&m)
|
||||
// x = x>>8&(m3&m) + x&(m3&m)
|
||||
// x = x>>16&(m4&m) + x&(m4&m)
|
||||
// x = x>>32&(m5&m) + x&(m5&m)
|
||||
// return int(x)
|
||||
//
|
||||
// Masking (& operations) can be left away when there's no
|
||||
// danger that a field's sum will carry over into the next
|
||||
// field: Since the result cannot be > 64, 8 bits is enough
|
||||
// and we can ignore the masks for the shifts by 8 and up.
|
||||
// Per "Hacker's Delight", the first line can be simplified
|
||||
// more, but it saves at best one instruction, so we leave
|
||||
// it alone for clarity.
|
||||
const m = 1<<64 - 1
|
||||
x = x>>1&(m0&m) + x&(m0&m)
|
||||
x = x>>2&(m1&m) + x&(m1&m)
|
||||
x = (x>>4 + x) & (m2 & m)
|
||||
x += x >> 8
|
||||
x += x >> 16
|
||||
x += x >> 32
|
||||
return int(x) & (1<<7 - 1)
|
||||
}
|
||||
14
vendor/golang.org/x/sys/unix/aliases.go
generated
vendored
Normal file
14
vendor/golang.org/x/sys/unix/aliases.go
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||
// +build go1.9
|
||||
|
||||
package unix
|
||||
|
||||
import "syscall"
|
||||
|
||||
type Signal = syscall.Signal
|
||||
type Errno = syscall.Errno
|
||||
type SysProcAttr = syscall.SysProcAttr
|
||||
29
vendor/golang.org/x/sys/unix/asm_darwin_386.s
generated
vendored
Normal file
29
vendor/golang.org/x/sys/unix/asm_darwin_386.s
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
//
|
||||
// System call support for 386, Darwin
|
||||
//
|
||||
|
||||
// Just jump to package syscall's implementation for all these functions.
|
||||
// The runtime may know about them.
|
||||
|
||||
TEXT ·Syscall(SB),NOSPLIT,$0-28
|
||||
JMP syscall·Syscall(SB)
|
||||
|
||||
TEXT ·Syscall6(SB),NOSPLIT,$0-40
|
||||
JMP syscall·Syscall6(SB)
|
||||
|
||||
TEXT ·Syscall9(SB),NOSPLIT,$0-52
|
||||
JMP syscall·Syscall9(SB)
|
||||
|
||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
|
||||
JMP syscall·RawSyscall(SB)
|
||||
|
||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
|
||||
JMP syscall·RawSyscall6(SB)
|
||||
29
vendor/golang.org/x/sys/unix/asm_darwin_amd64.s
generated
vendored
Normal file
29
vendor/golang.org/x/sys/unix/asm_darwin_amd64.s
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
//
|
||||
// System call support for AMD64, Darwin
|
||||
//
|
||||
|
||||
// Just jump to package syscall's implementation for all these functions.
|
||||
// The runtime may know about them.
|
||||
|
||||
TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||
JMP syscall·Syscall(SB)
|
||||
|
||||
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||
JMP syscall·Syscall6(SB)
|
||||
|
||||
TEXT ·Syscall9(SB),NOSPLIT,$0-104
|
||||
JMP syscall·Syscall9(SB)
|
||||
|
||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||
JMP syscall·RawSyscall(SB)
|
||||
|
||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||
JMP syscall·RawSyscall6(SB)
|
||||
30
vendor/golang.org/x/sys/unix/asm_darwin_arm.s
generated
vendored
Normal file
30
vendor/golang.org/x/sys/unix/asm_darwin_arm.s
generated
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
// +build arm,darwin
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
//
|
||||
// System call support for ARM, Darwin
|
||||
//
|
||||
|
||||
// Just jump to package syscall's implementation for all these functions.
|
||||
// The runtime may know about them.
|
||||
|
||||
TEXT ·Syscall(SB),NOSPLIT,$0-28
|
||||
B syscall·Syscall(SB)
|
||||
|
||||
TEXT ·Syscall6(SB),NOSPLIT,$0-40
|
||||
B syscall·Syscall6(SB)
|
||||
|
||||
TEXT ·Syscall9(SB),NOSPLIT,$0-52
|
||||
B syscall·Syscall9(SB)
|
||||
|
||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
|
||||
B syscall·RawSyscall(SB)
|
||||
|
||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
|
||||
B syscall·RawSyscall6(SB)
|
||||
30
vendor/golang.org/x/sys/unix/asm_darwin_arm64.s
generated
vendored
Normal file
30
vendor/golang.org/x/sys/unix/asm_darwin_arm64.s
generated
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
// +build arm64,darwin
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
//
|
||||
// System call support for AMD64, Darwin
|
||||
//
|
||||
|
||||
// Just jump to package syscall's implementation for all these functions.
|
||||
// The runtime may know about them.
|
||||
|
||||
TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||
B syscall·Syscall(SB)
|
||||
|
||||
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||
B syscall·Syscall6(SB)
|
||||
|
||||
TEXT ·Syscall9(SB),NOSPLIT,$0-104
|
||||
B syscall·Syscall9(SB)
|
||||
|
||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||
B syscall·RawSyscall(SB)
|
||||
|
||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||
B syscall·RawSyscall6(SB)
|
||||
29
vendor/golang.org/x/sys/unix/asm_dragonfly_amd64.s
generated
vendored
Normal file
29
vendor/golang.org/x/sys/unix/asm_dragonfly_amd64.s
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
//
|
||||
// System call support for AMD64, DragonFly
|
||||
//
|
||||
|
||||
// Just jump to package syscall's implementation for all these functions.
|
||||
// The runtime may know about them.
|
||||
|
||||
TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||
JMP syscall·Syscall(SB)
|
||||
|
||||
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||
JMP syscall·Syscall6(SB)
|
||||
|
||||
TEXT ·Syscall9(SB),NOSPLIT,$0-104
|
||||
JMP syscall·Syscall9(SB)
|
||||
|
||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||
JMP syscall·RawSyscall(SB)
|
||||
|
||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||
JMP syscall·RawSyscall6(SB)
|
||||
29
vendor/golang.org/x/sys/unix/asm_freebsd_386.s
generated
vendored
Normal file
29
vendor/golang.org/x/sys/unix/asm_freebsd_386.s
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
//
|
||||
// System call support for 386, FreeBSD
|
||||
//
|
||||
|
||||
// Just jump to package syscall's implementation for all these functions.
|
||||
// The runtime may know about them.
|
||||
|
||||
TEXT ·Syscall(SB),NOSPLIT,$0-28
|
||||
JMP syscall·Syscall(SB)
|
||||
|
||||
TEXT ·Syscall6(SB),NOSPLIT,$0-40
|
||||
JMP syscall·Syscall6(SB)
|
||||
|
||||
TEXT ·Syscall9(SB),NOSPLIT,$0-52
|
||||
JMP syscall·Syscall9(SB)
|
||||
|
||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
|
||||
JMP syscall·RawSyscall(SB)
|
||||
|
||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
|
||||
JMP syscall·RawSyscall6(SB)
|
||||
29
vendor/golang.org/x/sys/unix/asm_freebsd_amd64.s
generated
vendored
Normal file
29
vendor/golang.org/x/sys/unix/asm_freebsd_amd64.s
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
//
|
||||
// System call support for AMD64, FreeBSD
|
||||
//
|
||||
|
||||
// Just jump to package syscall's implementation for all these functions.
|
||||
// The runtime may know about them.
|
||||
|
||||
TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||
JMP syscall·Syscall(SB)
|
||||
|
||||
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||
JMP syscall·Syscall6(SB)
|
||||
|
||||
TEXT ·Syscall9(SB),NOSPLIT,$0-104
|
||||
JMP syscall·Syscall9(SB)
|
||||
|
||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||
JMP syscall·RawSyscall(SB)
|
||||
|
||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||
JMP syscall·RawSyscall6(SB)
|
||||
29
vendor/golang.org/x/sys/unix/asm_freebsd_arm.s
generated
vendored
Normal file
29
vendor/golang.org/x/sys/unix/asm_freebsd_arm.s
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
//
|
||||
// System call support for ARM, FreeBSD
|
||||
//
|
||||
|
||||
// Just jump to package syscall's implementation for all these functions.
|
||||
// The runtime may know about them.
|
||||
|
||||
TEXT ·Syscall(SB),NOSPLIT,$0-28
|
||||
B syscall·Syscall(SB)
|
||||
|
||||
TEXT ·Syscall6(SB),NOSPLIT,$0-40
|
||||
B syscall·Syscall6(SB)
|
||||
|
||||
TEXT ·Syscall9(SB),NOSPLIT,$0-52
|
||||
B syscall·Syscall9(SB)
|
||||
|
||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
|
||||
B syscall·RawSyscall(SB)
|
||||
|
||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
|
||||
B syscall·RawSyscall6(SB)
|
||||
65
vendor/golang.org/x/sys/unix/asm_linux_386.s
generated
vendored
Normal file
65
vendor/golang.org/x/sys/unix/asm_linux_386.s
generated
vendored
Normal file
@ -0,0 +1,65 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
//
|
||||
// System calls for 386, Linux
|
||||
//
|
||||
|
||||
// See ../runtime/sys_linux_386.s for the reason why we always use int 0x80
|
||||
// instead of the glibc-specific "CALL 0x10(GS)".
|
||||
#define INVOKE_SYSCALL INT $0x80
|
||||
|
||||
// Just jump to package syscall's implementation for all these functions.
|
||||
// The runtime may know about them.
|
||||
|
||||
TEXT ·Syscall(SB),NOSPLIT,$0-28
|
||||
JMP syscall·Syscall(SB)
|
||||
|
||||
TEXT ·Syscall6(SB),NOSPLIT,$0-40
|
||||
JMP syscall·Syscall6(SB)
|
||||
|
||||
TEXT ·SyscallNoError(SB),NOSPLIT,$0-24
|
||||
CALL runtime·entersyscall(SB)
|
||||
MOVL trap+0(FP), AX // syscall entry
|
||||
MOVL a1+4(FP), BX
|
||||
MOVL a2+8(FP), CX
|
||||
MOVL a3+12(FP), DX
|
||||
MOVL $0, SI
|
||||
MOVL $0, DI
|
||||
INVOKE_SYSCALL
|
||||
MOVL AX, r1+16(FP)
|
||||
MOVL DX, r2+20(FP)
|
||||
CALL runtime·exitsyscall(SB)
|
||||
RET
|
||||
|
||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
|
||||
JMP syscall·RawSyscall(SB)
|
||||
|
||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
|
||||
JMP syscall·RawSyscall6(SB)
|
||||
|
||||
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-24
|
||||
MOVL trap+0(FP), AX // syscall entry
|
||||
MOVL a1+4(FP), BX
|
||||
MOVL a2+8(FP), CX
|
||||
MOVL a3+12(FP), DX
|
||||
MOVL $0, SI
|
||||
MOVL $0, DI
|
||||
INVOKE_SYSCALL
|
||||
MOVL AX, r1+16(FP)
|
||||
MOVL DX, r2+20(FP)
|
||||
RET
|
||||
|
||||
TEXT ·socketcall(SB),NOSPLIT,$0-36
|
||||
JMP syscall·socketcall(SB)
|
||||
|
||||
TEXT ·rawsocketcall(SB),NOSPLIT,$0-36
|
||||
JMP syscall·rawsocketcall(SB)
|
||||
|
||||
TEXT ·seek(SB),NOSPLIT,$0-28
|
||||
JMP syscall·seek(SB)
|
||||
57
vendor/golang.org/x/sys/unix/asm_linux_amd64.s
generated
vendored
Normal file
57
vendor/golang.org/x/sys/unix/asm_linux_amd64.s
generated
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
//
|
||||
// System calls for AMD64, Linux
|
||||
//
|
||||
|
||||
// Just jump to package syscall's implementation for all these functions.
|
||||
// The runtime may know about them.
|
||||
|
||||
TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||
JMP syscall·Syscall(SB)
|
||||
|
||||
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||
JMP syscall·Syscall6(SB)
|
||||
|
||||
TEXT ·SyscallNoError(SB),NOSPLIT,$0-48
|
||||
CALL runtime·entersyscall(SB)
|
||||
MOVQ a1+8(FP), DI
|
||||
MOVQ a2+16(FP), SI
|
||||
MOVQ a3+24(FP), DX
|
||||
MOVQ $0, R10
|
||||
MOVQ $0, R8
|
||||
MOVQ $0, R9
|
||||
MOVQ trap+0(FP), AX // syscall entry
|
||||
SYSCALL
|
||||
MOVQ AX, r1+32(FP)
|
||||
MOVQ DX, r2+40(FP)
|
||||
CALL runtime·exitsyscall(SB)
|
||||
RET
|
||||
|
||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||
JMP syscall·RawSyscall(SB)
|
||||
|
||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||
JMP syscall·RawSyscall6(SB)
|
||||
|
||||
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48
|
||||
MOVQ a1+8(FP), DI
|
||||
MOVQ a2+16(FP), SI
|
||||
MOVQ a3+24(FP), DX
|
||||
MOVQ $0, R10
|
||||
MOVQ $0, R8
|
||||
MOVQ $0, R9
|
||||
MOVQ trap+0(FP), AX // syscall entry
|
||||
SYSCALL
|
||||
MOVQ AX, r1+32(FP)
|
||||
MOVQ DX, r2+40(FP)
|
||||
RET
|
||||
|
||||
TEXT ·gettimeofday(SB),NOSPLIT,$0-16
|
||||
JMP syscall·gettimeofday(SB)
|
||||
56
vendor/golang.org/x/sys/unix/asm_linux_arm.s
generated
vendored
Normal file
56
vendor/golang.org/x/sys/unix/asm_linux_arm.s
generated
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
//
|
||||
// System calls for arm, Linux
|
||||
//
|
||||
|
||||
// Just jump to package syscall's implementation for all these functions.
|
||||
// The runtime may know about them.
|
||||
|
||||
TEXT ·Syscall(SB),NOSPLIT,$0-28
|
||||
B syscall·Syscall(SB)
|
||||
|
||||
TEXT ·Syscall6(SB),NOSPLIT,$0-40
|
||||
B syscall·Syscall6(SB)
|
||||
|
||||
TEXT ·SyscallNoError(SB),NOSPLIT,$0-24
|
||||
BL runtime·entersyscall(SB)
|
||||
MOVW trap+0(FP), R7
|
||||
MOVW a1+4(FP), R0
|
||||
MOVW a2+8(FP), R1
|
||||
MOVW a3+12(FP), R2
|
||||
MOVW $0, R3
|
||||
MOVW $0, R4
|
||||
MOVW $0, R5
|
||||
SWI $0
|
||||
MOVW R0, r1+16(FP)
|
||||
MOVW $0, R0
|
||||
MOVW R0, r2+20(FP)
|
||||
BL runtime·exitsyscall(SB)
|
||||
RET
|
||||
|
||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
|
||||
B syscall·RawSyscall(SB)
|
||||
|
||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
|
||||
B syscall·RawSyscall6(SB)
|
||||
|
||||
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-24
|
||||
MOVW trap+0(FP), R7 // syscall entry
|
||||
MOVW a1+4(FP), R0
|
||||
MOVW a2+8(FP), R1
|
||||
MOVW a3+12(FP), R2
|
||||
SWI $0
|
||||
MOVW R0, r1+16(FP)
|
||||
MOVW $0, R0
|
||||
MOVW R0, r2+20(FP)
|
||||
RET
|
||||
|
||||
TEXT ·seek(SB),NOSPLIT,$0-28
|
||||
B syscall·seek(SB)
|
||||
52
vendor/golang.org/x/sys/unix/asm_linux_arm64.s
generated
vendored
Normal file
52
vendor/golang.org/x/sys/unix/asm_linux_arm64.s
generated
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build linux
|
||||
// +build arm64
|
||||
// +build !gccgo
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
// Just jump to package syscall's implementation for all these functions.
|
||||
// The runtime may know about them.
|
||||
|
||||
TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||
B syscall·Syscall(SB)
|
||||
|
||||
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||
B syscall·Syscall6(SB)
|
||||
|
||||
TEXT ·SyscallNoError(SB),NOSPLIT,$0-48
|
||||
BL runtime·entersyscall(SB)
|
||||
MOVD a1+8(FP), R0
|
||||
MOVD a2+16(FP), R1
|
||||
MOVD a3+24(FP), R2
|
||||
MOVD $0, R3
|
||||
MOVD $0, R4
|
||||
MOVD $0, R5
|
||||
MOVD trap+0(FP), R8 // syscall entry
|
||||
SVC
|
||||
MOVD R0, r1+32(FP) // r1
|
||||
MOVD R1, r2+40(FP) // r2
|
||||
BL runtime·exitsyscall(SB)
|
||||
RET
|
||||
|
||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||
B syscall·RawSyscall(SB)
|
||||
|
||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||
B syscall·RawSyscall6(SB)
|
||||
|
||||
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48
|
||||
MOVD a1+8(FP), R0
|
||||
MOVD a2+16(FP), R1
|
||||
MOVD a3+24(FP), R2
|
||||
MOVD $0, R3
|
||||
MOVD $0, R4
|
||||
MOVD $0, R5
|
||||
MOVD trap+0(FP), R8 // syscall entry
|
||||
SVC
|
||||
MOVD R0, r1+32(FP)
|
||||
MOVD R1, r2+40(FP)
|
||||
RET
|
||||
56
vendor/golang.org/x/sys/unix/asm_linux_mips64x.s
generated
vendored
Normal file
56
vendor/golang.org/x/sys/unix/asm_linux_mips64x.s
generated
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build linux
|
||||
// +build mips64 mips64le
|
||||
// +build !gccgo
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
//
|
||||
// System calls for mips64, Linux
|
||||
//
|
||||
|
||||
// Just jump to package syscall's implementation for all these functions.
|
||||
// The runtime may know about them.
|
||||
|
||||
TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||
JMP syscall·Syscall(SB)
|
||||
|
||||
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||
JMP syscall·Syscall6(SB)
|
||||
|
||||
TEXT ·SyscallNoError(SB),NOSPLIT,$0-48
|
||||
JAL runtime·entersyscall(SB)
|
||||
MOVV a1+8(FP), R4
|
||||
MOVV a2+16(FP), R5
|
||||
MOVV a3+24(FP), R6
|
||||
MOVV R0, R7
|
||||
MOVV R0, R8
|
||||
MOVV R0, R9
|
||||
MOVV trap+0(FP), R2 // syscall entry
|
||||
SYSCALL
|
||||
MOVV R2, r1+32(FP)
|
||||
MOVV R3, r2+40(FP)
|
||||
JAL runtime·exitsyscall(SB)
|
||||
RET
|
||||
|
||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||
JMP syscall·RawSyscall(SB)
|
||||
|
||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||
JMP syscall·RawSyscall6(SB)
|
||||
|
||||
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48
|
||||
MOVV a1+8(FP), R4
|
||||
MOVV a2+16(FP), R5
|
||||
MOVV a3+24(FP), R6
|
||||
MOVV R0, R7
|
||||
MOVV R0, R8
|
||||
MOVV R0, R9
|
||||
MOVV trap+0(FP), R2 // syscall entry
|
||||
SYSCALL
|
||||
MOVV R2, r1+32(FP)
|
||||
MOVV R3, r2+40(FP)
|
||||
RET
|
||||
54
vendor/golang.org/x/sys/unix/asm_linux_mipsx.s
generated
vendored
Normal file
54
vendor/golang.org/x/sys/unix/asm_linux_mipsx.s
generated
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build linux
|
||||
// +build mips mipsle
|
||||
// +build !gccgo
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
//
|
||||
// System calls for mips, Linux
|
||||
//
|
||||
|
||||
// Just jump to package syscall's implementation for all these functions.
|
||||
// The runtime may know about them.
|
||||
|
||||
TEXT ·Syscall(SB),NOSPLIT,$0-28
|
||||
JMP syscall·Syscall(SB)
|
||||
|
||||
TEXT ·Syscall6(SB),NOSPLIT,$0-40
|
||||
JMP syscall·Syscall6(SB)
|
||||
|
||||
TEXT ·Syscall9(SB),NOSPLIT,$0-52
|
||||
JMP syscall·Syscall9(SB)
|
||||
|
||||
TEXT ·SyscallNoError(SB),NOSPLIT,$0-24
|
||||
JAL runtime·entersyscall(SB)
|
||||
MOVW a1+4(FP), R4
|
||||
MOVW a2+8(FP), R5
|
||||
MOVW a3+12(FP), R6
|
||||
MOVW R0, R7
|
||||
MOVW trap+0(FP), R2 // syscall entry
|
||||
SYSCALL
|
||||
MOVW R2, r1+16(FP) // r1
|
||||
MOVW R3, r2+20(FP) // r2
|
||||
JAL runtime·exitsyscall(SB)
|
||||
RET
|
||||
|
||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
|
||||
JMP syscall·RawSyscall(SB)
|
||||
|
||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
|
||||
JMP syscall·RawSyscall6(SB)
|
||||
|
||||
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-24
|
||||
MOVW a1+4(FP), R4
|
||||
MOVW a2+8(FP), R5
|
||||
MOVW a3+12(FP), R6
|
||||
MOVW trap+0(FP), R2 // syscall entry
|
||||
SYSCALL
|
||||
MOVW R2, r1+16(FP)
|
||||
MOVW R3, r2+20(FP)
|
||||
RET
|
||||
56
vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s
generated
vendored
Normal file
56
vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s
generated
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build linux
|
||||
// +build ppc64 ppc64le
|
||||
// +build !gccgo
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
//
|
||||
// System calls for ppc64, Linux
|
||||
//
|
||||
|
||||
// Just jump to package syscall's implementation for all these functions.
|
||||
// The runtime may know about them.
|
||||
|
||||
TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||
BR syscall·Syscall(SB)
|
||||
|
||||
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||
BR syscall·Syscall6(SB)
|
||||
|
||||
TEXT ·SyscallNoError(SB),NOSPLIT,$0-48
|
||||
BL runtime·entersyscall(SB)
|
||||
MOVD a1+8(FP), R3
|
||||
MOVD a2+16(FP), R4
|
||||
MOVD a3+24(FP), R5
|
||||
MOVD R0, R6
|
||||
MOVD R0, R7
|
||||
MOVD R0, R8
|
||||
MOVD trap+0(FP), R9 // syscall entry
|
||||
SYSCALL R9
|
||||
MOVD R3, r1+32(FP)
|
||||
MOVD R4, r2+40(FP)
|
||||
BL runtime·exitsyscall(SB)
|
||||
RET
|
||||
|
||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||
BR syscall·RawSyscall(SB)
|
||||
|
||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||
BR syscall·RawSyscall6(SB)
|
||||
|
||||
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48
|
||||
MOVD a1+8(FP), R3
|
||||
MOVD a2+16(FP), R4
|
||||
MOVD a3+24(FP), R5
|
||||
MOVD R0, R6
|
||||
MOVD R0, R7
|
||||
MOVD R0, R8
|
||||
MOVD trap+0(FP), R9 // syscall entry
|
||||
SYSCALL R9
|
||||
MOVD R3, r1+32(FP)
|
||||
MOVD R4, r2+40(FP)
|
||||
RET
|
||||
56
vendor/golang.org/x/sys/unix/asm_linux_s390x.s
generated
vendored
Normal file
56
vendor/golang.org/x/sys/unix/asm_linux_s390x.s
generated
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build s390x
|
||||
// +build linux
|
||||
// +build !gccgo
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
//
|
||||
// System calls for s390x, Linux
|
||||
//
|
||||
|
||||
// Just jump to package syscall's implementation for all these functions.
|
||||
// The runtime may know about them.
|
||||
|
||||
TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||
BR syscall·Syscall(SB)
|
||||
|
||||
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||
BR syscall·Syscall6(SB)
|
||||
|
||||
TEXT ·SyscallNoError(SB),NOSPLIT,$0-48
|
||||
BL runtime·entersyscall(SB)
|
||||
MOVD a1+8(FP), R2
|
||||
MOVD a2+16(FP), R3
|
||||
MOVD a3+24(FP), R4
|
||||
MOVD $0, R5
|
||||
MOVD $0, R6
|
||||
MOVD $0, R7
|
||||
MOVD trap+0(FP), R1 // syscall entry
|
||||
SYSCALL
|
||||
MOVD R2, r1+32(FP)
|
||||
MOVD R3, r2+40(FP)
|
||||
BL runtime·exitsyscall(SB)
|
||||
RET
|
||||
|
||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||
BR syscall·RawSyscall(SB)
|
||||
|
||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||
BR syscall·RawSyscall6(SB)
|
||||
|
||||
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48
|
||||
MOVD a1+8(FP), R2
|
||||
MOVD a2+16(FP), R3
|
||||
MOVD a3+24(FP), R4
|
||||
MOVD $0, R5
|
||||
MOVD $0, R6
|
||||
MOVD $0, R7
|
||||
MOVD trap+0(FP), R1 // syscall entry
|
||||
SYSCALL
|
||||
MOVD R2, r1+32(FP)
|
||||
MOVD R3, r2+40(FP)
|
||||
RET
|
||||
29
vendor/golang.org/x/sys/unix/asm_netbsd_386.s
generated
vendored
Normal file
29
vendor/golang.org/x/sys/unix/asm_netbsd_386.s
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
//
|
||||
// System call support for 386, NetBSD
|
||||
//
|
||||
|
||||
// Just jump to package syscall's implementation for all these functions.
|
||||
// The runtime may know about them.
|
||||
|
||||
TEXT ·Syscall(SB),NOSPLIT,$0-28
|
||||
JMP syscall·Syscall(SB)
|
||||
|
||||
TEXT ·Syscall6(SB),NOSPLIT,$0-40
|
||||
JMP syscall·Syscall6(SB)
|
||||
|
||||
TEXT ·Syscall9(SB),NOSPLIT,$0-52
|
||||
JMP syscall·Syscall9(SB)
|
||||
|
||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
|
||||
JMP syscall·RawSyscall(SB)
|
||||
|
||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
|
||||
JMP syscall·RawSyscall6(SB)
|
||||
29
vendor/golang.org/x/sys/unix/asm_netbsd_amd64.s
generated
vendored
Normal file
29
vendor/golang.org/x/sys/unix/asm_netbsd_amd64.s
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
//
|
||||
// System call support for AMD64, NetBSD
|
||||
//
|
||||
|
||||
// Just jump to package syscall's implementation for all these functions.
|
||||
// The runtime may know about them.
|
||||
|
||||
TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||
JMP syscall·Syscall(SB)
|
||||
|
||||
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||
JMP syscall·Syscall6(SB)
|
||||
|
||||
TEXT ·Syscall9(SB),NOSPLIT,$0-104
|
||||
JMP syscall·Syscall9(SB)
|
||||
|
||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||
JMP syscall·RawSyscall(SB)
|
||||
|
||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||
JMP syscall·RawSyscall6(SB)
|
||||
29
vendor/golang.org/x/sys/unix/asm_netbsd_arm.s
generated
vendored
Normal file
29
vendor/golang.org/x/sys/unix/asm_netbsd_arm.s
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
//
|
||||
// System call support for ARM, NetBSD
|
||||
//
|
||||
|
||||
// Just jump to package syscall's implementation for all these functions.
|
||||
// The runtime may know about them.
|
||||
|
||||
TEXT ·Syscall(SB),NOSPLIT,$0-28
|
||||
B syscall·Syscall(SB)
|
||||
|
||||
TEXT ·Syscall6(SB),NOSPLIT,$0-40
|
||||
B syscall·Syscall6(SB)
|
||||
|
||||
TEXT ·Syscall9(SB),NOSPLIT,$0-52
|
||||
B syscall·Syscall9(SB)
|
||||
|
||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
|
||||
B syscall·RawSyscall(SB)
|
||||
|
||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
|
||||
B syscall·RawSyscall6(SB)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user