feat: add SS2022 HTTP obfs option

This commit is contained in:
OpenClaw
2026-06-29 03:13:59 +00:00
parent 0250e5efe8
commit a89108cf52

View File

@@ -23,6 +23,11 @@ METHOD_2022=""
PORT_RAW=""
KEY_RAW=""
METHOD_RAW=""
PORT_OBFS=""
KEY_OBFS=""
METHOD_OBFS=""
OBFS_BACKEND_PORT=""
OBFS_HOST=""
NODE_MODE=""
# ============ 基础检测 ============
@@ -45,9 +50,9 @@ get_pkg_manager() {
install_deps() {
info "安装依赖..."
case $PKG in
apt) apt update -qq &>/dev/null; apt install -y -qq curl openssl xz-utils tar chrony python3 &>/dev/null ;;
yum) yum install -y -q curl openssl xz tar chrony python3 &>/dev/null ;;
apk) apk add --quiet curl openssl xz tar chrony python3 &>/dev/null ;;
apt) apt update -qq &>/dev/null; apt install -y -qq curl openssl xz-utils tar chrony python3 ca-certificates &>/dev/null ;;
yum) yum install -y -q curl openssl xz tar chrony python3 ca-certificates &>/dev/null ;;
apk) apk add --quiet curl openssl xz tar chrony python3 ca-certificates &>/dev/null ;;
esac
}
@@ -179,6 +184,41 @@ install_ssrust() {
/usr/local/bin/ssserver --version && info "shadowsocks-rust 安装完成" || error "安装验证失败"
}
# ============ 安装 simple-obfs ============
install_simple_obfs() {
command -v obfs-server &>/dev/null && return 0
info "安装 simple-obfs (HTTP 伪装插件)..."
case $PKG in
apt)
apt update -qq &>/dev/null
apt install -y -qq --no-install-recommends git build-essential autoconf automake libtool pkg-config libssl-dev libev-dev libc-ares-dev libpcre2-dev asciidoc xmlto &>/dev/null \
|| error "安装 simple-obfs 编译依赖失败"
;;
yum)
yum install -y -q git gcc gcc-c++ make autoconf automake libtool pkgconfig openssl-devel libev-devel c-ares-devel pcre-devel asciidoc xmlto &>/dev/null \
|| error "安装 simple-obfs 编译依赖失败"
;;
apk)
apk add --quiet git build-base autoconf automake libtool pkgconf openssl-dev libev-dev c-ares-dev pcre2-dev asciidoc xmlto &>/dev/null \
|| error "安装 simple-obfs 编译依赖失败"
;;
esac
rm -rf /tmp/simple-obfs-src
git clone --depth=1 https://github.com/shadowsocks/simple-obfs.git /tmp/simple-obfs-src &>/dev/null \
|| error "下载 simple-obfs 失败"
cd /tmp/simple-obfs-src
git submodule update --init --recursive &>/dev/null || true
./autogen.sh &>/tmp/simple-obfs-autogen.log || error "simple-obfs autogen 失败: /tmp/simple-obfs-autogen.log"
./configure --disable-documentation &>/tmp/simple-obfs-configure.log || error "simple-obfs configure 失败: /tmp/simple-obfs-configure.log"
make -j"$(nproc 2>/dev/null || echo 1)" &>/tmp/simple-obfs-make.log || error "simple-obfs 编译失败: /tmp/simple-obfs-make.log"
make install &>/tmp/simple-obfs-install.log || error "simple-obfs 安装失败: /tmp/simple-obfs-install.log"
ldconfig 2>/dev/null || true
command -v obfs-server &>/dev/null || error "simple-obfs 安装验证失败"
info "simple-obfs 安装完成"
}
# ============ 节点选择 + 端口密码 + 写配置 ============
select_and_configure() {
SERVER_IP=$(get_ip)
@@ -187,6 +227,7 @@ select_and_configure() {
# 清空
PORT_2022="" ; KEY_2022="" ; METHOD_2022=""
PORT_RAW="" ; KEY_RAW="" ; METHOD_RAW=""
PORT_OBFS="" ; KEY_OBFS="" ; METHOD_OBFS="" ; OBFS_BACKEND_PORT="" ; OBFS_HOST=""
echo ""
echo -e "${CYAN}════════════════════════════════════════${NC}"
@@ -196,8 +237,9 @@ select_and_configure() {
echo -e " ${GREEN}1.${NC} SS2022-128 (2022-blake3-aes-128-gcm) — 新协议,推荐"
echo -e " ${GREEN}2.${NC} SS-AES-128 (aes-128-gcm) — 传统协议,兼容性好"
echo -e " ${GREEN}3.${NC} 双节点全装 (SS2022 + SS128)"
echo -e " ${GREEN}4.${NC} SS2022-128 + HTTP obfs (simple-obfs 伪装)"
echo ""
read -rp "请选择 [1-3] (默认3): " node_choice
read -rp "请选择 [1-4] (默认3): " node_choice
node_choice=${node_choice:-3}
if [[ "$node_choice" == "1" || "$node_choice" == "3" ]]; then
@@ -224,6 +266,24 @@ select_and_configure() {
METHOD_RAW="aes-128-gcm"
fi
if [[ "$node_choice" == "4" ]]; then
local dp3=$((RANDOM % 10000 + 20000))
local dk3=$(openssl rand -base64 16)
local bp=$((RANDOM % 10000 + 40000))
echo ""
echo -e " ${GREEN}SS2022-128 + HTTP obfs 配置:${NC}"
read -rp " 对外端口 [回车=${dp3}]: " PORT_OBFS
PORT_OBFS=${PORT_OBFS:-$dp3}
read -rp " 后端本地端口 [回车=${bp}]: " OBFS_BACKEND_PORT
OBFS_BACKEND_PORT=${OBFS_BACKEND_PORT:-$bp}
read -rp " 密码 [回车=${dk3}]: " KEY_OBFS
KEY_OBFS=${KEY_OBFS:-$dk3}
read -rp " 伪装 Host [回车=www.microsoft.com]: " OBFS_HOST
OBFS_HOST=${OBFS_HOST:-www.microsoft.com}
METHOD_OBFS="2022-blake3-aes-128-gcm"
install_simple_obfs
fi
# 写 JSON 配置
python3 -c "
import json
@@ -246,11 +306,32 @@ if '${PORT_RAW}':
'timeout': 300,
'fast_open': True
})
if '${PORT_OBFS}':
servers.append({
'server': '127.0.0.1',
'server_port': int('${OBFS_BACKEND_PORT}'),
'method': '${METHOD_OBFS}',
'password': '${KEY_OBFS}',
'timeout': 300,
'fast_open': True
})
with open('/etc/shadowsocks-rust/config.json', 'w') as f:
json.dump({'servers': servers}, f, indent=4)
print('OK')
" || error "生成配置失败"
if [[ -n "$PORT_OBFS" ]]; then
cat > /etc/shadowsocks-rust/obfs.env <<EOF
PORT_OBFS=${PORT_OBFS}
KEY_OBFS=${KEY_OBFS}
METHOD_OBFS=${METHOD_OBFS}
OBFS_BACKEND_PORT=${OBFS_BACKEND_PORT}
OBFS_HOST=${OBFS_HOST}
EOF
else
rm -f /etc/shadowsocks-rust/obfs.env
fi
info "配置文件: /etc/shadowsocks-rust/config.json"
}
@@ -282,6 +363,49 @@ EOF
journalctl -u ss-rust -n 5 --no-pager
error "ss-rust 服务启动失败"
fi
setup_obfs_service
}
setup_obfs_service() {
if [[ ! -f /etc/shadowsocks-rust/obfs.env ]]; then
systemctl disable --now ss-rust-obfs 2>/dev/null || true
rm -f /etc/systemd/system/ss-rust-obfs.service
systemctl daemon-reload
return 0
fi
# shellcheck disable=SC1091
source /etc/shadowsocks-rust/obfs.env
install_simple_obfs
cat > /etc/systemd/system/ss-rust-obfs.service << EOF
[Unit]
Description=Shadowsocks simple-obfs HTTP Frontend
After=network.target ss-rust.service
Wants=ss-rust.service
[Service]
Type=simple
ExecStart=/usr/local/bin/obfs-server -s 0.0.0.0 -p ${PORT_OBFS} -r 127.0.0.1:${OBFS_BACKEND_PORT} --obfs http --http-method GET
Restart=on-failure
RestartSec=5
LimitNOFILE=65535
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now ss-rust-obfs
sleep 1
if systemctl is-active --quiet ss-rust-obfs; then
info "simple-obfs 服务启动成功: 0.0.0.0:${PORT_OBFS} -> 127.0.0.1:${OBFS_BACKEND_PORT}"
else
journalctl -u ss-rust-obfs -n 10 --no-pager
error "simple-obfs 服务启动失败"
fi
}
# ============ 读取现有配置 ============
@@ -290,6 +414,7 @@ load_config() {
SERVER_IP=$(get_ip)
PORT_2022="" ; KEY_2022="" ; METHOD_2022=""
PORT_RAW="" ; KEY_RAW="" ; METHOD_RAW=""
PORT_OBFS="" ; KEY_OBFS="" ; METHOD_OBFS="" ; OBFS_BACKEND_PORT="" ; OBFS_HOST=""
eval $(python3 -c "
import json
@@ -306,6 +431,13 @@ for s in c['servers']:
print(f'KEY_RAW={s[\"password\"]}')
print(f'METHOD_RAW={m}')
" 2>/dev/null)
if [[ -f /etc/shadowsocks-rust/obfs.env ]]; then
# shellcheck disable=SC1091
source /etc/shadowsocks-rust/obfs.env
if [[ -n "$OBFS_BACKEND_PORT" && "$PORT_2022" == "$OBFS_BACKEND_PORT" ]]; then
PORT_2022="" ; KEY_2022="" ; METHOD_2022=""
fi
fi
return 0
}
@@ -335,6 +467,18 @@ gen_subscribe() {
info_txt="${info_txt}【SS-AES-128】传统协议\n 地址: ${SERVER_IP}\n 端口: ${PORT_RAW}\n 加密: ${METHOD_RAW}\n 密码: ${KEY_RAW}\n\n"
fi
if [[ -n "$PORT_OBFS" ]]; then
local plugin_raw="obfs-local;obfs=http;obfs-host=${OBFS_HOST}"
local plugin_enc
plugin_enc=$(PLUGIN_RAW="$plugin_raw" python3 -c 'import os, urllib.parse; print(urllib.parse.quote(os.environ["PLUGIN_RAW"], safe=""))')
local uri="ss://$(echo -n "${METHOD_OBFS}:${KEY_OBFS}" | base64 -w0)@${SERVER_IP}:${PORT_OBFS}/?plugin=${plugin_enc}#SS2022-OBFS-HTTP"
URI_OBFS="$uri"
uris="${uris}${uri}\n"
surge="${surge}SS2022-OBFS-HTTP = ss, ${SERVER_IP}, ${PORT_OBFS}, encrypt-method=${METHOD_OBFS}, password=${KEY_OBFS}, obfs=http, obfs-host=${OBFS_HOST}\n"
clash="${clash} - name: SS2022-OBFS-HTTP\n type: ss\n server: ${SERVER_IP}\n port: ${PORT_OBFS}\n cipher: ${METHOD_OBFS}\n password: \"${KEY_OBFS}\"\n udp: false\n plugin: obfs\n plugin-opts:\n mode: http\n host: ${OBFS_HOST}\n\n"
info_txt="${info_txt}【SS2022 + HTTP obfs】simple-obfs 伪装\n 地址: ${SERVER_IP}\n 端口: ${PORT_OBFS}\n 加密: ${METHOD_OBFS}\n 密码: ${KEY_OBFS}\n 插件: obfs/http\n Host: ${OBFS_HOST}\n 后端: 127.0.0.1:${OBFS_BACKEND_PORT}\n\n"
fi
echo -e "$uris" | base64 -w0 > "$sub_dir/subscribe.txt"
echo -e "# Surge SS | $(date '+%Y-%m-%d %H:%M:%S') | ${SERVER_IP}\n[Proxy]\n${surge}" > "$sub_dir/surge.conf"
@@ -369,16 +513,29 @@ show_result() {
echo ""
fi
if [[ -n "$PORT_OBFS" ]]; then
echo -e "${GREEN}【SS2022 + HTTP obfs】simple-obfs 伪装${NC}"
echo -e " 地址: ${SERVER_IP}"
echo -e " 端口: ${YELLOW}${PORT_OBFS}${NC}"
echo -e " 加密: ${METHOD_OBFS}"
echo -e " 密码: ${YELLOW}${KEY_OBFS}${NC}"
echo -e " 插件: obfs / http"
echo -e " Host: ${OBFS_HOST}"
echo ""
fi
echo -e "${CYAN}────────────────────────────────────────${NC}"
echo -e "${GREEN}【Surge 格式】${NC}"
[[ -n "$PORT_2022" ]] && echo " SS2022-128 = ss, ${SERVER_IP}, ${PORT_2022}, encrypt-method=${METHOD_2022}, password=${KEY_2022}"
[[ -n "$PORT_RAW" ]] && echo " SS-AES-128 = ss, ${SERVER_IP}, ${PORT_RAW}, encrypt-method=${METHOD_RAW}, password=${KEY_RAW}"
[[ -n "$PORT_OBFS" ]] && echo " SS2022-OBFS-HTTP = ss, ${SERVER_IP}, ${PORT_OBFS}, encrypt-method=${METHOD_OBFS}, password=${KEY_OBFS}, obfs=http, obfs-host=${OBFS_HOST}"
echo ""
echo -e "${CYAN}────────────────────────────────────────${NC}"
echo -e "${GREEN}【SS 链接】${NC}"
[[ -n "${URI_2022:-}" ]] && echo " ${URI_2022}"
[[ -n "${URI_RAW:-}" ]] && echo " ${URI_RAW}"
[[ -n "${URI_OBFS:-}" ]] && echo " ${URI_OBFS}"
echo ""
echo -e "${CYAN}────────────────────────────────────────${NC}"
@@ -422,6 +579,7 @@ if 0 <= idx < len(c['servers']):
json.dump(c, f, indent=4)
"
systemctl restart ss-rust
setup_obfs_service
gen_subscribe
info "端口已改为 ${new_port}"
}
@@ -438,7 +596,25 @@ for s in c['servers']:
with open('/etc/shadowsocks-rust/config.json','w') as f:
json.dump(c, f, indent=4)
"
if [[ -f /etc/shadowsocks-rust/obfs.env ]]; then
local new_obfs_key
new_obfs_key=$(openssl rand -base64 16)
sed -i "s|^KEY_OBFS=.*|KEY_OBFS=${new_obfs_key}|" /etc/shadowsocks-rust/obfs.env
# shellcheck disable=SC1091
source /etc/shadowsocks-rust/obfs.env
python3 -c "
import json
with open('/etc/shadowsocks-rust/config.json') as f:
c = json.load(f)
for s in c.get('servers', []):
if str(s.get('server_port')) == '${OBFS_BACKEND_PORT}':
s['password'] = '${KEY_OBFS}'
with open('/etc/shadowsocks-rust/config.json','w') as f:
json.dump(c, f, indent=4)
"
fi
systemctl restart ss-rust
setup_obfs_service
gen_subscribe
info "密钥已重置"
show_result
@@ -590,9 +766,9 @@ SYSCTL
# ============ 卸载 ============
uninstall() {
warn "卸载 shadowsocks-rust..."
systemctl stop ss-rust 2>/dev/null
systemctl disable ss-rust 2>/dev/null
rm -f /etc/systemd/system/ss-rust.service
systemctl stop ss-rust ss-rust-obfs 2>/dev/null
systemctl disable ss-rust ss-rust-obfs 2>/dev/null
rm -f /etc/systemd/system/ss-rust.service /etc/systemd/system/ss-rust-obfs.service
rm -f /usr/local/bin/ssserver /usr/local/bin/sslocal /usr/local/bin/ssurl
rm -rf /etc/shadowsocks-rust
systemctl daemon-reload
@@ -644,8 +820,8 @@ show_menu() {
4) reset_keys ;;
5) systemctl start ss-rust && info "已启动" ;;
6) systemctl stop ss-rust && info "已停止" ;;
7) systemctl restart ss-rust && info "已重启" ;;
8) journalctl -u ss-rust --no-pager -n 30 ;;
7) systemctl restart ss-rust; setup_obfs_service; info "已重启" ;;
8) journalctl -u ss-rust -u ss-rust-obfs --no-pager -n 50 ;;
9) uninstall ;;
10) setup_bbr ;;
11) get_pkg_manager; install_deps; sync_time ;;
@@ -661,10 +837,10 @@ main() {
install) do_install ;;
uninstall|remove) uninstall ;;
show|config|info) show_config ;;
restart) systemctl restart ss-rust && info "已重启" ;;
restart) systemctl restart ss-rust; setup_obfs_service; info "已重启" ;;
start) systemctl start ss-rust && info "已启动" ;;
stop) systemctl stop ss-rust && info "已停止" ;;
log|logs) journalctl -u ss-rust --no-pager -n 30 ;;
log|logs) journalctl -u ss-rust -u ss-rust-obfs --no-pager -n 50 ;;
reset) reset_keys ;;
bbr) setup_bbr ;;
sync|time) get_pkg_manager; install_deps; sync_time ;;