mirror of
https://github.com/WJQSERVER-STUDIO/ghproxy.git
synced 2026-02-03 00:01:10 +08:00
commit
97ae0044e7
17 changed files with 282 additions and 84 deletions
2
.github/workflows/build-dev.yml
vendored
2
.github/workflows/build-dev.yml
vendored
|
|
@ -46,7 +46,7 @@ jobs:
|
||||||
goarch: [amd64, arm64]
|
goarch: [amd64, arm64]
|
||||||
env:
|
env:
|
||||||
OUTPUT_BINARY: ghproxy
|
OUTPUT_BINARY: ghproxy
|
||||||
GO_VERSION: 1.23.6
|
GO_VERSION: 1.24
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
|
||||||
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
|
|
@ -45,7 +45,7 @@ jobs:
|
||||||
goarch: [amd64, arm64]
|
goarch: [amd64, arm64]
|
||||||
env:
|
env:
|
||||||
OUTPUT_BINARY: ghproxy
|
OUTPUT_BINARY: ghproxy
|
||||||
GO_VERSION: 1.23.6
|
GO_VERSION: 1.24
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
|
||||||
18
CHANGELOG.md
18
CHANGELOG.md
|
|
@ -1,5 +1,23 @@
|
||||||
# 更新日志
|
# 更新日志
|
||||||
|
|
||||||
|
2.2.0
|
||||||
|
---
|
||||||
|
- RELEASE: v2.2.0正式版发布;
|
||||||
|
- CHANGE: 更新Go版本至1.24.0
|
||||||
|
- ADD: 加入`Socks5`和`HTTP(S)`出站支持
|
||||||
|
- CHANGE: 配置新增`Outbound`配置块
|
||||||
|
|
||||||
|
25w13b
|
||||||
|
---
|
||||||
|
- PRE-RELEASE: 此版本是v2.2.0的预发布版本,请勿在生产环境中使用;
|
||||||
|
- CHANGE: 更新Go版本至1.24.0
|
||||||
|
|
||||||
|
25w13a
|
||||||
|
---
|
||||||
|
- PRE-RELEASE: 此版本是v2.2.0的预发布版本,请勿在生产环境中使用;
|
||||||
|
- ADD: 加入`Socks5`和`HTTP(S)`出站支持
|
||||||
|
- CHANGE: 配置新增`Outbound`配置块
|
||||||
|
|
||||||
2.1.0
|
2.1.0
|
||||||
---
|
---
|
||||||
- RELEASE: v2.1.0正式版发布;
|
- RELEASE: v2.1.0正式版发布;
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
25w12d
|
25w13b
|
||||||
22
README.md
22
README.md
|
|
@ -71,6 +71,12 @@ docker run -p 7210:8080 -v ./ghproxy/log/run:/data/ghproxy/log -v ./ghproxy/log/
|
||||||
wget -O install.sh https://raw.githubusercontent.com/WJQSERVER-STUDIO/ghproxy/main/deploy/install.sh && chmod +x install.sh &&./install.sh
|
wget -O install.sh https://raw.githubusercontent.com/WJQSERVER-STUDIO/ghproxy/main/deploy/install.sh && chmod +x install.sh &&./install.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Dev一键部署脚本:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
wget -O install-dev.sh https://raw.githubusercontent.com/WJQSERVER-STUDIO/ghproxy/dev/deploy/install-dev.sh && chmod +x install-dev.sh && ./install-dev.sh
|
||||||
|
```
|
||||||
|
|
||||||
## 配置说明
|
## 配置说明
|
||||||
|
|
||||||
### 外部配置文件
|
### 外部配置文件
|
||||||
|
|
@ -115,6 +121,10 @@ enabled = false # 是否开启速率限制
|
||||||
rateMethod = "total" # "ip" or "total" 速率限制方式
|
rateMethod = "total" # "ip" or "total" 速率限制方式
|
||||||
ratePerMinute = 180 # 每分钟限制请求数量
|
ratePerMinute = 180 # 每分钟限制请求数量
|
||||||
burst = 5 # 突发请求数量
|
burst = 5 # 突发请求数量
|
||||||
|
|
||||||
|
[outbound]
|
||||||
|
enabled = false # 是否使用自定义代理出站
|
||||||
|
url = "socks5://127.0.0.1:1080" # "http://127.0.0.1:7890" 支持Socks5/HTTP(S)出站传输
|
||||||
```
|
```
|
||||||
|
|
||||||
### 黑名单配置
|
### 黑名单配置
|
||||||
|
|
@ -160,3 +170,15 @@ example.com {
|
||||||
|
|
||||||

|

|
||||||

|

|
||||||
|
|
||||||
|
## 赞助
|
||||||
|
|
||||||
|
如果您觉得本项目对您有帮助,欢迎赞助支持,您的赞助将用于Demo服务器开支及开发者时间成本支出,感谢您的支持!
|
||||||
|
|
||||||
|
为爱发电,开源不易
|
||||||
|
|
||||||
|
爱发电: https://afdian.com/a/wjqserver
|
||||||
|
|
||||||
|
### 捐赠列表
|
||||||
|
|
||||||
|
虚位以待...
|
||||||
|
|
|
||||||
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
||||||
2.1.0
|
2.2.0
|
||||||
|
|
@ -13,6 +13,7 @@ type Config struct {
|
||||||
Blacklist BlacklistConfig
|
Blacklist BlacklistConfig
|
||||||
Whitelist WhitelistConfig
|
Whitelist WhitelistConfig
|
||||||
RateLimit RateLimitConfig
|
RateLimit RateLimitConfig
|
||||||
|
Outbound OutboundConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
type ServerConfig struct {
|
type ServerConfig struct {
|
||||||
|
|
@ -62,6 +63,16 @@ type RateLimitConfig struct {
|
||||||
Burst int `toml:"burst"`
|
Burst int `toml:"burst"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
[outbound]
|
||||||
|
enabled = false
|
||||||
|
url = "socks5://127.0.0.1:1080" # "http://127.0.0.1:7890"
|
||||||
|
*/
|
||||||
|
type OutboundConfig struct {
|
||||||
|
Enabled bool `toml:"enabled"`
|
||||||
|
Url string `toml:"url"`
|
||||||
|
}
|
||||||
|
|
||||||
// LoadConfig 从 TOML 配置文件加载配置
|
// LoadConfig 从 TOML 配置文件加载配置
|
||||||
func LoadConfig(filePath string) (*Config, error) {
|
func LoadConfig(filePath string) (*Config, error) {
|
||||||
var config Config
|
var config Config
|
||||||
|
|
|
||||||
|
|
@ -36,3 +36,7 @@ enabled = false
|
||||||
rateMethod = "total" # "ip" or "total"
|
rateMethod = "total" # "ip" or "total"
|
||||||
ratePerMinute = 180
|
ratePerMinute = 180
|
||||||
burst = 5
|
burst = 5
|
||||||
|
|
||||||
|
[outbound]
|
||||||
|
enabled = false
|
||||||
|
url = "socks5://127.0.0.1:1080" # "http://127.0.0.1:7890"
|
||||||
|
|
@ -2,17 +2,17 @@
|
||||||
host = "127.0.0.1"
|
host = "127.0.0.1"
|
||||||
port = 8080
|
port = 8080
|
||||||
sizeLimit = 125 # MB
|
sizeLimit = 125 # MB
|
||||||
enableH2C = false
|
enableH2C = "on"
|
||||||
debug = false
|
debug = false
|
||||||
|
|
||||||
[pages]
|
[pages]
|
||||||
enabled = false
|
enabled = false
|
||||||
staticDir = "/usr/local/ghproxy/pages"
|
staticDir = "/usr/local/ghproxy/pages"
|
||||||
level = "info"
|
|
||||||
|
|
||||||
[log]
|
[log]
|
||||||
logFilePath = "/usr/local/ghproxy/log/ghproxy.log"
|
logFilePath = "/usr/local/ghproxy/log/ghproxy.log"
|
||||||
maxLogSize = 5 # MB
|
maxLogSize = 5 # MB
|
||||||
|
level = "info" # dump, debug, info, warn, error, none
|
||||||
|
|
||||||
[cors]
|
[cors]
|
||||||
enabled = true
|
enabled = true
|
||||||
|
|
@ -36,3 +36,7 @@ enabled = false
|
||||||
rateMethod = "total" # "ip" or "total"
|
rateMethod = "total" # "ip" or "total"
|
||||||
ratePerMinute = 180
|
ratePerMinute = 180
|
||||||
burst = 5
|
burst = 5
|
||||||
|
|
||||||
|
[outbound]
|
||||||
|
enabled = false
|
||||||
|
url = "socks5://127.0.0.1:1080" # "http://127.0.0.1:7890"
|
||||||
|
|
|
||||||
|
|
@ -73,8 +73,51 @@ if [ -z "$ghproxy_dir" ]; then
|
||||||
ghproxy_dir="/usr/local/ghproxy"
|
ghproxy_dir="/usr/local/ghproxy"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
make_systemd_service() {
|
# 创建目录
|
||||||
|
mkdir -p ${ghproxy_dir}
|
||||||
|
mkdir -p ${ghproxy_dir}/config
|
||||||
|
mkdir -p ${ghproxy_dir}/log
|
||||||
|
mkdir -p ${ghproxy_dir}/pages
|
||||||
|
|
||||||
|
# 获取最新版本号
|
||||||
|
VERSION=$(curl -s https://raw.githubusercontent.com/WJQSERVER-STUDIO/ghproxy/dev/DEV-VERSION)
|
||||||
|
wget -q -O ${ghproxy_dir}/VERSION https://raw.githubusercontent.com/WJQSERVER-STUDIO/ghproxy/dev/DEV-VERSION
|
||||||
|
|
||||||
|
# 下载ghproxy
|
||||||
|
wget -q -O ${ghproxy_dir}/ghproxy-linux-$ARCH.tar.gz https://github.com/WJQSERVER-STUDIO/ghproxy/releases/download/$VERSION/ghproxy-linux-$ARCH.tar.gz
|
||||||
|
install tar
|
||||||
|
tar -zxvf ${ghproxy_dir}/ghproxy-linux-$ARCH.tar.gz -C ${ghproxy_dir}
|
||||||
|
chmod +x ${ghproxy_dir}/ghproxy
|
||||||
|
|
||||||
|
# 下载pages
|
||||||
|
wget -q -O ${ghproxy_dir}/pages/index.html https://raw.githubusercontent.com/WJQSERVER-STUDIO/ghproxy/dev/pages/index.html
|
||||||
|
wget -q -O ${ghproxy_dir}/pages/favicon.ico https://raw.githubusercontent.com/WJQSERVER-STUDIO/ghproxy/dev/pages/favicon.ico
|
||||||
|
|
||||||
|
|
||||||
|
# 下载配置文件
|
||||||
|
if [ -f ${ghproxy_dir}/config/config.toml ]; then
|
||||||
|
echo "配置文件已存在, 跳过下载"
|
||||||
|
echo "[WARNING] 请检查配置文件是否正确,DEV版本升级时请注意配置文件兼容性"
|
||||||
|
sleep 2
|
||||||
|
else
|
||||||
|
wget -q -O ${ghproxy_dir}/config/config.toml https://raw.githubusercontent.com/WJQSERVER-STUDIO/ghproxy/dev/deploy/config.toml
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 替换 port = 8080
|
||||||
|
sed -i "s/port = 8080/port = $PORT/g" ${ghproxy_dir}/config/config.toml
|
||||||
|
sed -i 's/host = "127.0.0.1"/host = "'"$IP"'"/g' ${ghproxy_dir}/config/config.toml
|
||||||
|
sed -i "s|staticDir = \"/usr/local/ghproxy/pages\"|staticDir = \"${ghproxy_dir}/pages\"|g" ${ghproxy_dir}/config/config.toml
|
||||||
|
sed -i "s|logFilePath = \"/usr/local/ghproxy/log/ghproxy.log\"|logFilePath = \"${ghproxy_dir}/log/ghproxy.log\"|g" ${ghproxy_dir}/config/config.toml
|
||||||
|
sed -i "s|blacklistFile = \"/usr/local/ghproxy/config/blacklist.json\"|blacklistFile = \"${ghproxy_dir}/config/blacklist.json\"|g" ${ghproxy_dir}/config/config.toml
|
||||||
|
sed -i "s|whitelistFile = \"/usr/local/ghproxy/config/whitelist.json\"|whitelistFile = \"${ghproxy_dir}/config/whitelist.json\"|g" ${ghproxy_dir}/config/config.toml
|
||||||
|
|
||||||
|
# 下载systemd服务文件
|
||||||
|
if [ "$ghproxy_dir" = "/usr/local/ghproxy" ]; then
|
||||||
|
wget -q -O /etc/systemd/system/ghproxy.service https://raw.githubusercontent.com/WJQSERVER-STUDIO/ghproxy/dev/deploy/ghproxy.service
|
||||||
|
else
|
||||||
|
|
||||||
cat <<EOF > /etc/systemd/system/ghproxy.service
|
cat <<EOF > /etc/systemd/system/ghproxy.service
|
||||||
|
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=Github Proxy Service
|
Description=Github Proxy Service
|
||||||
After=network.target
|
After=network.target
|
||||||
|
|
@ -91,51 +134,6 @@ WantedBy=multi-user.target
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
# 创建目录
|
|
||||||
mkdir -p ${ghproxy_dir}
|
|
||||||
mkdir -p ${ghproxy_dir}/config
|
|
||||||
mkdir -p ${ghproxy_dir}/log
|
|
||||||
mkdir -p ${ghproxy_dir}/pages
|
|
||||||
|
|
||||||
# 获取最新版本号
|
|
||||||
VERSION=$(curl -s https://raw.githubusercontent.com/WJQSERVER-STUDIO/ghproxy/main/DEV-VERSION)
|
|
||||||
wget -q -O ${ghproxy_dir}/VERSION https://raw.githubusercontent.com/WJQSERVER-STUDIO/ghproxy/main/DEV-VERSION
|
|
||||||
|
|
||||||
# 下载ghproxy
|
|
||||||
wget -q -O ${ghproxy_dir}/ghproxy https://github.com/WJQSERVER-STUDIO/ghproxy/releases/download/$VERSION/ghproxy-linux-$ARCH.tar.gz
|
|
||||||
install tar
|
|
||||||
tar -zxvf ${ghproxy_dir}/ghproxy-linux-$ARCH.tar.gz -C ${ghproxy_dir}
|
|
||||||
chmod +x ${ghproxy_dir}/ghproxy
|
|
||||||
|
|
||||||
# 下载pages
|
|
||||||
wget -q -O ${ghproxy_dir}/pages/index.html https://raw.githubusercontent.com/WJQSERVER-STUDIO/ghproxy/main/pages/index.html
|
|
||||||
wget -q -O ${ghproxy_dir}/pages/favicon.ico https://raw.githubusercontent.com/WJQSERVER-STUDIO/ghproxy/main/pages/favicon.ico
|
|
||||||
|
|
||||||
|
|
||||||
# 下载配置文件
|
|
||||||
if [ -f ${ghproxy_dir}/config/config.toml ]; then
|
|
||||||
echo "配置文件已存在, 跳过下载"
|
|
||||||
echo "[WARNING] 请检查配置文件是否正确,DEV版本升级时请注意配置文件兼容性"
|
|
||||||
sleep 2
|
|
||||||
else
|
|
||||||
wget -q -O ${ghproxy_dir}/config/config.toml https://raw.githubusercontent.com/WJQSERVER-STUDIO/ghproxy/main/deploy/config.toml
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 替换 port = 8080
|
|
||||||
sed -i "s/port = 8080/port = $PORT/g" ${ghproxy_dir}/config/config.toml
|
|
||||||
sed -i 's/host = "127.0.0.1"/host = "'"$IP"'"/g' ${ghproxy_dir}/config/config.toml
|
|
||||||
sed -i "s|staticDir = \"/usr/local/ghproxy/pages\"|staticDir = \"${ghproxy_dir}/pages\"|g" ${ghproxy_dir}/config/config.toml
|
|
||||||
sed -i "s|logFilePath = \"/usr/local/ghproxy/log/ghproxy.log\"|logFilePath = \"${ghproxy_dir}/log/ghproxy.log\"|g" ${ghproxy_dir}/config/config.toml
|
|
||||||
sed -i "s|blacklistFile = \"/usr/local/ghproxy/config/blacklist.json\"|blacklistFile = \"${ghproxy_dir}/config/blacklist.json\"|g" ${ghproxy_dir}/config/config.toml
|
|
||||||
sed -i "s|whitelistFile = \"/usr/local/ghproxy/config/whitelist.json\"|whitelistFile = \"${ghproxy_dir}/config/whitelist.json\"|g" ${ghproxy_dir}/config/config.toml
|
|
||||||
|
|
||||||
# 下载systemd服务文件
|
|
||||||
if [ "$ghproxy_dir" = "/usr/local/ghproxy" ]; then
|
|
||||||
wget -q -O /etc/systemd/system/ghproxy.service https://raw.githubusercontent.com/WJQSERVER-STUDIO/ghproxy/main/deploy/ghproxy.service
|
|
||||||
else
|
|
||||||
make_systemd_service()
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 启动ghproxy
|
# 启动ghproxy
|
||||||
|
|
|
||||||
|
|
@ -73,26 +73,6 @@ if [ -z "$ghproxy_dir" ]; then
|
||||||
ghproxy_dir="/usr/local/ghproxy"
|
ghproxy_dir="/usr/local/ghproxy"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
make_systemd_service() {
|
|
||||||
cat <<EOF > /etc/systemd/system/ghproxy.service
|
|
||||||
[Unit]
|
|
||||||
Description=Github Proxy Service
|
|
||||||
After=network.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
ExecStart=/bin/bash -c '$ghproxy_dir/ghproxy -cfg $ghproxy_dir/config/config.toml > $ghproxy_dir/log/run.log 2>&1'
|
|
||||||
WorkingDirectory=$ghproxy_dir
|
|
||||||
Restart=always
|
|
||||||
User=root
|
|
||||||
Group=root
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
|
|
||||||
EOF
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
# 创建目录
|
# 创建目录
|
||||||
mkdir -p ${ghproxy_dir}
|
mkdir -p ${ghproxy_dir}
|
||||||
mkdir -p ${ghproxy_dir}/config
|
mkdir -p ${ghproxy_dir}/config
|
||||||
|
|
@ -104,7 +84,7 @@ VERSION=$(curl -s https://raw.githubusercontent.com/WJQSERVER-STUDIO/ghproxy/mai
|
||||||
wget -q -O ${ghproxy_dir}/VERSION https://raw.githubusercontent.com/WJQSERVER-STUDIO/ghproxy/main/VERSION
|
wget -q -O ${ghproxy_dir}/VERSION https://raw.githubusercontent.com/WJQSERVER-STUDIO/ghproxy/main/VERSION
|
||||||
|
|
||||||
# 下载ghproxy
|
# 下载ghproxy
|
||||||
wget -q -O ${ghproxy_dir}/ghproxy https://github.com/WJQSERVER-STUDIO/ghproxy/releases/download/${VERSION}/ghproxy-linux-${ARCH}.tar.gz
|
wget -q -O ${ghproxy_dir}/ghproxy-linux-$ARCH.tar.gz https://github.com/WJQSERVER-STUDIO/ghproxy/releases/download/${VERSION}/ghproxy-linux-${ARCH}.tar.gz
|
||||||
install tar
|
install tar
|
||||||
tar -zxvf ${ghproxy_dir}/ghproxy-linux-$ARCH.tar.gz -C ${ghproxy_dir}
|
tar -zxvf ${ghproxy_dir}/ghproxy-linux-$ARCH.tar.gz -C ${ghproxy_dir}
|
||||||
chmod +x ${ghproxy_dir}/ghproxy
|
chmod +x ${ghproxy_dir}/ghproxy
|
||||||
|
|
@ -135,7 +115,25 @@ sed -i "s|whitelistFile = \"/usr/local/ghproxy/config/whitelist.json\"|whitelist
|
||||||
if [ "$ghproxy_dir" = "/usr/local/ghproxy" ]; then
|
if [ "$ghproxy_dir" = "/usr/local/ghproxy" ]; then
|
||||||
wget -q -O /etc/systemd/system/ghproxy.service https://raw.githubusercontent.com/WJQSERVER-STUDIO/ghproxy/main/deploy/ghproxy.service
|
wget -q -O /etc/systemd/system/ghproxy.service https://raw.githubusercontent.com/WJQSERVER-STUDIO/ghproxy/main/deploy/ghproxy.service
|
||||||
else
|
else
|
||||||
make_systemd_service()
|
|
||||||
|
cat <<EOF > /etc/systemd/system/ghproxy.service
|
||||||
|
|
||||||
|
[Unit]
|
||||||
|
Description=Github Proxy Service
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=/bin/bash -c '$ghproxy_dir/ghproxy -cfg $ghproxy_dir/config/config.toml > $ghproxy_dir/log/run.log 2>&1'
|
||||||
|
WorkingDirectory=$ghproxy_dir
|
||||||
|
Restart=always
|
||||||
|
User=root
|
||||||
|
Group=root
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
|
||||||
|
EOF
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 启动ghproxy
|
# 启动ghproxy
|
||||||
|
|
|
||||||
4
go.mod
4
go.mod
|
|
@ -1,11 +1,12 @@
|
||||||
module ghproxy
|
module ghproxy
|
||||||
|
|
||||||
go 1.23.6
|
go 1.24.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/BurntSushi/toml v1.4.0
|
github.com/BurntSushi/toml v1.4.0
|
||||||
github.com/WJQSERVER-STUDIO/go-utils/logger v1.3.0
|
github.com/WJQSERVER-STUDIO/go-utils/logger v1.3.0
|
||||||
github.com/gin-gonic/gin v1.10.0
|
github.com/gin-gonic/gin v1.10.0
|
||||||
|
golang.org/x/net v0.35.0
|
||||||
golang.org/x/time v0.10.0
|
golang.org/x/time v0.10.0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -31,7 +32,6 @@ require (
|
||||||
github.com/ugorji/go/codec v1.2.12 // indirect
|
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||||
golang.org/x/arch v0.14.0 // indirect
|
golang.org/x/arch v0.14.0 // indirect
|
||||||
golang.org/x/crypto v0.33.0 // indirect
|
golang.org/x/crypto v0.33.0 // indirect
|
||||||
golang.org/x/net v0.34.0 // indirect
|
|
||||||
golang.org/x/sys v0.30.0 // indirect
|
golang.org/x/sys v0.30.0 // indirect
|
||||||
golang.org/x/text v0.22.0 // indirect
|
golang.org/x/text v0.22.0 // indirect
|
||||||
google.golang.org/protobuf v1.36.5 // indirect
|
google.golang.org/protobuf v1.36.5 // indirect
|
||||||
|
|
|
||||||
2
go.sum
2
go.sum
|
|
@ -73,6 +73,8 @@ golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
|
||||||
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
|
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
|
||||||
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
|
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
|
||||||
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
|
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
|
||||||
|
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
|
||||||
|
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
||||||
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
|
|
||||||
6
main.go
6
main.go
|
|
@ -100,8 +100,8 @@ func setupRateLimit(cfg *config.Config) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func InitReq() {
|
func InitReq(cfg *config.Config) {
|
||||||
proxy.InitReq()
|
proxy.InitReq(cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
@ -109,7 +109,7 @@ func init() {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
loadConfig()
|
loadConfig()
|
||||||
setupLogger(cfg)
|
setupLogger(cfg)
|
||||||
InitReq()
|
InitReq(cfg)
|
||||||
loadlist(cfg)
|
loadlist(cfg)
|
||||||
setupRateLimit(cfg)
|
setupRateLimit(cfg)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,9 +22,9 @@ var (
|
||||||
BufferPool *sync.Pool
|
BufferPool *sync.Pool
|
||||||
)
|
)
|
||||||
|
|
||||||
func InitReq() {
|
func InitReq(cfg *config.Config) {
|
||||||
initChunkedHTTPClient()
|
initChunkedHTTPClient(cfg)
|
||||||
initGitHTTPClient()
|
initGitHTTPClient(cfg)
|
||||||
|
|
||||||
// 初始化固定大小的缓存池
|
// 初始化固定大小的缓存池
|
||||||
BufferPool = &sync.Pool{
|
BufferPool = &sync.Pool{
|
||||||
|
|
@ -34,7 +34,7 @@ func InitReq() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func initChunkedHTTPClient() {
|
func initChunkedHTTPClient(cfg *config.Config) {
|
||||||
ctr = &http.Transport{
|
ctr = &http.Transport{
|
||||||
MaxIdleConns: 100,
|
MaxIdleConns: 100,
|
||||||
MaxConnsPerHost: 60,
|
MaxConnsPerHost: 60,
|
||||||
|
|
@ -47,6 +47,9 @@ func initChunkedHTTPClient() {
|
||||||
KeepAlive: 30 * time.Second,
|
KeepAlive: 30 * time.Second,
|
||||||
}).DialContext,
|
}).DialContext,
|
||||||
}
|
}
|
||||||
|
if cfg.Outbound.Enabled {
|
||||||
|
initTransport(cfg, ctr)
|
||||||
|
}
|
||||||
cclient = &http.Client{
|
cclient = &http.Client{
|
||||||
Transport: ctr,
|
Transport: ctr,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
135
proxy/dial.go
Normal file
135
proxy/dial.go
Normal file
|
|
@ -0,0 +1,135 @@
|
||||||
|
/*
|
||||||
|
made&PR by @lfhy
|
||||||
|
https://github.com/WJQSERVER-STUDIO/ghproxy/pull/46
|
||||||
|
*/
|
||||||
|
|
||||||
|
package proxy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"ghproxy/config"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"golang.org/x/net/proxy"
|
||||||
|
)
|
||||||
|
|
||||||
|
// initTransport 初始化 HTTP 传输层的代理设置
|
||||||
|
func initTransport(cfg *config.Config, transport *http.Transport) {
|
||||||
|
// 如果代理功能未启用,直接返回
|
||||||
|
if !cfg.Outbound.Enabled {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果代理 URL 未设置,使用环境变量中的代理配置
|
||||||
|
if cfg.Outbound.Url == "" {
|
||||||
|
transport.Proxy = http.ProxyFromEnvironment
|
||||||
|
logWarning("Outbound proxy is not set, using environment variables")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 尝试解析代理 URL
|
||||||
|
proxyInfo, err := url.Parse(cfg.Outbound.Url)
|
||||||
|
if err != nil {
|
||||||
|
// 如果解析失败,记录错误日志并使用环境变量中的代理配置
|
||||||
|
logError("Failed to parse outbound proxy URL %v", err)
|
||||||
|
transport.Proxy = http.ProxyFromEnvironment
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据代理 URL 的 scheme(协议类型)选择代理类型
|
||||||
|
switch strings.ToLower(proxyInfo.Scheme) {
|
||||||
|
case "http", "https": // 如果是 HTTP/HTTPS 代理
|
||||||
|
transport.Proxy = http.ProxyURL(proxyInfo) // 设置 HTTP(S) 代理
|
||||||
|
logInfo("Using HTTP(S) proxy: %s", proxyInfo.Redacted())
|
||||||
|
case "socks5": // 如果是 SOCKS5 代理
|
||||||
|
// 调用 newProxyDial 创建 SOCKS5 代理拨号器
|
||||||
|
proxyDialer := newProxyDial(cfg.Outbound.Url)
|
||||||
|
transport.Proxy = nil // 禁用 HTTP Proxy 设置,因为 SOCKS5 不需要 HTTP Proxy
|
||||||
|
|
||||||
|
// 尝试将 Dialer 转换为支持上下文的 ContextDialer
|
||||||
|
if contextDialer, ok := proxyDialer.(proxy.ContextDialer); ok {
|
||||||
|
transport.DialContext = contextDialer.DialContext
|
||||||
|
} else {
|
||||||
|
// 如果不支持 ContextDialer,则回退到传统的 Dial 方法
|
||||||
|
transport.Dial = proxyDialer.Dial
|
||||||
|
logWarning("SOCKS5 dialer does not support ContextDialer, using legacy Dial")
|
||||||
|
}
|
||||||
|
logInfo("Using SOCKS5 proxy chain: %s", cfg.Outbound.Url)
|
||||||
|
default: // 如果代理协议不支持
|
||||||
|
logError("Unsupported proxy scheme: %s", proxyInfo.Scheme)
|
||||||
|
transport.Proxy = http.ProxyFromEnvironment // 回退到环境变量代理
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// newProxyDial 创建一个 SOCKS5 代理拨号器
|
||||||
|
func newProxyDial(proxyUrls string) proxy.Dialer {
|
||||||
|
var proxyDialer proxy.Dialer = proxy.Direct // 初始为直接连接,不使用代理
|
||||||
|
|
||||||
|
// 支持多个代理 URL(以逗号分隔)
|
||||||
|
for _, proxyUrl := range strings.Split(proxyUrls, ",") {
|
||||||
|
proxyUrl = strings.TrimSpace(proxyUrl) // 去除首尾空格
|
||||||
|
if proxyUrl == "" { // 跳过空的代理 URL
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析代理 URL
|
||||||
|
urlInfo, err := url.Parse(proxyUrl)
|
||||||
|
if err != nil {
|
||||||
|
// 如果 URL 解析失败,记录错误日志并跳过
|
||||||
|
logError("Failed to parse proxy URL %q: %v", proxyUrl, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查代理协议是否为 SOCKS5
|
||||||
|
if urlInfo.Scheme != "socks5" {
|
||||||
|
logWarning("Skipping non-SOCKS5 proxy: %s", urlInfo.Scheme)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析代理认证信息(用户名和密码)
|
||||||
|
auth := parseAuth(urlInfo)
|
||||||
|
|
||||||
|
// 创建 SOCKS5 代理拨号器
|
||||||
|
dialer, err := createSocksDialer(urlInfo.Host, auth, proxyDialer)
|
||||||
|
if err != nil {
|
||||||
|
// 如果创建失败,记录错误日志并跳过
|
||||||
|
logError("Failed to create SOCKS5 dialer for %q: %v", proxyUrl, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新代理拨号器,支持代理链
|
||||||
|
proxyDialer = dialer
|
||||||
|
}
|
||||||
|
|
||||||
|
return proxyDialer
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseAuth 解析代理 URL 中的认证信息(用户名和密码)
|
||||||
|
func parseAuth(urlInfo *url.URL) *proxy.Auth {
|
||||||
|
// 如果 URL 中没有用户信息,返回 nil
|
||||||
|
if urlInfo.User == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取用户名
|
||||||
|
username := urlInfo.User.Username()
|
||||||
|
|
||||||
|
// 获取密码(注意:Password() 返回两个值,需要显式处理第二个值)
|
||||||
|
password, passwordSet := urlInfo.User.Password()
|
||||||
|
if !passwordSet {
|
||||||
|
password = "" // 如果密码未设置,使用空字符串
|
||||||
|
}
|
||||||
|
|
||||||
|
// 返回包含用户名和密码的认证信息
|
||||||
|
return &proxy.Auth{
|
||||||
|
User: username,
|
||||||
|
Password: password, // 允许空密码
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// createSocksDialer 创建 SOCKS5 拨号器
|
||||||
|
func createSocksDialer(host string, auth *proxy.Auth, previous proxy.Dialer) (proxy.Dialer, error) {
|
||||||
|
// 调用 golang.org/x/net/proxy 提供的 SOCKS5 方法创建拨号器
|
||||||
|
return proxy.SOCKS5("tcp", host, auth, previous)
|
||||||
|
}
|
||||||
|
|
@ -17,12 +17,15 @@ var (
|
||||||
gtr *http.Transport
|
gtr *http.Transport
|
||||||
)
|
)
|
||||||
|
|
||||||
func initGitHTTPClient() {
|
func initGitHTTPClient(cfg *config.Config) {
|
||||||
gtr = &http.Transport{
|
gtr = &http.Transport{
|
||||||
MaxIdleConns: 30,
|
MaxIdleConns: 30,
|
||||||
MaxConnsPerHost: 30,
|
MaxConnsPerHost: 30,
|
||||||
IdleConnTimeout: 30 * time.Second,
|
IdleConnTimeout: 30 * time.Second,
|
||||||
}
|
}
|
||||||
|
if cfg.Outbound.Enabled {
|
||||||
|
initTransport(cfg, gtr)
|
||||||
|
}
|
||||||
gclient = &http.Client{
|
gclient = &http.Client{
|
||||||
Transport: gtr,
|
Transport: gtr,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue