feat: add SS2022 HTTP obfs option
This commit is contained in:
198
ss-rust.sh
198
ss-rust.sh
@@ -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 ;;
|
||||
|
||||
Reference in New Issue
Block a user