You've already forked v2ray-core
Compare commits
238 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6b5d2fed91 | ||
|
|
b610fc0a70 | ||
|
|
d31a067fc3 | ||
|
|
b760ac149d | ||
|
|
221a13e658 | ||
|
|
087a62ef3d | ||
|
|
38e89bd2c7 | ||
|
|
5d616dcc75 | ||
|
|
b55fceba68 | ||
|
|
220b783caa | ||
|
|
8f45736dd3 | ||
|
|
34c13f3b27 | ||
|
|
944c45a776 | ||
|
|
5e59534333 | ||
|
|
13cef19430 | ||
|
|
ca032dd00f | ||
|
|
d671780804 | ||
|
|
85633ec25e | ||
|
|
71aca12ab3 | ||
|
|
46aa2c9e5e | ||
|
|
09295f7ef6 | ||
|
|
1eb00981de | ||
|
|
c84e795518 | ||
|
|
669b8893d7 | ||
|
|
82ae56e710 | ||
|
|
166826c478 | ||
|
|
af9999f861 | ||
|
|
f48cc6df3d | ||
|
|
43fb76ac62 | ||
|
|
75183b8961 | ||
|
|
dc745d1e7a | ||
|
|
26fd271f66 | ||
|
|
4684e07b14 | ||
|
|
e3aa2bdf48 | ||
|
|
89637f68e7 | ||
|
|
1486ac6aa5 | ||
|
|
7db6bd4b78 | ||
|
|
be76b37554 | ||
|
|
70e70d314e | ||
|
|
7d1cb8aa44 | ||
|
|
551c747013 | ||
|
|
7d9b9cfca7 | ||
|
|
feb5e08c0e | ||
|
|
9682a3df55 | ||
|
|
534bb31ef1 | ||
|
|
289105fa8c | ||
|
|
6f541f60bf | ||
|
|
82075d1868 | ||
|
|
dd617da67a | ||
|
|
8b197a042d | ||
|
|
dbc2929cfd | ||
|
|
4032e20b03 | ||
|
|
423b2a815e | ||
|
|
3700d65d8f | ||
|
|
f426c5cce5 | ||
|
|
774bdf202b | ||
|
|
aa4dc77978 | ||
|
|
8366627f5f | ||
|
|
765d66296b | ||
|
|
dc8af28d56 | ||
|
|
9f8a865772 | ||
|
|
a641f8274e | ||
|
|
3aab7d1dea | ||
|
|
cd7c08b05e | ||
|
|
cd31b76e73 | ||
|
|
f89bfe50cb | ||
|
|
25de855502 | ||
|
|
54a300af56 | ||
|
|
76a8ac8434 | ||
|
|
64fd7c8ce8 | ||
|
|
1bcdb10811 | ||
|
|
ae7553d117 | ||
|
|
6c745ac290 | ||
|
|
ba237b0361 | ||
|
|
70ae685106 | ||
|
|
b5433d2980 | ||
|
|
4de72b4225 | ||
|
|
a6b3281421 | ||
|
|
c3dae6305e | ||
|
|
b6c21b1646 | ||
|
|
73f83d09ab | ||
|
|
35809561f5 | ||
|
|
9f9f0a2a96 | ||
|
|
b23e6fb1ba | ||
|
|
d123109fcd | ||
|
|
7962aba52e | ||
|
|
1fe1b5c89a | ||
|
|
a1e4c9bc70 | ||
|
|
e0aa18b6f3 | ||
|
|
4b81ba947f | ||
|
|
371e176535 | ||
|
|
05493cc096 | ||
|
|
9dc12961fa | ||
|
|
9f4fb3065d | ||
|
|
2a96605138 | ||
|
|
206008081d | ||
|
|
2d934d1027 | ||
|
|
200e6ea3dc | ||
|
|
bab1c33de3 | ||
|
|
524b2aca56 | ||
|
|
e62e6608e1 | ||
|
|
c5842b91e6 | ||
|
|
ea62c9314d | ||
|
|
49b63cbd79 | ||
|
|
9e84ce38dd | ||
|
|
b472e3e617 | ||
|
|
882320e45a | ||
|
|
808ca5d473 | ||
|
|
0fd0c374c1 | ||
|
|
2bd5f2fe96 | ||
|
|
94ea326d89 | ||
|
|
3f6ef26a00 | ||
|
|
c7d9abfb48 | ||
|
|
e61b44ff78 | ||
|
|
13b309f1b3 | ||
|
|
cfbb875546 | ||
|
|
d555508cfe | ||
|
|
c7b5d178b7 | ||
|
|
f45baff01d | ||
|
|
c93003eab6 | ||
|
|
0d71d3dcf8 | ||
|
|
5d13ec9196 | ||
|
|
04a0c04934 | ||
|
|
19061275ca | ||
|
|
9608f77ba8 | ||
|
|
d055c0497d | ||
|
|
30b5f521c4 | ||
|
|
450bc5b3f0 | ||
|
|
0314d05792 | ||
|
|
01e940fd8e | ||
|
|
f9dc0a7fb6 | ||
|
|
debbdc7276 | ||
|
|
99cf401867 | ||
|
|
82dee01833 | ||
|
|
a5caa01cb6 | ||
|
|
197fe15d5a | ||
|
|
f0e63c6e3c | ||
|
|
e19749180e | ||
|
|
7cfd630a03 | ||
|
|
2614c37d50 | ||
|
|
e176746d03 | ||
|
|
8c6dac924c | ||
|
|
2ad7060375 | ||
|
|
ad3bcd2c07 | ||
|
|
7f4f8091f9 | ||
|
|
4a663f2b25 | ||
|
|
fa657b8681 | ||
|
|
4ae653e884 | ||
|
|
52917c3243 | ||
|
|
8f60e8275b | ||
|
|
4a6ae20474 | ||
|
|
556f4bf743 | ||
|
|
3ca28ce2d8 | ||
|
|
1aefd6ce40 | ||
|
|
30116d6433 | ||
|
|
6f22e67df4 | ||
|
|
a03c4fcfb4 | ||
|
|
78e4d60a91 | ||
|
|
4448d37c2b | ||
|
|
622591bf03 | ||
|
|
ca0ca362d3 | ||
|
|
621cb8fc80 | ||
|
|
699e73c760 | ||
|
|
3c3a828e3b | ||
|
|
8854c7872f | ||
|
|
8cfb682f9c | ||
|
|
63b7eeacd1 | ||
|
|
b9480cb4b4 | ||
|
|
0d60a9e719 | ||
|
|
0eb590ce7a | ||
|
|
3c8c9adcf7 | ||
|
|
bec564b455 | ||
|
|
4da588d406 | ||
|
|
275e2d5af7 | ||
|
|
95f808ccd8 | ||
|
|
aecf18af0c | ||
|
|
35e9da8ca6 | ||
|
|
b258ca7290 | ||
|
|
d1881e2bc6 | ||
|
|
0e39a08e10 | ||
|
|
a43cd8acf5 | ||
|
|
7a9f446272 | ||
|
|
37d051f5e5 | ||
|
|
1e49ba3b0f | ||
|
|
087415850b | ||
|
|
8abff5a3cf | ||
|
|
2c4c5c50c2 | ||
|
|
0a7d99803d | ||
|
|
e43acf6e2a | ||
|
|
23e5d3cd12 | ||
|
|
8cf38342e9 | ||
|
|
dd8e957f59 | ||
|
|
a32d6416e5 | ||
|
|
7718b9629c | ||
|
|
2a27093144 | ||
|
|
ab734056da | ||
|
|
09075e62fd | ||
|
|
94ac104ffd | ||
|
|
48f5e7e76b | ||
|
|
ad4f41e1c0 | ||
|
|
1a294298e8 | ||
|
|
60f3746c27 | ||
|
|
3446d63a1e | ||
|
|
ef6bd5e192 | ||
|
|
847b289798 | ||
|
|
388af4d1e3 | ||
|
|
1a7b2337f8 | ||
|
|
f44ea4fbec | ||
|
|
fa976b8a1b | ||
|
|
20f05b5373 | ||
|
|
894b6939cd | ||
|
|
7113c7e6ef | ||
|
|
ebb2d66a50 | ||
|
|
40277a1460 | ||
|
|
8b47480f01 | ||
|
|
73182c5952 | ||
|
|
f9e3183356 | ||
|
|
a9f3116fc3 | ||
|
|
1f8cb7f86c | ||
|
|
81cf3059cd | ||
|
|
77ffbf00ce | ||
|
|
0e7286917e | ||
|
|
db22d17f09 | ||
|
|
74b0181133 | ||
|
|
c8f43e9629 | ||
|
|
969d134681 | ||
|
|
e043c4d12e | ||
|
|
c096ee0a81 | ||
|
|
15c0e975ca | ||
|
|
7460f61f39 | ||
|
|
4fef267c10 | ||
|
|
4cffa37b27 | ||
|
|
a46459fd11 | ||
|
|
d01c687f27 | ||
|
|
3c4e0d6712 | ||
|
|
f4f2a98e6e | ||
|
|
3593db2d73 | ||
|
|
a59b3510ff |
23
Dockerfile
Normal file
23
Dockerfile
Normal file
@@ -0,0 +1,23 @@
|
||||
############################
|
||||
# STEP 1 build executable binary
|
||||
############################
|
||||
FROM golang:alpine AS builder
|
||||
RUN apk update && apk add --no-cache git bash wget
|
||||
WORKDIR /go/src/v2ray.com/core
|
||||
RUN git clone --progress https://github.com/v2fly/v2ray-core.git . && \
|
||||
bash ./release/user-package.sh nosource noconf codename=$(git describe --tags) buildname=docker-fly abpathtgz=/tmp/v2ray.tgz
|
||||
############################
|
||||
# STEP 2 build a small image
|
||||
############################
|
||||
FROM alpine
|
||||
|
||||
LABEL maintainer "V2Fly Community <admin@v2fly.org>"
|
||||
COPY --from=builder /tmp/v2ray.tgz /tmp
|
||||
RUN apk update && apk add ca-certificates && \
|
||||
mkdir -p /usr/bin/v2ray && \
|
||||
tar xvfz /tmp/v2ray.tgz -C /usr/bin/v2ray
|
||||
|
||||
#ENTRYPOINT ["/usr/bin/v2ray/v2ray"]
|
||||
ENV PATH /usr/bin/v2ray:$PATH
|
||||
CMD ["v2ray", "-config=/etc/v2ray/config.json"]
|
||||
|
||||
79
SECURITY.md
Normal file
79
SECURITY.md
Normal file
@@ -0,0 +1,79 @@
|
||||
# 安全策略 Security Policy
|
||||
|
||||
## 受支持的版本 Supported Versions
|
||||
|
||||
目前 v2ray-core 项目由 [V2Fly 社区](https://github.com/v2fly) 继续提供代码维护,由于精力有限且项目复杂度较高,只维护主线代码的功能和安全性完整。原则上主页的兼容性保证继续遵循,
|
||||
如有例外另行说明。
|
||||
|
||||
Currently v2ray-core project is maintained by [V2Fly community](https://github.com/v2fly). Feature and security guarantee may only be limited to the
|
||||
master branch, though we would still try our best to follow the compatiblity claims listed on the official website.
|
||||
|
||||
|
||||
## 汇报安全风险 Reporting a Vulnerability
|
||||
|
||||
可以使用邮箱 dev |at| v2fly.org,或下方列出的 gpg 公钥在 GitHub 提交 issue 并注明安全风险。
|
||||
|
||||
You can either use email dev |at| v2fly.org, or directly open an GitHub issue with the gpg key listed below.
|
||||
|
||||
|
||||
```
|
||||
|
||||
pub rsa4096 2020-06-02 [SC] [有效至:2020-12-29]
|
||||
E2E35E27914FB007C0D4B6DDB117BA3BE8B494A7
|
||||
uid V2Fly Developers <dev |at| v2fly.org>
|
||||
sub rsa4096 2020-06-02 [E] [有效至:2020-12-29]
|
||||
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
mQINBF7V7pQBEACozcw4/BlPgFWaz4AdN8HKSrCDLlN+/g7m4AKZIo13fAnDh+sJ
|
||||
2H4NrWNr0xxgovbco5Xw4OSSwY1BuUhnb4AmIyxbwqUQD2UADe5xD6gMBwNiJTP4
|
||||
02VCHhh7DnWTeLbAsUgRotxUCxsWVvd2F08SYGfJggOVftOnG+VNnwzTOvHWFVEw
|
||||
1Pv1DaY7bKSA0voACerRbAPCYqhmElAGJHYNjBMaxqCaWFJWpAFfBxkvS1FDVyZk
|
||||
BsABhn6sOcGJn8EYSHUIXhWwqtkQCjBB4OOik+Jn+S2DFGyk5l1NrGRQtX8C0BYn
|
||||
nc7VaxtFOp5fnJ4y0GNd4AM9KO0/Ojosi6b64l407Fj9i9OXznmZUACQw2u+VcL3
|
||||
qNy768hsTmka3pXzpRHZwYcOLOEr3jGHmLOtXgQ656OjF8Xd9DJ4cB42X8iBeqTp
|
||||
iQchHIdBpnu27ZbBFy09OMak+STB5zA0JmxDaC8b48mVkc0BMRXdYl7wWXJsEJf1
|
||||
roAOr3RCBKiE840w0PLOTnUljfqazPYTwzs91oP+SeZjBmGOpaAh7bh5BVOpzPSE
|
||||
bdA61/n01GEb5bpOKpaTi9GviF3RCbfFnLKJnBq0vHvW9BqKTVFRPAKkBGuOPBdy
|
||||
8MBNY+VY/2aP3ukZUoYe8Ypl9Q7dVPRjnoWaH0sEMzftoh+3s7GSSgAylQARAQAB
|
||||
tCBWMkZseSBEZXZlbG9wZXJzIDxkZXZAdjJmbHkub3JnPokCVAQTAQgAPhYhBOLj
|
||||
XieRT7AHwNS23bEXujvotJSnBQJe1e6UAhsDBQkBFNsABQsJCAcCBhUKCQgLAgQW
|
||||
AgMBAh4BAheAAAoJELEXujvotJSnq1IP/1POoq4iwZ29T2DE6bCd+KFNdDZAfgY/
|
||||
U9KvzOycGl3AUPv5QoDGVs6GLXSelO9QYICXI2K9tsaNzIesFsx9r3LCRzr91LSI
|
||||
Jx6aqPpvJVBzxYBdarwpUmOsKRPzLIDMf8udlZrXWmtq2qS3cfxqiJkrWt+fnd3H
|
||||
cu8BH8fwzjZyxQYfdNRJ+Dk8d2ocgQ4mRpirB70sqi8zE95ox4YytZfd0QHD/gs+
|
||||
ihTVeXPtgFtqfCUOduTkF4gsKigQR6Jx3KUuNldLirAxF2XaVTCmygAOuymGYX9L
|
||||
vI9xc0s/RoltwOHK1m26idO/0blLPCahXM6WpJR7Ds3ou5phYPKnaF6ly/AAqpIv
|
||||
W+g7qFKxeKKJ0evwM/syMtDUEqJ7LS3XCd3z/E2mBCeNazc5TLM+Cx5AqvAN7qs1
|
||||
WXGG32LlbeD22Zq9zAWHC+mOI4iaHBGCzp58ugHJunq9AmiVHEB9ttuagtLWeQ3I
|
||||
lu65xVq1XV/2r2viUCnb6xbSuhkPnm7pr5ssZgZW07k2IwyaeFLz33moD0rmbWeR
|
||||
8dQVFbXTFMbXbj1bCMC8eav1uHme8Lr9PkJ82dt3n6d76s2V18M7ZRsfaH5yQmLF
|
||||
v/RucXo6GjAslRSEs/miNim5juletdgv7VZ3z7Vjc6LJ1hukQpRCIgZX5lQK2IOz
|
||||
dvDOqQyBTUPQuQINBF7V7pQBEADkQdO75smeKnmPt0/aNNlb7JDOSWW5VY0kYgx3
|
||||
6Toh139JstIQ2xz0CLSGReizUFB6eR3DXmezLrmhkgN2Aq5A+hCtFAJwWKuKr1HS
|
||||
usvJ1el9h0oh7IO+tF8E/gNYwWfabjPX27FGVCHR1qG7ffN51Bghrnwi1T4YC98E
|
||||
R9EGU6N0Xs9DeIJL9WQPH/DF22251i/OAXkqKVGn3PNe2cBsp0yKxr9mlSyzjrha
|
||||
KXokPiPcvNqlnkiDCgfiRj7c2C2Lyl9PoEiGpsNZaCZYkMPgjM0xiLenQddwRyOU
|
||||
z2cLG3d8WdCTRyHSZd/YQtSi5R6AnkJEsVtUiDN5zwNFVpQlTq3jNHsVUpjFU2nK
|
||||
ourTZVCCLbAC60VTdxLN6eFO0f+lS2WjyJ7uZ9SGbS6uP0jMNphH/QjVF848bWXs
|
||||
1CuZty5QQY7+MTNUAhSWWntrpTkdXYqT0zUqiOc1YNnkfg3hvC4d0dbnFTfcyZnB
|
||||
Sg8e7/9n6+ms75/deYgnLuA6h7pkIcflm7pUMfVKXKz5Vlc8FC9ia0UtobeKBKqi
|
||||
jObfiO/zmNL0HQBeX0e8GkJrCyv6ikD8cUqsmVtgw7jdxGsV0SL5CddDnGKsc68O
|
||||
pGDmkAuRqR3QtXju/4r7a8IEVveGWc3rUvddYrtqbbCNWCN0JKX13PEvbNAm+2eD
|
||||
MGQtcQARAQABiQI8BBgBCAAmFiEE4uNeJ5FPsAfA1LbdsRe6O+i0lKcFAl7V7pQC
|
||||
GwwFCQEU2wAACgkQsRe6O+i0lKfK3g//a23lroIF0RZCEMox8gP5DCEZtucSg80V
|
||||
4meDEAjllT3eyEIM/RcvYT2b1ViMvMYLL8lf81vQ6OvYq8F8iUYD/FpjH2gmVruE
|
||||
oMBliLNxwQZHO8AuZtRFCCkjlTk6KYn0b370ypHFE/e8oJaGJxrsRHIjGbKl7DBp
|
||||
a735hUl16+sT1k3V0p4BpAcd/4MOCvDSHn1TOr8gQV48tHbkm9zv1WNikzgwH9ig
|
||||
rvBFidmWr1jZ+vJmtgiZCerCS5P5Tgd1qr2kBgPPQhhwEcg9bHBcIrtTw/RTyHN5
|
||||
cchrvgViCAc4ZgybqV0inawOC96HQ1K9syxXpXhjhrqL/7tJ6Ff03N5yrnQbPpw2
|
||||
KMOMQPNMibBNWnuTsUwRa3L27Mx4q6qJp+92GL9xAefytnupvvC105nvBlIym8dQ
|
||||
gCiWHi3nZogmYoNMq50Eieawc0eR9ojwrJtEWihYM95i2Mt0pTCiAh955c3vHjt3
|
||||
BBYXYEBxKV3ByOxZEIKDYa119ggS7N1OZsLt+tXdCAkKN1qEcia4vSBqUjAV76//
|
||||
iUFxqF5n0d8tGpHN49D7MGZT/WYaQBuhxK2Mj4ljXg8EYlVi5Sy3O7GPUEhR16dx
|
||||
Y7pbP42vmaDsZaWURUdxeYkj4ha+z1MKqfhDePN6oRerh9I7fJnQK3DbRZGWAiEv
|
||||
F1cKt4RANJY=
|
||||
=qRzt
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
```
|
||||
@@ -14,3 +14,9 @@ jobs:
|
||||
go test -p 1 -v -timeout 30m ./...
|
||||
workingDirectory: '$(Build.SourcesDirectory)'
|
||||
displayName: 'Test'
|
||||
|
||||
- script: |
|
||||
go build ./common/buf
|
||||
condition: always()
|
||||
workingDirectory: '$(Build.SourcesDirectory)'
|
||||
displayName: 'Test Buf error'
|
||||
|
||||
@@ -3,8 +3,12 @@ trigger:
|
||||
branches:
|
||||
include:
|
||||
- master
|
||||
- dev*
|
||||
- refs/tags/*
|
||||
|
||||
pr: none
|
||||
pr:
|
||||
- master
|
||||
- dev*
|
||||
|
||||
jobs:
|
||||
- template: azure-pipelines.template.yml
|
||||
@@ -30,8 +34,9 @@ jobs:
|
||||
pool:
|
||||
vmImage: 'ubuntu-latest'
|
||||
|
||||
variables:
|
||||
CODECOV_TOKEN: '$(coverage.token)'
|
||||
#variables:
|
||||
# CODECOV_TOKEN: '$(coverage.token)'
|
||||
|
||||
|
||||
steps:
|
||||
- checkout: self
|
||||
@@ -50,43 +55,78 @@ jobs:
|
||||
|
||||
pool:
|
||||
vmImage: 'ubuntu-latest'
|
||||
|
||||
variables:
|
||||
GOPATH: '$(system.defaultWorkingDirectory)'
|
||||
BAZEL_VER: '0.23.0'
|
||||
- group: GithubToken
|
||||
- name: GOPATH
|
||||
value: '$(system.defaultWorkingDirectory)/gopath'
|
||||
- name: BAZEL_VER
|
||||
value: '0.23.0'
|
||||
|
||||
steps:
|
||||
- checkout: none
|
||||
- checkout: self
|
||||
- task: GoTool@0
|
||||
inputs:
|
||||
version: '1.14.1'
|
||||
- script: |
|
||||
mkdir triggersrc
|
||||
ls -I "triggersrc" | xargs cp -rf -t triggersrc
|
||||
mkdir gopath
|
||||
displayName: Prepare Environment
|
||||
workingDirectory: '$(system.defaultWorkingDirectory)'
|
||||
- script: |
|
||||
sudo apt-get -y update
|
||||
sudo apt-get -y install jq git file pkg-config zip g++ zlib1g-dev unzip python openssl
|
||||
sudo apt-get -y install jq git file pkg-config zip g++ zlib1g-dev unzip python openssl tree
|
||||
displayName: Apt Install
|
||||
- script: |
|
||||
go version
|
||||
go get -insecure -v -t -d v2ray.com/core/...
|
||||
workingDirectory: '$(system.defaultWorkingDirectory)'
|
||||
unset GOPATH
|
||||
mkdir ./src
|
||||
mkdir ./src/v2ray.com
|
||||
ln -s $(pwd)/../triggersrc ./src/v2ray.com/core
|
||||
go get -v -t -d ./src/v2ray.com/core/...
|
||||
tree
|
||||
workingDirectory: '$(GOPATH)'
|
||||
displayName: 'Fetch sources'
|
||||
- script: |
|
||||
mkdir release
|
||||
cd src
|
||||
zip -9 -r ../release/src_all.zip * -x '*.git*'
|
||||
workingDirectory: '$(system.defaultWorkingDirectory)'
|
||||
workingDirectory: '$(GOPATH)'
|
||||
displayName: 'Dump sources'
|
||||
- script: |
|
||||
curl -L -o bazel-installer.sh https://github.com/bazelbuild/bazel/releases/download/${BAZEL_VER}/bazel-${BAZEL_VER}-installer-linux-x86_64.sh
|
||||
chmod +x bazel-installer.sh
|
||||
./bazel-installer.sh --user
|
||||
workingDirectory: '$(system.defaultWorkingDirectory)'
|
||||
workingDirectory: '$(GOPATH)'
|
||||
displayName: 'Install Bazel'
|
||||
- script: |
|
||||
cd ./src/v2ray.com/core
|
||||
$HOME/bin/bazel build --action_env=GOPATH=$GOPATH --action_env=PATH=$PATH --action_env=GPG_PASS=${SIGN_KEY_PASS} //release:all
|
||||
workingDirectory: '$(system.defaultWorkingDirectory)'
|
||||
./release/updatedat.sh
|
||||
$HOME/bin/bazel build --action_env=GOPATH=$GOPATH --action_env=PATH=$PATH --action_env=GPG_PASS=${SIGN_KEY_PASS} --action_env=SPWD=$PWD --action_env=GOCACHE=$(go env GOCACHE) --spawn_strategy local //release:all
|
||||
workingDirectory: '$(GOPATH)'
|
||||
displayName: 'Build Binaries'
|
||||
- script: |
|
||||
cp ./src/v2ray.com/core/bazel-bin/release/*.zip ./release/
|
||||
workingDirectory: '$(system.defaultWorkingDirectory)'
|
||||
workingDirectory: '$(GOPATH)'
|
||||
displayName: 'Dump Binaries'
|
||||
- script: |
|
||||
cd ./src/v2ray.com/core
|
||||
echo $RELEASE_TAG
|
||||
./release/bleedingrelease.sh
|
||||
workingDirectory: '$(GOPATH)'
|
||||
displayName: 'Generate Bleeding Edge Release'
|
||||
env:
|
||||
GITHUB_TOKEN: $(GITHUB_TOKEN)
|
||||
PRERELEASE: true
|
||||
RELEASE_TAG: unstable-$(Build.SourceVersion)
|
||||
- script: |
|
||||
cd ./src/v2ray.com/core
|
||||
echo $RELEASE_TAG
|
||||
./release/tagrelease.sh
|
||||
workingDirectory: '$(GOPATH)'
|
||||
displayName: 'Generate Tag Release'
|
||||
env:
|
||||
GITHUB_TOKEN: $(GITHUB_TOKEN)
|
||||
PRERELEASE: true
|
||||
RELEASE_TAG: unstable-$(Build.SourceVersion)
|
||||
TRIGGER_REASON: $(Build.SourceBranch)
|
||||
|
||||
@@ -15,11 +15,38 @@ func Roll(n int) int {
|
||||
return rand.Intn(n)
|
||||
}
|
||||
|
||||
// Roll returns a non-negative number between 0 (inclusive) and n (exclusive).
|
||||
func RollDeterministic(n int, seed int64) int {
|
||||
if n == 1 {
|
||||
return 0
|
||||
}
|
||||
return rand.New(rand.NewSource(seed)).Intn(n)
|
||||
}
|
||||
|
||||
// RollUint16 returns a random uint16 value.
|
||||
func RollUint16() uint16 {
|
||||
return uint16(rand.Intn(65536))
|
||||
}
|
||||
|
||||
func RollUint64() uint64 {
|
||||
return rand.Uint64()
|
||||
}
|
||||
|
||||
func NewDeterministicDice(seed int64) *deterministicDice {
|
||||
return &deterministicDice{rand.New(rand.NewSource(seed))}
|
||||
}
|
||||
|
||||
type deterministicDice struct {
|
||||
*rand.Rand
|
||||
}
|
||||
|
||||
func (dd *deterministicDice) Roll(n int) int {
|
||||
if n == 1 {
|
||||
return 0
|
||||
}
|
||||
return dd.Intn(n)
|
||||
}
|
||||
|
||||
func init() {
|
||||
rand.Seed(time.Now().Unix())
|
||||
}
|
||||
|
||||
@@ -38,6 +38,8 @@ const (
|
||||
RequestOptionChunkMasking bitmask.Byte = 0x04
|
||||
|
||||
RequestOptionGlobalPadding bitmask.Byte = 0x08
|
||||
|
||||
RequestOptionEarlyChecksum bitmask.Byte = 0x16
|
||||
)
|
||||
|
||||
type RequestHeader struct {
|
||||
|
||||
2
core.go
2
core.go
@@ -19,7 +19,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
version = "4.23.2"
|
||||
version = "4.23.4"
|
||||
build = "Custom"
|
||||
codename = "V2Fly, a community-driven edition of V2Ray."
|
||||
intro = "A unified platform for anti-censorship."
|
||||
|
||||
@@ -113,7 +113,9 @@ func defaultBufferPolicy() Buffer {
|
||||
func SessionDefault() Session {
|
||||
return Session{
|
||||
Timeouts: Timeout{
|
||||
Handshake: time.Second * 4,
|
||||
//Align Handshake timeout with nginx client_header_timeout
|
||||
//So that this value will not indicate server identity
|
||||
Handshake: time.Second * 60,
|
||||
ConnectionIdle: time.Second * 300,
|
||||
UplinkOnly: time.Second * 1,
|
||||
DownlinkOnly: time.Second * 1,
|
||||
|
||||
6
go.mod
6
go.mod
@@ -8,10 +8,10 @@ require (
|
||||
github.com/miekg/dns v1.1.4
|
||||
github.com/refraction-networking/utls v0.0.0-20190909200633-43c36d3c1f57
|
||||
go.starlark.net v0.0.0-20190919145610-979af19b165c
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a
|
||||
golang.org/x/crypto v0.0.0-20191029031824-8986dd9e96cf
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d
|
||||
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b // indirect
|
||||
google.golang.org/grpc v1.24.0
|
||||
h12.io/socks v1.0.0
|
||||
|
||||
6
go.sum
6
go.sum
@@ -20,14 +20,20 @@ go.starlark.net v0.0.0-20190919145610-979af19b165c h1:WR7X1xgXJlXhQBdorVc9Db3Rhw
|
||||
go.starlark.net v0.0.0-20190919145610-979af19b165c/go.mod h1:c1/X6cHgvdXj6pUlmWKMkuqRnW4K8x2vwt6JAaaircg=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191029031824-8986dd9e96cf h1:fnPsqIDRbCSgumaMCRpoIoF2s4qxv0xSSS0BVZUE/ss=
|
||||
golang.org/x/crypto v0.0.0-20191029031824-8986dd9e96cf/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
|
||||
@@ -28,10 +28,11 @@ def _go_command(ctx):
|
||||
"CGO_ENABLED=0",
|
||||
"GOOS="+ctx.attr.os,
|
||||
"GOARCH="+ctx.attr.arch,
|
||||
"GOROOT_FINAL=/go",
|
||||
#"GOROOT_FINAL=/go",
|
||||
"GO111MODULE=on",
|
||||
"GOCACHE=${TMPDIR}/gocache"
|
||||
]
|
||||
|
||||
|
||||
if ctx.attr.mips: # https://github.com/golang/go/issues/27260
|
||||
envs+=["GOMIPS="+ctx.attr.mips]
|
||||
envs+=["GOMIPS64="+ctx.attr.mips]
|
||||
@@ -40,7 +41,9 @@ def _go_command(ctx):
|
||||
if ctx.attr.arm:
|
||||
envs+=["GOARM="+ctx.attr.arm]
|
||||
|
||||
command = " ".join(envs) + " " + command
|
||||
switchToPwd="cd ${SPWD} && "
|
||||
|
||||
command = switchToPwd + " ".join(envs) + " " + command
|
||||
|
||||
ctx.actions.run_shell(
|
||||
outputs = [output_file],
|
||||
|
||||
@@ -5,8 +5,10 @@ import (
|
||||
"encoding/binary"
|
||||
"hash/fnv"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"sync"
|
||||
"time"
|
||||
"v2ray.com/core/common/dice"
|
||||
|
||||
"golang.org/x/crypto/chacha20poly1305"
|
||||
|
||||
@@ -123,7 +125,29 @@ func parseSecurityType(b byte) protocol.SecurityType {
|
||||
// DecodeRequestHeader decodes and returns (if successful) a RequestHeader from an input stream.
|
||||
func (s *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.RequestHeader, error) {
|
||||
buffer := buf.New()
|
||||
defer buffer.Release()
|
||||
behaviorRand := dice.NewDeterministicDice(int64(s.userValidator.GetBehaviorSeed()))
|
||||
BaseDrainSize := behaviorRand.Roll(3266)
|
||||
RandDrainMax := behaviorRand.Roll(64) + 1
|
||||
RandDrainRolled := dice.Roll(RandDrainMax)
|
||||
DrainSize := BaseDrainSize + 16 + 38 + RandDrainRolled
|
||||
readSizeRemain := DrainSize
|
||||
|
||||
drainConnection := func(e error) error {
|
||||
//We read a deterministic generated length of data before closing the connection to offset padding read pattern
|
||||
readSizeRemain -= int(buffer.Len())
|
||||
if readSizeRemain > 0 {
|
||||
err := s.DrainConnN(reader, readSizeRemain)
|
||||
if err != nil {
|
||||
return newError("failed to drain connection DrainSize = ", BaseDrainSize, " ", RandDrainMax, " ", RandDrainRolled).Base(err).Base(e)
|
||||
}
|
||||
return newError("connection drained DrainSize = ", BaseDrainSize, " ", RandDrainMax, " ", RandDrainRolled).Base(e)
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
defer func() {
|
||||
buffer.Release()
|
||||
}()
|
||||
|
||||
if _, err := buffer.ReadFullFrom(reader, protocol.IDBytesLen); err != nil {
|
||||
return nil, newError("failed to read request header").Base(err)
|
||||
@@ -131,7 +155,7 @@ func (s *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Request
|
||||
|
||||
user, timestamp, valid := s.userValidator.Get(buffer.Bytes())
|
||||
if !valid {
|
||||
return nil, newError("invalid user")
|
||||
return nil, drainConnection(newError("invalid user"))
|
||||
}
|
||||
|
||||
iv := hashTimestamp(md5.New(), timestamp)
|
||||
@@ -140,6 +164,7 @@ func (s *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Request
|
||||
aesStream := crypto.NewAesDecryptionStream(vmessAccount.ID.CmdKey(), iv[:])
|
||||
decryptor := crypto.NewCryptionReader(aesStream, reader)
|
||||
|
||||
readSizeRemain -= int(buffer.Len())
|
||||
buffer.Clear()
|
||||
if _, err := buffer.ReadFullFrom(decryptor, 38); err != nil {
|
||||
return nil, newError("failed to read request header").Base(err)
|
||||
@@ -157,7 +182,7 @@ func (s *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Request
|
||||
sid.key = s.requestBodyKey
|
||||
sid.nonce = s.requestBodyIV
|
||||
if !s.sessionHistory.addIfNotExits(sid) {
|
||||
return nil, newError("duplicated session id, possibly under replay attack")
|
||||
return nil, drainConnection(newError("duplicated session id, possibly under replay attack"))
|
||||
}
|
||||
|
||||
s.responseHeader = buffer.Byte(33) // 1 byte
|
||||
@@ -194,7 +219,8 @@ func (s *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Request
|
||||
expectedHash := binary.BigEndian.Uint32(buffer.BytesFrom(-4))
|
||||
|
||||
if actualHash != expectedHash {
|
||||
return nil, newError("invalid auth")
|
||||
//It is possible that we are under attack described in https://github.com/v2ray/v2ray-core/issues/2523
|
||||
return nil, drainConnection(newError("invalid auth"))
|
||||
}
|
||||
|
||||
if request.Address == nil {
|
||||
@@ -347,3 +373,8 @@ func (s *ServerSession) EncodeResponseBody(request *protocol.RequestHeader, writ
|
||||
panic("Unknown security type.")
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ServerSession) DrainConnN(reader io.Reader, n int) error {
|
||||
_, err := io.CopyN(ioutil.Discard, reader, int64(n))
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -3,9 +3,11 @@
|
||||
package vmess
|
||||
|
||||
import (
|
||||
"hash/crc64"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
"v2ray.com/core/common/dice"
|
||||
|
||||
"v2ray.com/core/common"
|
||||
"v2ray.com/core/common/protocol"
|
||||
@@ -26,11 +28,13 @@ type user struct {
|
||||
// TimedUserValidator is a user Validator based on time.
|
||||
type TimedUserValidator struct {
|
||||
sync.RWMutex
|
||||
users []*user
|
||||
userHash map[[16]byte]indexTimePair
|
||||
hasher protocol.IDHash
|
||||
baseTime protocol.Timestamp
|
||||
task *task.Periodic
|
||||
users []*user
|
||||
userHash map[[16]byte]indexTimePair
|
||||
hasher protocol.IDHash
|
||||
baseTime protocol.Timestamp
|
||||
task *task.Periodic
|
||||
behaviorSeed uint64
|
||||
behaviorFused bool
|
||||
}
|
||||
|
||||
type indexTimePair struct {
|
||||
@@ -124,6 +128,11 @@ func (v *TimedUserValidator) Add(u *protocol.MemoryUser) error {
|
||||
v.users = append(v.users, uu)
|
||||
v.generateNewHashes(protocol.Timestamp(nowSec), uu)
|
||||
|
||||
if v.behaviorFused == false {
|
||||
account := uu.user.Account.(*MemoryAccount)
|
||||
v.behaviorSeed = crc64.Update(v.behaviorSeed, crc64.MakeTable(crc64.ECMA), account.ID.Bytes())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -131,6 +140,8 @@ func (v *TimedUserValidator) Get(userHash []byte) (*protocol.MemoryUser, protoco
|
||||
defer v.RUnlock()
|
||||
v.RLock()
|
||||
|
||||
v.behaviorFused = true
|
||||
|
||||
var fixedSizeHash [16]byte
|
||||
copy(fixedSizeHash[:], userHash)
|
||||
pair, found := v.userHash[fixedSizeHash]
|
||||
@@ -170,3 +181,13 @@ func (v *TimedUserValidator) Remove(email string) bool {
|
||||
func (v *TimedUserValidator) Close() error {
|
||||
return v.task.Close()
|
||||
}
|
||||
|
||||
func (v *TimedUserValidator) GetBehaviorSeed() uint64 {
|
||||
v.Lock()
|
||||
defer v.Unlock()
|
||||
v.behaviorFused = true
|
||||
if v.behaviorSeed == 0 {
|
||||
v.behaviorSeed = dice.RollUint64()
|
||||
}
|
||||
return v.behaviorSeed
|
||||
}
|
||||
|
||||
52
release/bleedingrelease.sh
Executable file
52
release/bleedingrelease.sh
Executable file
@@ -0,0 +1,52 @@
|
||||
#!/bin/bash
|
||||
|
||||
|
||||
RELBODY="https://www.v2ray.com/chapter_00/01_versions.html"
|
||||
JSON_DATA=$(echo "{}" | jq -c ".tag_name=\"${RELEASE_TAG}\"")
|
||||
JSON_DATA=$(echo ${JSON_DATA} | jq -c ".prerelease=${PRERELEASE}")
|
||||
JSON_DATA=$(echo ${JSON_DATA} | jq -c ".body=\"${RELBODY}\"")
|
||||
RELEASE_DATA=$(curl --data "${JSON_DATA}" -H "Authorization: token ${GITHUB_TOKEN}" -X POST https://api.github.com/repos/v2fly/V2FlyBleedingEdgeBinary/releases)
|
||||
echo $RELEASE_DATA
|
||||
RELEASE_ID=$(echo $RELEASE_DATA| jq ".id")
|
||||
|
||||
function uploadfile() {
|
||||
FILE=$1
|
||||
CTYPE=$(file -b --mime-type $FILE)
|
||||
|
||||
sleep 1
|
||||
curl -H "Authorization: token ${GITHUB_TOKEN}" -H "Content-Type: ${CTYPE}" --data-binary @$FILE "https://uploads.github.com/repos/v2fly/V2FlyBleedingEdgeBinary/releases/${RELEASE_ID}/assets?name=$(basename $FILE)"
|
||||
sleep 1
|
||||
}
|
||||
|
||||
function upload() {
|
||||
FILE=$1
|
||||
DGST=$1.dgst
|
||||
openssl dgst -md5 $FILE | sed 's/([^)]*)//g' >> $DGST
|
||||
openssl dgst -sha1 $FILE | sed 's/([^)]*)//g' >> $DGST
|
||||
openssl dgst -sha256 $FILE | sed 's/([^)]*)//g' >> $DGST
|
||||
openssl dgst -sha512 $FILE | sed 's/([^)]*)//g' >> $DGST
|
||||
uploadfile $FILE
|
||||
uploadfile $DGST
|
||||
}
|
||||
|
||||
ART_ROOT=$GOPATH/src/v2ray.com/core/bazel-bin/release
|
||||
|
||||
upload ${ART_ROOT}/v2ray-macos.zip
|
||||
upload ${ART_ROOT}/v2ray-windows-64.zip
|
||||
upload ${ART_ROOT}/v2ray-windows-32.zip
|
||||
upload ${ART_ROOT}/v2ray-linux-64.zip
|
||||
upload ${ART_ROOT}/v2ray-linux-32.zip
|
||||
upload ${ART_ROOT}/v2ray-linux-arm.zip
|
||||
upload ${ART_ROOT}/v2ray-linux-arm64.zip
|
||||
upload ${ART_ROOT}/v2ray-linux-mips64.zip
|
||||
upload ${ART_ROOT}/v2ray-linux-mips64le.zip
|
||||
upload ${ART_ROOT}/v2ray-linux-mips.zip
|
||||
upload ${ART_ROOT}/v2ray-linux-mipsle.zip
|
||||
upload ${ART_ROOT}/v2ray-linux-ppc64.zip
|
||||
upload ${ART_ROOT}/v2ray-linux-ppc64le.zip
|
||||
upload ${ART_ROOT}/v2ray-linux-s390x.zip
|
||||
upload ${ART_ROOT}/v2ray-freebsd-64.zip
|
||||
upload ${ART_ROOT}/v2ray-freebsd-32.zip
|
||||
upload ${ART_ROOT}/v2ray-openbsd-64.zip
|
||||
upload ${ART_ROOT}/v2ray-openbsd-32.zip
|
||||
upload ${ART_ROOT}/v2ray-dragonfly-64.zip
|
||||
@@ -1,25 +1,22 @@
|
||||
[Unit]
|
||||
Description=V2Ray - A unified platform for anti-censorship
|
||||
Documentation=https://v2ray.com https://guide.v2fly.org
|
||||
Description=V2Ray Service
|
||||
Documentation=https://www.v2ray.com/ https://www.v2fly.org/
|
||||
After=network.target nss-lookup.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
# If the version of systemd is 240 or above, then uncommenting Type=exec and commenting out Type=simple
|
||||
#Type=exec
|
||||
Type=simple
|
||||
# Runs as root or add CAP_NET_BIND_SERVICE ability can bind 1 to 1024 port.
|
||||
# This service runs as root. You may consider to run it as another user for security concerns.
|
||||
# By uncommenting User=v2ray and commenting out User=root, the service will run as user v2ray.
|
||||
# By uncommenting User=nobody and commenting out User=root, the service will run as user nobody.
|
||||
# More discussion at https://github.com/v2ray/v2ray-core/issues/1011
|
||||
User=root
|
||||
#User=v2ray
|
||||
CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_NET_RAW
|
||||
NoNewPrivileges=yes
|
||||
#User=nobody
|
||||
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
|
||||
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
|
||||
NoNewPrivileges=true
|
||||
ExecStart=/usr/bin/v2ray/v2ray -config /etc/v2ray/config.json
|
||||
Restart=on-failure
|
||||
# Don't restart in the case of configuration error
|
||||
RestartPreventExitStatus=23
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
@@ -1,26 +1,22 @@
|
||||
[Unit]
|
||||
Description=V2Ray - A unified platform for anti-censorship - Profile -> %i
|
||||
Documentation=https://v2ray.com https://guide.v2fly.org
|
||||
Description=V2Ray Service
|
||||
Documentation=https://www.v2ray.com/ https://www.v2fly.org/
|
||||
After=network.target nss-lookup.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
# If the version of systemd is 240 or above, then uncommenting Type=exec and commenting out Type=simple
|
||||
#Type=exec
|
||||
Type=simple
|
||||
# Runs as root or add CAP_NET_BIND_SERVICE ability can bind 1 to 1024 port.
|
||||
# This service runs as root. You may consider to run it as another user for security concerns.
|
||||
# By uncommenting User=v2ray and commenting out User=root, the service will run as user v2ray.
|
||||
# By uncommenting User=nobody and commenting out User=root, the service will run as user nobody.
|
||||
# More discussion at https://github.com/v2ray/v2ray-core/issues/1011
|
||||
User=root
|
||||
#User=v2ray
|
||||
CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_NET_RAW
|
||||
NoNewPrivileges=yes
|
||||
#User=nobody
|
||||
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
|
||||
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
|
||||
NoNewPrivileges=true
|
||||
ExecStart=/usr/bin/v2ray/v2ray -config /etc/v2ray/%i.json
|
||||
Restart=on-failure
|
||||
# Don't restart in the case of configuration error
|
||||
RestartPreventExitStatus=23
|
||||
|
||||
[Install]
|
||||
DefaultInstance=default
|
||||
WantedBy=multi-user.target
|
||||
|
||||
75
release/tagrelease.sh
Executable file
75
release/tagrelease.sh
Executable file
@@ -0,0 +1,75 @@
|
||||
#!/bin/bash
|
||||
|
||||
CONST_refs="refs"
|
||||
|
||||
TRIGGER_REASON_A=${TRIGGER_REASON:0:${#CONST_refs}}
|
||||
|
||||
if [ $TRIGGER_REASON_A != $CONST_refs ]
|
||||
then
|
||||
echo "not a tag: $TRIGGER_REASON_A"
|
||||
exit
|
||||
fi
|
||||
|
||||
CONST_refsB="refs/tags/"
|
||||
|
||||
TRIGGER_REASON_B=${TRIGGER_REASON:0:${#CONST_refsB}}
|
||||
|
||||
if [ $TRIGGER_REASON_B != $CONST_refsB ]
|
||||
then
|
||||
echo "not a tag (B)"
|
||||
exit
|
||||
fi
|
||||
|
||||
|
||||
GITHUB_RELEASE_TAG=${TRIGGER_REASON:${#CONST_refsB}:10}
|
||||
|
||||
echo ${GITHUB_RELEASE_TAG}
|
||||
|
||||
|
||||
RELEASE_DATA=$(curl -H "Authorization: token ${GITHUB_TOKEN}" -X GET https://api.github.com/repos/v2fly/v2ray-core/releases/tags/${GITHUB_RELEASE_TAG})
|
||||
echo $RELEASE_DATA
|
||||
RELEASE_ID=$(echo $RELEASE_DATA| jq ".id")
|
||||
|
||||
echo $RELEASE_ID
|
||||
|
||||
function uploadfile() {
|
||||
FILE=$1
|
||||
CTYPE=$(file -b --mime-type $FILE)
|
||||
|
||||
sleep 1
|
||||
curl -H "Authorization: token ${GITHUB_TOKEN}" -H "Content-Type: ${CTYPE}" --data-binary @$FILE "https://uploads.github.com/repos/v2fly/v2ray-core/releases/${RELEASE_ID}/assets?name=$(basename $FILE)"
|
||||
sleep 1
|
||||
}
|
||||
|
||||
function upload() {
|
||||
FILE=$1
|
||||
DGST=$1.dgst
|
||||
openssl dgst -md5 $FILE | sed 's/([^)]*)//g' >> $DGST
|
||||
openssl dgst -sha1 $FILE | sed 's/([^)]*)//g' >> $DGST
|
||||
openssl dgst -sha256 $FILE | sed 's/([^)]*)//g' >> $DGST
|
||||
openssl dgst -sha512 $FILE | sed 's/([^)]*)//g' >> $DGST
|
||||
uploadfile $FILE
|
||||
uploadfile $DGST
|
||||
}
|
||||
|
||||
ART_ROOT=$GOPATH/src/v2ray.com/core/bazel-bin/release
|
||||
|
||||
upload ${ART_ROOT}/v2ray-macos.zip
|
||||
upload ${ART_ROOT}/v2ray-windows-64.zip
|
||||
upload ${ART_ROOT}/v2ray-windows-32.zip
|
||||
upload ${ART_ROOT}/v2ray-linux-64.zip
|
||||
upload ${ART_ROOT}/v2ray-linux-32.zip
|
||||
upload ${ART_ROOT}/v2ray-linux-arm.zip
|
||||
upload ${ART_ROOT}/v2ray-linux-arm64.zip
|
||||
upload ${ART_ROOT}/v2ray-linux-mips64.zip
|
||||
upload ${ART_ROOT}/v2ray-linux-mips64le.zip
|
||||
upload ${ART_ROOT}/v2ray-linux-mips.zip
|
||||
upload ${ART_ROOT}/v2ray-linux-mipsle.zip
|
||||
upload ${ART_ROOT}/v2ray-linux-ppc64.zip
|
||||
upload ${ART_ROOT}/v2ray-linux-ppc64le.zip
|
||||
upload ${ART_ROOT}/v2ray-linux-s390x.zip
|
||||
upload ${ART_ROOT}/v2ray-freebsd-64.zip
|
||||
upload ${ART_ROOT}/v2ray-freebsd-32.zip
|
||||
upload ${ART_ROOT}/v2ray-openbsd-64.zip
|
||||
upload ${ART_ROOT}/v2ray-openbsd-32.zip
|
||||
upload ${ART_ROOT}/v2ray-dragonfly-64.zip
|
||||
14
release/updatedat.sh
Executable file
14
release/updatedat.sh
Executable file
@@ -0,0 +1,14 @@
|
||||
#!/bin/bash
|
||||
|
||||
|
||||
pushd $GOPATH/src/v2ray.com/core/
|
||||
# Update geoip.dat
|
||||
GEOIP_TAG=$(curl --silent "https://api.github.com/repos/v2ray/geoip/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
|
||||
curl -L -o release/config/geoip.dat "https://github.com/v2ray/geoip/releases/download/${GEOIP_TAG}/geoip.dat"
|
||||
sleep 1
|
||||
|
||||
# Update geosite.dat
|
||||
GEOSITE_TAG=$(curl --silent "https://api.github.com/repos/v2ray/domain-list-community/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
|
||||
curl -L -o release/config/geosite.dat "https://github.com/v2ray/domain-list-community/releases/download/${GEOSITE_TAG}/dlc.dat"
|
||||
sleep 1
|
||||
popd
|
||||
@@ -42,7 +42,7 @@ echo "mode: set" | cat - ${COV_SORTED} > ${COVERAGE_FILE}
|
||||
|
||||
if [ "$FAIL" -eq 0 ]; then
|
||||
echo "Uploading coverage datea to codecov."
|
||||
bash <(curl -s https://codecov.io/bash) -f ${COVERAGE_FILE} -v || echo "Codecov did not collect coverage reports."
|
||||
#bash <(curl -s https://codecov.io/bash) -f ${COVERAGE_FILE} -v || echo "Codecov did not collect coverage reports."
|
||||
fi
|
||||
|
||||
exit $FAIL
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -265,7 +266,9 @@ func TestCommanderAddRemoveUser(t *testing.T) {
|
||||
common.Must(err)
|
||||
defer CloseAllServers(servers)
|
||||
|
||||
if err := testTCPConn(clientPort, 1024, time.Second*5)(); err != io.EOF {
|
||||
if err := testTCPConn(clientPort, 1024, time.Second*5)(); err != io.EOF &&
|
||||
/*We might wish to drain the connection*/
|
||||
(err != nil && !strings.HasSuffix(err.Error(), "i/o timeout")) {
|
||||
t.Fatal("expected error: ", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -919,7 +919,6 @@ func TestVMessKCPLarge(t *testing.T) {
|
||||
|
||||
servers, err := InitializeServerConfigs(serverConfig, clientConfig)
|
||||
common.Must(err)
|
||||
defer CloseAllServers(servers)
|
||||
|
||||
var errg errgroup.Group
|
||||
for i := 0; i < 2; i++ {
|
||||
@@ -928,6 +927,11 @@ func TestVMessKCPLarge(t *testing.T) {
|
||||
if err := errg.Wait(); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
defer func(){
|
||||
<-time.After(5*time.Second)
|
||||
CloseAllServers(servers)
|
||||
}()
|
||||
}
|
||||
|
||||
func TestVMessGCMMux(t *testing.T) {
|
||||
@@ -1161,7 +1165,6 @@ func TestVMessGCMMuxUDP(t *testing.T) {
|
||||
|
||||
servers, err := InitializeServerConfigs(serverConfig, clientConfig)
|
||||
common.Must(err)
|
||||
defer CloseAllServers(servers)
|
||||
|
||||
for range "abcd" {
|
||||
var errg errgroup.Group
|
||||
@@ -1174,4 +1177,9 @@ func TestVMessGCMMuxUDP(t *testing.T) {
|
||||
}
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
|
||||
defer func(){
|
||||
<-time.After(5*time.Second)
|
||||
CloseAllServers(servers)
|
||||
}()
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package http
|
||||
//go:generate errorgen
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"io"
|
||||
@@ -28,6 +29,8 @@ const (
|
||||
|
||||
var (
|
||||
ErrHeaderToLong = newError("Header too long.")
|
||||
|
||||
ErrHeaderMisMatch = newError("Header Mismatch.")
|
||||
)
|
||||
|
||||
type Reader interface {
|
||||
@@ -51,12 +54,22 @@ func (NoOpWriter) Write(io.Writer) error {
|
||||
}
|
||||
|
||||
type HeaderReader struct {
|
||||
req *http.Request
|
||||
expectedHeader *RequestConfig
|
||||
}
|
||||
|
||||
func (*HeaderReader) Read(reader io.Reader) (*buf.Buffer, error) {
|
||||
func (h *HeaderReader) ExpectThisRequest(expectedHeader *RequestConfig) *HeaderReader {
|
||||
h.expectedHeader = expectedHeader
|
||||
return h
|
||||
}
|
||||
|
||||
func (h *HeaderReader) Read(reader io.Reader) (*buf.Buffer, error) {
|
||||
buffer := buf.New()
|
||||
totalBytes := int32(0)
|
||||
endingDetected := false
|
||||
|
||||
var headerBuf bytes.Buffer
|
||||
|
||||
for totalBytes < maxHeaderLength {
|
||||
_, err := buffer.ReadFrom(reader)
|
||||
if err != nil {
|
||||
@@ -64,6 +77,7 @@ func (*HeaderReader) Read(reader io.Reader) (*buf.Buffer, error) {
|
||||
return nil, err
|
||||
}
|
||||
if n := bytes.Index(buffer.Bytes(), []byte(ENDING)); n != -1 {
|
||||
headerBuf.Write(buffer.BytesRange(0, int32(n+len(ENDING))))
|
||||
buffer.Advance(int32(n + len(ENDING)))
|
||||
endingDetected = true
|
||||
break
|
||||
@@ -71,19 +85,56 @@ func (*HeaderReader) Read(reader io.Reader) (*buf.Buffer, error) {
|
||||
lenEnding := int32(len(ENDING))
|
||||
if buffer.Len() >= lenEnding {
|
||||
totalBytes += buffer.Len() - lenEnding
|
||||
headerBuf.Write(buffer.BytesRange(0, buffer.Len()-lenEnding))
|
||||
leftover := buffer.BytesFrom(-lenEnding)
|
||||
buffer.Clear()
|
||||
copy(buffer.Extend(lenEnding), leftover)
|
||||
|
||||
if _, err := readRequest(bufio.NewReader(bytes.NewReader(headerBuf.Bytes())), false); err != io.ErrUnexpectedEOF {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
if buffer.IsEmpty() {
|
||||
buffer.Release()
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if !endingDetected {
|
||||
buffer.Release()
|
||||
return nil, ErrHeaderToLong
|
||||
}
|
||||
|
||||
if h.expectedHeader == nil {
|
||||
if buffer.IsEmpty() {
|
||||
buffer.Release()
|
||||
return nil, nil
|
||||
}
|
||||
return buffer, nil
|
||||
}
|
||||
|
||||
//Parse the request
|
||||
|
||||
if req, err := readRequest(bufio.NewReader(bytes.NewReader(headerBuf.Bytes())), false); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
h.req = req
|
||||
}
|
||||
|
||||
//Check req
|
||||
path := h.req.URL.Path
|
||||
hasThisUri := false
|
||||
for _, u := range h.expectedHeader.Uri {
|
||||
if u == path {
|
||||
hasThisUri = true
|
||||
}
|
||||
}
|
||||
|
||||
if hasThisUri == false {
|
||||
return nil, ErrHeaderMisMatch
|
||||
}
|
||||
|
||||
if buffer.IsEmpty() {
|
||||
buffer.Release()
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return buffer, nil
|
||||
}
|
||||
|
||||
@@ -110,18 +161,24 @@ func (w *HeaderWriter) Write(writer io.Writer) error {
|
||||
type HttpConn struct {
|
||||
net.Conn
|
||||
|
||||
readBuffer *buf.Buffer
|
||||
oneTimeReader Reader
|
||||
oneTimeWriter Writer
|
||||
errorWriter Writer
|
||||
readBuffer *buf.Buffer
|
||||
oneTimeReader Reader
|
||||
oneTimeWriter Writer
|
||||
errorWriter Writer
|
||||
errorMismatchWriter Writer
|
||||
errorTooLongWriter Writer
|
||||
|
||||
errReason error
|
||||
}
|
||||
|
||||
func NewHttpConn(conn net.Conn, reader Reader, writer Writer, errorWriter Writer) *HttpConn {
|
||||
func NewHttpConn(conn net.Conn, reader Reader, writer Writer, errorWriter Writer, errorMismatchWriter Writer, errorTooLongWriter Writer) *HttpConn {
|
||||
return &HttpConn{
|
||||
Conn: conn,
|
||||
oneTimeReader: reader,
|
||||
oneTimeWriter: writer,
|
||||
errorWriter: errorWriter,
|
||||
Conn: conn,
|
||||
oneTimeReader: reader,
|
||||
oneTimeWriter: writer,
|
||||
errorWriter: errorWriter,
|
||||
errorMismatchWriter: errorMismatchWriter,
|
||||
errorTooLongWriter: errorTooLongWriter,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,6 +186,7 @@ func (c *HttpConn) Read(b []byte) (int, error) {
|
||||
if c.oneTimeReader != nil {
|
||||
buffer, err := c.oneTimeReader.Read(c.Conn)
|
||||
if err != nil {
|
||||
c.errReason = err
|
||||
return 0, err
|
||||
}
|
||||
c.readBuffer = buffer
|
||||
@@ -165,7 +223,16 @@ func (c *HttpConn) Close() error {
|
||||
if c.oneTimeWriter != nil && c.errorWriter != nil {
|
||||
// Connection is being closed but header wasn't sent. This means the client request
|
||||
// is probably not valid. Sending back a server error header in this case.
|
||||
c.errorWriter.Write(c.Conn)
|
||||
|
||||
//Write response based on error reason
|
||||
|
||||
if c.errReason == ErrHeaderMisMatch {
|
||||
c.errorMismatchWriter.Write(c.Conn)
|
||||
} else if c.errReason == ErrHeaderToLong {
|
||||
c.errorTooLongWriter.Write(c.Conn)
|
||||
} else {
|
||||
c.errorWriter.Write(c.Conn)
|
||||
}
|
||||
}
|
||||
|
||||
return c.Conn.Close()
|
||||
@@ -230,36 +297,17 @@ func (a HttpAuthenticator) Client(conn net.Conn) net.Conn {
|
||||
if a.config.Response != nil {
|
||||
writer = a.GetClientWriter()
|
||||
}
|
||||
return NewHttpConn(conn, reader, writer, NoOpWriter{})
|
||||
return NewHttpConn(conn, reader, writer, NoOpWriter{}, NoOpWriter{}, NoOpWriter{})
|
||||
}
|
||||
|
||||
func (a HttpAuthenticator) Server(conn net.Conn) net.Conn {
|
||||
if a.config.Request == nil && a.config.Response == nil {
|
||||
return conn
|
||||
}
|
||||
return NewHttpConn(conn, new(HeaderReader), a.GetServerWriter(), formResponseHeader(&ResponseConfig{
|
||||
Version: &Version{
|
||||
Value: "1.1",
|
||||
},
|
||||
Status: &Status{
|
||||
Code: "500",
|
||||
Reason: "Internal Server Error",
|
||||
},
|
||||
Header: []*Header{
|
||||
{
|
||||
Name: "Connection",
|
||||
Value: []string{"close"},
|
||||
},
|
||||
{
|
||||
Name: "Cache-Control",
|
||||
Value: []string{"private"},
|
||||
},
|
||||
{
|
||||
Name: "Content-Length",
|
||||
Value: []string{"0"},
|
||||
},
|
||||
},
|
||||
}))
|
||||
return NewHttpConn(conn, new(HeaderReader).ExpectThisRequest(a.config.Request), a.GetServerWriter(),
|
||||
formResponseHeader(resp400),
|
||||
formResponseHeader(resp404),
|
||||
formResponseHeader(resp400))
|
||||
}
|
||||
|
||||
func NewHttpAuthenticator(ctx context.Context, config *Config) (HttpAuthenticator, error) {
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package http_test
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -28,10 +30,15 @@ func TestReaderWriter(t *testing.T) {
|
||||
|
||||
reader := &HeaderReader{}
|
||||
buffer, err := reader.Read(cache)
|
||||
common.Must(err)
|
||||
if buffer.String() != "efg" {
|
||||
t.Error("buffer: ", buffer.String())
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "malformed HTTP request") {
|
||||
t.Error("unknown error ", err)
|
||||
}
|
||||
_ = buffer
|
||||
return
|
||||
/*
|
||||
if buffer.String() != "efg" {
|
||||
t.Error("buffer: ", buffer.String())
|
||||
}*/
|
||||
}
|
||||
|
||||
func TestRequestHeader(t *testing.T) {
|
||||
@@ -65,10 +72,16 @@ func TestLongRequestHeader(t *testing.T) {
|
||||
|
||||
reader := HeaderReader{}
|
||||
b, err := reader.Read(bytes.NewReader(payload))
|
||||
common.Must(err)
|
||||
if b.String() != "abcd" {
|
||||
t.Error("expect content abcd, but actually ", b.String())
|
||||
|
||||
if err != nil && !(strings.HasPrefix(err.Error(), "invalid") || strings.HasPrefix(err.Error(), "malformed")) {
|
||||
t.Error("unknown error ", err)
|
||||
}
|
||||
_ = b
|
||||
/*
|
||||
common.Must(err)
|
||||
if b.String() != "abcd" {
|
||||
t.Error("expect content abcd, but actually ", b.String())
|
||||
}*/
|
||||
}
|
||||
|
||||
func TestConnection(t *testing.T) {
|
||||
@@ -143,3 +156,164 @@ func TestConnection(t *testing.T) {
|
||||
t.Error("response: ", string(actualResponse[:totalBytes]))
|
||||
}
|
||||
}
|
||||
|
||||
func TestConnectionInvPath(t *testing.T) {
|
||||
auth, err := NewHttpAuthenticator(context.Background(), &Config{
|
||||
Request: &RequestConfig{
|
||||
Method: &Method{Value: "Post"},
|
||||
Uri: []string{"/testpath"},
|
||||
Header: []*Header{
|
||||
{
|
||||
Name: "Host",
|
||||
Value: []string{"www.v2ray.com", "www.google.com"},
|
||||
},
|
||||
{
|
||||
Name: "User-Agent",
|
||||
Value: []string{"Test-Agent"},
|
||||
},
|
||||
},
|
||||
},
|
||||
Response: &ResponseConfig{
|
||||
Version: &Version{
|
||||
Value: "1.1",
|
||||
},
|
||||
Status: &Status{
|
||||
Code: "404",
|
||||
Reason: "Not Found",
|
||||
},
|
||||
},
|
||||
})
|
||||
common.Must(err)
|
||||
|
||||
authR, err := NewHttpAuthenticator(context.Background(), &Config{
|
||||
Request: &RequestConfig{
|
||||
Method: &Method{Value: "Post"},
|
||||
Uri: []string{"/testpathErr"},
|
||||
Header: []*Header{
|
||||
{
|
||||
Name: "Host",
|
||||
Value: []string{"www.v2ray.com", "www.google.com"},
|
||||
},
|
||||
{
|
||||
Name: "User-Agent",
|
||||
Value: []string{"Test-Agent"},
|
||||
},
|
||||
},
|
||||
},
|
||||
Response: &ResponseConfig{
|
||||
Version: &Version{
|
||||
Value: "1.1",
|
||||
},
|
||||
Status: &Status{
|
||||
Code: "404",
|
||||
Reason: "Not Found",
|
||||
},
|
||||
},
|
||||
})
|
||||
common.Must(err)
|
||||
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
common.Must(err)
|
||||
|
||||
go func() {
|
||||
conn, err := listener.Accept()
|
||||
common.Must(err)
|
||||
authConn := auth.Server(conn)
|
||||
b := make([]byte, 256)
|
||||
for {
|
||||
n, err := authConn.Read(b)
|
||||
if err != nil {
|
||||
authConn.Close()
|
||||
break
|
||||
}
|
||||
_, err = authConn.Write(b[:n])
|
||||
common.Must(err)
|
||||
}
|
||||
}()
|
||||
|
||||
conn, err := net.DialTCP("tcp", nil, listener.Addr().(*net.TCPAddr))
|
||||
common.Must(err)
|
||||
|
||||
authConn := authR.Client(conn)
|
||||
defer authConn.Close()
|
||||
|
||||
authConn.Write([]byte("Test payload"))
|
||||
authConn.Write([]byte("Test payload 2"))
|
||||
|
||||
expectedResponse := "Test payloadTest payload 2"
|
||||
actualResponse := make([]byte, 256)
|
||||
deadline := time.Now().Add(time.Second * 5)
|
||||
totalBytes := 0
|
||||
for {
|
||||
n, err := authConn.Read(actualResponse[totalBytes:])
|
||||
if err == nil {
|
||||
t.Error("Error Expected", err)
|
||||
} else {
|
||||
return
|
||||
}
|
||||
totalBytes += n
|
||||
if totalBytes >= len(expectedResponse) || time.Now().After(deadline) {
|
||||
break
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func TestConnectionInvReq(t *testing.T) {
|
||||
auth, err := NewHttpAuthenticator(context.Background(), &Config{
|
||||
Request: &RequestConfig{
|
||||
Method: &Method{Value: "Post"},
|
||||
Uri: []string{"/testpath"},
|
||||
Header: []*Header{
|
||||
{
|
||||
Name: "Host",
|
||||
Value: []string{"www.v2ray.com", "www.google.com"},
|
||||
},
|
||||
{
|
||||
Name: "User-Agent",
|
||||
Value: []string{"Test-Agent"},
|
||||
},
|
||||
},
|
||||
},
|
||||
Response: &ResponseConfig{
|
||||
Version: &Version{
|
||||
Value: "1.1",
|
||||
},
|
||||
Status: &Status{
|
||||
Code: "404",
|
||||
Reason: "Not Found",
|
||||
},
|
||||
},
|
||||
})
|
||||
common.Must(err)
|
||||
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
common.Must(err)
|
||||
|
||||
go func() {
|
||||
conn, err := listener.Accept()
|
||||
common.Must(err)
|
||||
authConn := auth.Server(conn)
|
||||
b := make([]byte, 256)
|
||||
for {
|
||||
n, err := authConn.Read(b)
|
||||
if err != nil {
|
||||
authConn.Close()
|
||||
break
|
||||
}
|
||||
_, err = authConn.Write(b[:n])
|
||||
common.Must(err)
|
||||
}
|
||||
}()
|
||||
|
||||
conn, err := net.DialTCP("tcp", nil, listener.Addr().(*net.TCPAddr))
|
||||
common.Must(err)
|
||||
|
||||
conn.Write([]byte("ABCDEFGHIJKMLN\r\n\r\n"))
|
||||
l, _, err := bufio.NewReader(conn).ReadLine()
|
||||
common.Must(err)
|
||||
if !strings.HasPrefix(string(l), "HTTP/1.1 400 Bad Request") {
|
||||
t.Error("Resp to non http conn", string(l))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
11
transport/internet/headers/http/linkedreadRequest.go
Normal file
11
transport/internet/headers/http/linkedreadRequest.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"net/http"
|
||||
|
||||
_ "unsafe" // required to use //go:linkname
|
||||
)
|
||||
|
||||
//go:linkname readRequest net/http.readRequest
|
||||
func readRequest(b *bufio.Reader, deleteHostHeader bool) (req *http.Request, err error)
|
||||
49
transport/internet/headers/http/resp.go
Normal file
49
transport/internet/headers/http/resp.go
Normal file
@@ -0,0 +1,49 @@
|
||||
package http
|
||||
|
||||
var resp400 = &ResponseConfig{
|
||||
Version: &Version{
|
||||
Value: "1.1",
|
||||
},
|
||||
Status: &Status{
|
||||
Code: "400",
|
||||
Reason: "Bad Request",
|
||||
},
|
||||
Header: []*Header{
|
||||
{
|
||||
Name: "Connection",
|
||||
Value: []string{"close"},
|
||||
},
|
||||
{
|
||||
Name: "Cache-Control",
|
||||
Value: []string{"private"},
|
||||
},
|
||||
{
|
||||
Name: "Content-Length",
|
||||
Value: []string{"0"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var resp404 = &ResponseConfig{
|
||||
Version: &Version{
|
||||
Value: "1.1",
|
||||
},
|
||||
Status: &Status{
|
||||
Code: "404",
|
||||
Reason: "Not Found",
|
||||
},
|
||||
Header: []*Header{
|
||||
{
|
||||
Name: "Connection",
|
||||
Value: []string{"close"},
|
||||
},
|
||||
{
|
||||
Name: "Cache-Control",
|
||||
Value: []string{"private"},
|
||||
},
|
||||
{
|
||||
Name: "Content-Length",
|
||||
Value: []string{"0"},
|
||||
},
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user