Compare commits

..

36 Commits

Author SHA1 Message Date
svefnz c1dd5bf640 fix: recursively update explicit ports in imported Caddy configuration files
Main / build (push) Waiting to run
2026-07-08 13:04:50 +08:00
svefnz f05e5e0410 fix: make Caddyfile global config update robust to avoid IPv6 conflicts
Main / build (push) Waiting to run
2026-07-08 12:54:48 +08:00
svefnz f07100c074 fix: override caddy-based node client port to 443 when HAProxy is active
Main / build (push) Waiting to run
2026-07-08 12:35:46 +08:00
svefnz 90a8ad633f fix: resolve node remarks printed as default prefix upon initial node creation
Main / build (push) Waiting to run
2026-07-08 12:24:13 +08:00
svefnz 5a102d7306 feat: support custom remarks for node connection links
Main / build (push) Waiting to run
2026-07-08 02:11:04 +08:00
svefnz 17d82a1ead docs: clarify interactive prompts and output notices for HAProxy L4 routing
Main / build (push) Waiting to run
2026-07-08 02:05:14 +08:00
svefnz 3f456ad592 fix: remove fallback block generation from sing-box VLESS configuration since HAProxy handles fallback
Main / build (push) Waiting to run
2026-07-08 02:00:22 +08:00
svefnz 21f3d14277 feat: enable automated script updates directly from the Gitea repository
Main / build (push) Waiting to run
2026-07-08 01:56:59 +08:00
svefnz 81206be8a4 feat: automate HAProxy cleanup and Caddy restore during sing-box uninstallation
Main / build (push) Waiting to run
2026-07-08 01:55:33 +08:00
svefnz 3f383af8d4 feat: automate HAProxy L4 SNI routing for Caddy and VLESS-REALITY co-existence on port 443
Main / build (push) Waiting to run
2026-07-08 01:53:59 +08:00
svefnz c573968dfc fix: relocate fallback configuration block to root level of inbound object
Main / build (push) Waiting to run
2026-07-08 01:46:06 +08:00
svefnz 585cb5e09d feat: decouple reality handshake destination from fallback destination to support external SNIs on 443
Main / build (push) Waiting to run
2026-07-08 01:37:42 +08:00
svefnz 1446138557 feat: force using Caddy domain as SNI when REALITY fallback is enabled
Main / build (push) Waiting to run
2026-07-08 01:25:56 +08:00
svefnz e37c61d437 fix: replace recursive ask call with direct read to fix variable scope pollution
Main / build (push) Waiting to run
2026-07-08 01:10:20 +08:00
svefnz fcdeee1249 feat: prompt for Caddy fallback on port 443 regardless of port occupancy status
Main / build (push) Waiting to run
2026-07-08 01:04:46 +08:00
svefnz 5309bf254b fix: update existing https_port in Caddyfile instead of appending a duplicate key
Main / build (push) Waiting to run
2026-07-08 00:57:36 +08:00
svefnz 88f9422f01 feat: automatically adjust Caddyfile and restart Caddy when enabling REALITY fallback on 443
Main / build (push) Waiting to run
2026-07-08 00:56:35 +08:00
svefnz b0aa99f394 fix: ensure config.json is generated if it does not exist when saving a new configuration
Main / build (push) Waiting to run
2026-07-08 00:52:58 +08:00
svefnz 1f62620be3 fix: correct protocol variable check inside port validation to support interactive menu
Main / build (push) Waiting to run
2026-07-08 00:51:08 +08:00
svefnz 7549097b3f feat: support Caddy fallback routing for VLESS-REALITY on port 443
Main / build (push) Waiting to run
2026-07-08 00:46:24 +08:00
svefnz 2347e16958 refactor: remove all remaining feedback prompts and issue references
Main / build (push) Waiting to run
2026-07-08 00:14:56 +08:00
svefnz 2f7153b058 feat: disable automatic reality config generation on install 2026-07-08 00:13:47 +08:00
svefnz bb682d3f63 fix: update online installation source URL to Gitea
Main / build (push) Waiting to run
2026-07-08 00:05:48 +08:00
svefnz a3e048b949 fix: reuse existing Caddy binary and preserve Caddyfile on install
Main / build (push) Waiting to run
2026-07-07 23:47:56 +08:00
svefnz 906ee96282 docs: add one-key installation commands to README.md
Main / build (push) Waiting to run
2026-07-07 23:39:22 +08:00
svefnz 576209e0cc refactor: remove promotional content, ads, and author branding for a clean project
Main / build (push) Waiting to run
2026-07-07 23:35:32 +08:00
233boy 2d78583b5a fix test run 2026-06-04 14:27:04 +08:00
233boy 4376b9a907 fix hy2 tls* 2026-06-02 15:43:27 +08:00
233boy fc79047a2e Merge pull request #134 from Jah-yee/main
fix: correct typo 'atuo' → 'auto' in src/help.sh line 35
2026-05-26 21:35:50 +08:00
Jah-yee a075e3e1dc fix: correct typo 'atuo' → 'auto' in src/help.sh line 35 2026-05-23 12:19:43 +08:00
233boy 3cc47489a2 Merge pull request #121 from fr0der1c/anytls
feat: add AnyTLS protocol support
2026-04-14 22:26:49 +08:00
frederic b1c634a0cc feat: add AnyTLS protocol support
- Add AnyTLS to protocol list and README
- Support self-signed TLS (default) and ACME auto-cert with domain
- Auto-detect sing-box version: use certificate_provider (>= 1.14.0)
  or tls.acme (older versions)
- Usage: sing-box add anytls [port] [password] [domain]
- Generate anytls:// share links
- Handle config read-back for change/info operations

Co-Authored-By: Oz <oz-agent@warp.dev>
2026-04-14 21:57:43 +08:00
233boy 2b970915ee Merge pull request #119 from rowanchen-com/main
fix: force full package install on Alpine and wait for service start
2026-03-21 21:08:07 +08:00
rowanchen-com 2199ef62ce fix: force install full wget on Alpine to replace BusyBox version 2026-03-21 18:21:39 +08:00
rowanchen-com 4b18389b35 fix: wait for background tasks before exit to prevent output overlap 2026-03-21 18:14:18 +08:00
233boy 7effde1e08 Merge pull request #118 from rowanchen-com/main
fix: avoid apk lock conflict on Alpine
2026-03-21 18:08:54 +08:00
8 changed files with 437 additions and 139 deletions
+18 -38
View File
@@ -1,55 +1,36 @@
# 介绍 # sing-box 一键安装及管理脚本
最好用的 sing-box 一键安装脚本 & 管理脚本 这是一个用于快速部署 and 管理 sing-box 一键脚本
# 特点 ## 特点
- 快速安装 - 快速安装
- 无敌好用
- 零学习成本 - 零学习成本
- 自动化 TLS - 自动化 TLS
- 简化所有流程
- 兼容 sing-box 命令 - 兼容 sing-box 命令
- 强大的快捷参数 - 强大的快捷参数
- 支持所有常用协议 - 支持所有常用协议VLESS-REALITY, TUIC, Trojan, Hysteria2, Shadowsocks, VMess 等)
- 一键添加 VLESS-REALITY (默认)
- 一键添加 TUIC
- 一键添加 Trojan
- 一键添加 Hysteria2
- 一键添加 Shadowsocks 2022
- 一键添加 VMess-(TCP/HTTP/QUIC)
- 一键添加 VMess-(WS/H2/HTTPUpgrade)-TLS
- 一键添加 VLESS-(WS/H2/HTTPUpgrade)-TLS
- 一键添加 Trojan-(WS/H2/HTTPUpgrade)-TLS
- 一键启用 BBR - 一键启用 BBR
- 一键更改伪装网站
- 一键更改 (端口/UUID/密码/域名/路径/加密方式/SNI/等...)
- 还有更多...
# 设计理念 ## 安装命令
设计理念为:**高效率,超快速,极易用** 系统支持:Ubuntu / Debian / CentOS / Alpine / SUSE (仅限 64 位系统,需以 ROOT 用户运行)。
脚本基于作者的自身使用需求,以 **多配置同时运行** 为核心设计 一键安装及管理命令:
```bash
bash <(wget -qO- https://git.lll.rest/svefnz/sing-box/raw/branch/main/install.sh)
```
或者使用 `curl`
```bash
bash <(curl -fsSL https://git.lll.rest/svefnz/sing-box/raw/branch/main/install.sh)
```
并且专门优化了,添加、更改、查看、删除、这四项常用功能 ## 帮助信息
你只需要一条命令即可完成 添加、更改、查看、删除、等操作
例如,添加一个配置仅需不到 1 秒!瞬间完成添加!其他操作亦是如此!
脚本的参数非常高效率并且超级易用,请掌握参数的使用
# 文档
安装及使用:https://233boy.com/sing-box/sing-box-script/
# 帮助
使用:`sing-box help` 使用:`sing-box help`
``` ```
sing-box script v1.0 by 233boy sing-box script v1.0
Usage: sing-box [options]... [args]... Usage: sing-box [options]... [args]...
基本: 基本:
@@ -67,6 +48,7 @@ Usage: sing-box [options]... [args]...
qr [name] 二维码信息 qr [name] 二维码信息
url [name] URL 信息 url [name] URL 信息
log 查看日志 log 查看日志
更改: 更改:
full [name] [...] 更改多个参数 full [name] [...] 更改多个参数
id [name] [uuid | auto] 更改 UUID id [name] [uuid | auto] 更改 UUID
@@ -74,7 +56,7 @@ Usage: sing-box [options]... [args]...
port [name] [port | auto] 更改端口 port [name] [port | auto] 更改端口
path [name] [path | auto] 更改路径 path [name] [path | auto] 更改路径
passwd [name] [password | auto] 更改密码 passwd [name] [password | auto] 更改密码
key [name] [Private key | atuo] [Public key] 更改密钥 key [name] [Private key | auto] [Public key] 更改密钥
method [name] [method | auto] 更改加密方式 method [name] [method | auto] 更改加密方式
sni [name] [ ip | domain] 更改 serverName sni [name] [ ip | domain] 更改 serverName
new [name] [...] 更改协议 new [name] [...] 更改协议
@@ -109,6 +91,4 @@ Usage: sing-box [options]... [args]...
h, help 显示此帮助界面 h, help 显示此帮助界面
谨慎使用 del, ddel, 此选项会直接删除配置; 无需确认 谨慎使用 del, ddel, 此选项会直接删除配置; 无需确认
反馈问题) https://github.com/233boy/sing-box/issues
文档(doc) https://233boy.com/sing-box/sing-box-script/
``` ```
+16 -10
View File
@@ -1,7 +1,6 @@
#!/bin/bash #!/bin/bash
author=233boy author=sb
# github=https://github.com/233boy/sing-box
# bash fonts colors # bash fonts colors
red='\e[31m' red='\e[31m'
@@ -177,7 +176,7 @@ download() {
is_ok=$is_core_ok is_ok=$is_core_ok
;; ;;
sh) sh)
link=https://github.com/${is_sh_repo}/releases/latest/download/code.tar.gz link=https://git.lll.rest/svefnz/sing-box/archive/main.tar.gz
name="$is_core_name 脚本" name="$is_core_name 脚本"
tmpfile=$tmpsh tmpfile=$tmpsh
is_ok=$is_sh_ok is_ok=$is_sh_ok
@@ -303,7 +302,6 @@ exit_and_del_tmpdir() {
[[ ! $1 ]] && { [[ ! $1 ]] && {
msg err "哦豁.." msg err "哦豁.."
msg err "安装过程出现错误..." msg err "安装过程出现错误..."
echo -e "反馈问题) https://github.com/${is_sh_repo}/issues"
echo echo
exit 1 exit 1
} }
@@ -324,7 +322,7 @@ main() {
# show welcome msg # show welcome msg
clear clear
echo echo
echo "........... $is_core_name script by $author .........." echo "........... $is_core_name script .........."
echo echo
# start installing... # start installing...
@@ -353,7 +351,10 @@ main() {
# install dependent pkg # install dependent pkg
if [[ $cmd =~ apk ]]; then if [[ $cmd =~ apk ]]; then
install_pkg $is_pkg # Alpine: force install full versions to replace BusyBox applets
apk update &>/dev/null
apk add $is_pkg &>/dev/null
[[ $? == 0 ]] && >$is_pkg_ok
else else
install_pkg $is_pkg & install_pkg $is_pkg &
fi fi
@@ -405,7 +406,7 @@ main() {
if [[ $local_install ]]; then if [[ $local_install ]]; then
cp -rf $PWD/* $is_sh_dir cp -rf $PWD/* $is_sh_dir
else else
tar zxf $is_sh_ok -C $is_sh_dir tar zxf $is_sh_ok --strip-components 1 -C $is_sh_dir
fi fi
# create core bin dir # create core bin dir
@@ -435,7 +436,7 @@ main() {
mkdir -p $is_log_dir mkdir -p $is_log_dir
# show a tips msg # show a tips msg
msg ok "生成配置文件..." msg ok "初始化配置目录..."
# create service # create service
load systemd.sh load systemd.sh
@@ -446,8 +447,13 @@ main() {
mkdir -p $is_conf_dir mkdir -p $is_conf_dir
load core.sh load core.sh
# create a reality config # wait for background tasks (e.g., OpenRC service start)
add reality wait
_green "\nsing-box 脚本安装成功!\n"
msg "你可以输入 ${green}sing-box${none} 或者 ${green}sb${none} 快捷命令来打开管理菜单配置你的节点。"
echo
# remove tmp dir and exit. # remove tmp dir and exit.
exit_and_del_tmpdir ok exit_and_del_tmpdir ok
} }
+1 -1
View File
@@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
args=$@ args=$@
is_sh_ver=v1.15 is_sh_ver=v1.18
. /etc/sing-box/sh/src/init.sh . /etc/sing-box/sh/src/init.sh
+9 -7
View File
@@ -3,12 +3,13 @@ caddy_config() {
case $1 in case $1 in
new) new)
mkdir -p $is_caddy_dir $is_caddy_dir/sites $is_caddy_conf mkdir -p $is_caddy_dir $is_caddy_dir/sites $is_caddy_conf
cat >$is_caddyfile <<-EOF if [[ -f $is_caddyfile ]]; then
# don't edit this file # [[ ! $(grep -F "$is_caddy_conf/*.conf" $is_caddyfile) ]] && {
# for more info, see https://233boy.com/$is_core/caddy-auto-tls/ echo -e "\nimport $is_caddy_conf/*.conf" >>$is_caddyfile
# 不要编辑这个文件 # }
# 更多相关请阅读此文章: https://233boy.com/$is_core/caddy-auto-tls/ else
# https://caddyserver.com/docs/caddyfile/options cat >$is_caddyfile <<-EOF
# caddy configuration #
{ {
admin off admin off
http_port $is_http_port http_port $is_http_port
@@ -17,6 +18,7 @@ caddy_config() {
import $is_caddy_conf/*.conf import $is_caddy_conf/*.conf
import $is_caddy_dir/sites/*.conf import $is_caddy_dir/sites/*.conf
EOF EOF
fi
;; ;;
*ws* | *http*) *ws* | *http*)
cat >${is_caddy_site_file} <<<" cat >${is_caddy_site_file} <<<"
@@ -52,6 +54,6 @@ reverse_proxy https://$proxy_site {
;; ;;
esac esac
[[ $1 != "new" && $1 != 'proxy' ]] && { [[ $1 != "new" && $1 != 'proxy' ]] && {
[[ ! -f ${is_caddy_site_file}.add ]] && echo "# see https://233boy.com/$is_core/caddy-auto-tls/" >${is_caddy_site_file}.add [[ ! -f ${is_caddy_site_file}.add ]] && echo "# caddy site configuration" >${is_caddy_site_file}.add
} }
} }
+382 -60
View File
@@ -20,6 +20,7 @@ protocol_list=(
Trojan-HTTPUpgrade-TLS Trojan-HTTPUpgrade-TLS
VLESS-REALITY VLESS-REALITY
VLESS-HTTP2-REALITY VLESS-HTTP2-REALITY
AnyTLS
# Direct # Direct
Socks Socks
) )
@@ -42,7 +43,6 @@ mainmenu=(
"卸载" "卸载"
"帮助" "帮助"
"其他" "其他"
"关于"
) )
info_list=( info_list=(
"协议 (protocol)" "协议 (protocol)"
@@ -150,6 +150,151 @@ get_port() {
done done
} }
update_caddyfile_fallback() {
[[ ! -f $is_caddyfile ]] && return
# Backup Caddyfile
cp -f $is_caddyfile ${is_caddyfile}.bak
# 1. Replace servers :443 with servers :4443
sed -i 's/servers :443/servers :4443/g' $is_caddyfile
# 2. Replace any site block headers explicit :443 with :4443
sed -i 's/:443\b/:4443/g' $is_caddyfile
# 3. Add or update https_port 4443 globally
if grep -q "https_port" $is_caddyfile; then
# Replace existing https_port with 4443
sed -i 's/https_port[[:space:]]\+[0-9]\+/https_port 4443/g' $is_caddyfile
elif grep -q '^[[:space:]]*{[[:space:]]*$' $is_caddyfile; then
# Insert inside existing global block
sed -i '0,/^[[:space:]]*{[[:space:]]*$/s//{\n https_port 4443/' $is_caddyfile
else
# Prepend a new global block at the very top of the Caddyfile
echo -e "{\n https_port 4443\n}\n$(cat $is_caddyfile)" >$is_caddyfile
fi
# 4. Replace any explicit :443 in other conf files inside /etc/caddy/sing-box/
if [[ -d /etc/caddy/sing-box ]]; then
sed -i 's/:443\b/:4443/g' /etc/caddy/sing-box/*.conf 2>/dev/null
fi
}
install_haproxy() {
[[ $(type -P haproxy) ]] && return
msg "正在安装 HAProxy 用于四层端口分流..."
if [[ $(type -P apt-get) ]]; then
apt-get update && apt-get install -y haproxy
elif [[ $(type -P dnf) ]]; then
dnf install -y haproxy
elif [[ $(type -P yum) ]]; then
yum install -y haproxy
else
err "未知的软件包管理器,请手动安装 haproxy!"
fi
}
restore_caddy_default() {
[[ ! -f $is_caddyfile ]] && return
if [[ -f ${is_caddyfile}.bak ]]; then
mv -f ${is_caddyfile}.bak $is_caddyfile
else
sed -i 's/servers :4443/servers :443/g' $is_caddyfile
sed -i 's/:4443[[:space:]]*{/:443 {/g' $is_caddyfile
sed -i 's/https_port 4443/https_port 443/g' $is_caddyfile
fi
# Restore explicit :4443 in other conf files inside /etc/caddy/sing-box/
if [[ -d /etc/caddy/sing-box ]]; then
sed -i 's/:4443\b/:443/g' /etc/caddy/sing-box/*.conf 2>/dev/null
fi
systemctl restart caddy >/dev/null 2>&1
}
update_haproxy_config() {
[[ ! -d $is_conf_dir ]] && return
local haproxy_conf="/etc/haproxy/haproxy.cfg"
[[ ! -d /etc/haproxy ]] && mkdir -p /etc/haproxy
[[ -f $haproxy_conf ]] && cp -f $haproxy_conf ${haproxy_conf}.bak
cat >$haproxy_conf <<'EOF'
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
user haproxy
group haproxy
daemon
defaults
log global
mode tcp
timeout connect 5s
timeout client 50s
timeout server 50s
frontend https-in
bind *:443
mode tcp
tcp-request inspect-delay 5s
tcp-request content accept if { req_ssl_hello_type 1 }
EOF
local acl_rules=""
local use_backend_rules=""
local backends=""
local has_reality=0
for config in $is_conf_dir/*.json; do
[[ ! -f $config ]] && continue
local json_clean=$(cat "$config" | sed s#//.*##)
local is_real=$(jq -r '.inbounds[0].tls.reality.enabled // empty' <<<"$json_clean")
[[ $is_real != "true" ]] && continue
local local_port=$(jq -r '.inbounds[0].listen_port // empty' <<<"$json_clean")
local sni=$(jq -r '.inbounds[0].tls.server_name // empty' <<<"$json_clean")
[[ ! $local_port || ! $sni ]] && continue
[[ $local_port == "443" ]] && continue
has_reality=1
local backend_name="singbox_backend_${local_port}"
acl_rules="${acl_rules}\n acl is_reality_${local_port} req.ssl_sni -i ${sni}"
use_backend_rules="${use_backend_rules}\n use_backend ${backend_name} if is_reality_${local_port}"
backends="${backends}\n\nbackend ${backend_name}\n mode tcp\n server srv1 127.0.0.1:${local_port}"
done
if [[ $has_reality -eq 1 ]]; then
echo -e "$acl_rules" >>$haproxy_conf
echo -e "$use_backend_rules" >>$haproxy_conf
echo -e " default_backend caddy_backend" >>$haproxy_conf
cat >>$haproxy_conf <<'EOF'
backend caddy_backend
mode tcp
server caddy 127.0.0.1:4443
EOF
echo -e "$backends" >>$haproxy_conf
systemctl daemon-reload
systemctl enable haproxy >/dev/null 2>&1
systemctl restart haproxy >/dev/null 2>&1
else
if systemctl is-active --quiet haproxy; then
systemctl stop haproxy >/dev/null 2>&1
systemctl disable haproxy >/dev/null 2>&1
fi
restore_caddy_default
fi
}
get_pbk() { get_pbk() {
is_tmp_pbk=($($is_core_bin generate reality-keypair | sed 's/.*://')) is_tmp_pbk=($($is_core_bin generate reality-keypair | sed 's/.*://'))
is_public_key=${is_tmp_pbk[1]} is_public_key=${is_tmp_pbk[1]}
@@ -227,7 +372,7 @@ ask() {
[[ $is_no_auto_tls ]] && { [[ $is_no_auto_tls ]] && {
unset is_tmp_list unset is_tmp_list
for v in ${protocol_list[@]}; do for v in ${protocol_list[@]}; do
[[ $(grep -i tls$ <<<$v) ]] && is_tmp_list=(${is_tmp_list[@]} $v) [[ $(grep -i "\-tls$" <<<$v) ]] && is_tmp_list=(${is_tmp_list[@]} $v)
done done
} }
is_opt_msg="\n请选择协议:\n" is_opt_msg="\n请选择协议:\n"
@@ -280,6 +425,18 @@ ask() {
msg "$is_err 请输入正确的端口, 可选(1-65535)" msg "$is_err 请输入正确的端口, 可选(1-65535)"
continue continue
} }
if [[ $REPLY == 443 && $is_caddy && ${is_new_protocol,,} =~ "reality" ]]; then
msg "\n检测到你的系统已启用 Caddy。"
msg "你可以选择启用 REALITY 回落分流功能,将非代理流量转发给本地 Caddy。"
msg "这会自动安装 HAProxy 监听 443 端口进行四层分流,并将 Caddy 的 https 端口自动调整为 4443。"
echo -ne "是否启用 Caddy 回落分流?(y/n):"
read is_enable_fallback
if [[ $is_enable_fallback =~ ^[Yy]$ ]]; then
is_reality_fallback=1
export $is_ask_set=$REPLY
break
fi
fi
if [[ $(is_test port_used $REPLY) && $is_ask_set != 'door_port' ]]; then if [[ $(is_test port_used $REPLY) && $is_ask_set != 'door_port' ]]; then
msg "$is_err 无法使用 ($REPLY) 端口." msg "$is_err 无法使用 ($REPLY) 端口."
continue continue
@@ -323,6 +480,8 @@ create() {
if [[ $host ]]; then if [[ $host ]]; then
is_config_name=$2-${host}.json is_config_name=$2-${host}.json
is_listen='listen: "127.0.0.1"' is_listen='listen: "127.0.0.1"'
elif [[ $is_anytls_domain ]]; then
is_config_name=$2-${is_anytls_domain}.json
else else
is_config_name=$2-${port}.json is_config_name=$2-${port}.json
fi fi
@@ -330,7 +489,12 @@ create() {
# get json # get json
[[ $is_change || ! $json_str ]] && get protocol $2 [[ $is_change || ! $json_str ]] && get protocol $2
[[ $net == "reality" ]] && is_add_public_key=",outbounds:[{type:\"direct\"},{tag:\"public_key_$is_public_key\",type:\"direct\"}]" [[ $net == "reality" ]] && is_add_public_key=",outbounds:[{type:\"direct\"},{tag:\"public_key_$is_public_key\",type:\"direct\"}]"
is_new_json=$(jq "{inbounds:[{tag:\"$is_config_name\",type:\"$is_protocol\",$is_listen,listen_port:$port,$json_str}]$is_add_public_key}" <<<{}) local write_port=$port
if [[ $is_reality_fallback ]]; then
get_port
write_port=$tmp_port
fi
is_new_json=$(jq "{inbounds:[{tag:\"$is_config_name\",type:\"$is_protocol\",$is_listen,listen_port:$write_port,$json_str}]$is_add_public_key}" <<<{})
[[ $is_test_json ]] && return # tmp test [[ $is_test_json ]] && return # tmp test
# only show json, dont save to file. # only show json, dont save to file.
[[ $is_gen ]] && { [[ $is_gen ]] && {
@@ -339,14 +503,58 @@ create() {
msg msg
return return
} }
# Read old remarks before file deletion
local old_remarks=""
if [[ -f $is_json_file ]]; then
old_remarks=$(grep -E '^[[:space:]]*//[[:space:]]*remarks:' $is_json_file | sed 's/.*remarks:[[:space:]]*//')
elif [[ $is_config_file && -f $is_conf_dir/$is_config_file ]]; then
old_remarks=$(grep -E '^[[:space:]]*//[[:space:]]*remarks:' $is_conf_dir/$is_config_file | sed 's/.*remarks:[[:space:]]*//')
fi
local is_remarks=""
if [[ ! $is_gen ]]; then
if [[ $is_change ]]; then
if [[ $old_remarks ]]; then
msg "\n当前节点备注名称为: $old_remarks"
fi
echo -ne "请输入新的节点备注名称 (回车保持不变,输入 clear 确认清除):"
read is_remarks
if [[ -z $is_remarks ]]; then
is_remarks=$old_remarks
elif [[ $is_remarks == "clear" ]]; then
is_remarks=""
fi
else
msg "\n你可以为该节点设置一个自定义备注名称(用于生成的链接末尾显示)。"
echo -ne "请输入节点备注名称 (直接回车将使用默认生成值):"
read is_remarks
fi
fi
# del old file # del old file
[[ $is_config_file ]] && is_no_del_msg=1 && del $is_config_file [[ $is_config_file ]] && is_no_del_msg=1 && del $is_config_file
# save json to file # save json to file
cat <<<$is_new_json >$is_json_file if [[ $is_remarks ]]; then
if [[ $is_new_install ]]; then echo "// remarks: $is_remarks" >$is_json_file
echo "$is_new_json" >>$is_json_file
else
echo "$is_new_json" >$is_json_file
fi
if [[ ! -f $is_config_json ]]; then
# config.json # config.json
create config.json create config.json
fi fi
# If reality fallback is enabled, automatically update Caddyfile!
if [[ $is_reality_fallback ]]; then
msg "\n自动调整 Caddy 配置文件以支持 4443 端口回落..."
update_caddyfile_fallback
msg "Caddy 配置文件更新成功,备份已保存至 ${is_caddyfile}.bak"
msg "正在重启 Caddy 以释放 443 端口..."
manage restart caddy &>/dev/null
sleep 1
install_haproxy
update_haproxy_config
fi
# caddy auto tls # caddy auto tls
[[ $is_caddy && $host && ! $is_no_auto_tls ]] && { [[ $is_caddy && $host && ! $is_no_auto_tls ]] && {
create caddy $net create caddy $net
@@ -615,9 +823,6 @@ change() {
[[ $is_auto ]] && is_new_servername=$is_random_servername [[ $is_auto ]] && is_new_servername=$is_random_servername
[[ ! $is_new_servername ]] && ask string is_new_servername "请输入新的 serverName:" [[ ! $is_new_servername ]] && ask string is_new_servername "请输入新的 serverName:"
is_servername=$is_new_servername is_servername=$is_new_servername
[[ $(grep -i "^233boy.com$" <<<$is_servername) ]] && {
err "你干嘛~哎呦~"
}
add $net add $net
;; ;;
11) 11)
@@ -629,13 +834,9 @@ change() {
[[ ! -f $is_caddy_conf/${host}.conf.add ]] && err "无法配置伪装网站." [[ ! -f $is_caddy_conf/${host}.conf.add ]] && err "无法配置伪装网站."
[[ ! $is_new_proxy_site ]] && ask string is_new_proxy_site "请输入新的伪装网站 (例如 example.com):" [[ ! $is_new_proxy_site ]] && ask string is_new_proxy_site "请输入新的伪装网站 (例如 example.com):"
proxy_site=$(sed 's#^.*//##;s#/$##' <<<$is_new_proxy_site) proxy_site=$(sed 's#^.*//##;s#/$##' <<<$is_new_proxy_site)
[[ $(grep -i "^233boy.com$" <<<$proxy_site) ]] && { load caddy.sh
err "你干嘛~哎呦~" caddy_config proxy
} || { manage restart caddy &
load caddy.sh
caddy_config proxy
manage restart caddy &
}
msg "\n已更新伪装网站为: $(_green $proxy_site) \n" msg "\n已更新伪装网站为: $(_green $proxy_site) \n"
;; ;;
12) 12)
@@ -660,6 +861,7 @@ del() {
pause pause
fi fi
rm -rf $is_conf_dir/"$is_config_file" rm -rf $is_conf_dir/"$is_config_file"
update_haproxy_config
[[ ! $is_new_json ]] && manage restart & [[ ! $is_new_json ]] && manage restart &
[[ ! $is_no_del_msg ]] && _green "\n已删除: $is_config_file\n" [[ ! $is_no_del_msg ]] && _green "\n已删除: $is_config_file\n"
@@ -691,6 +893,24 @@ uninstall() {
else else
ask string y "是否卸载 ${is_core_name}? [y]:" ask string y "是否卸载 ${is_core_name}? [y]:"
fi fi
# Clean up HAProxy and restore Caddy before removing files
if systemctl is-active --quiet haproxy >/dev/null 2>&1; then
systemctl stop haproxy >/dev/null 2>&1
systemctl disable haproxy >/dev/null 2>&1
if [[ $(type -P apt-get) ]]; then
apt-get purge -y haproxy >/dev/null 2>&1
apt-get autoremove -y >/dev/null 2>&1
elif [[ $(type -P dnf) ]]; then
dnf remove -y haproxy >/dev/null 2>&1
elif [[ $(type -P yum) ]]; then
yum remove -y haproxy >/dev/null 2>&1
fi
fi
# If Caddy is NOT being uninstalled (REPLY != '2'), we must restore Caddy back to port 443!
if [[ $REPLY != '2' ]]; then
restore_caddy_default
fi
manage stop &>/dev/null manage stop &>/dev/null
manage disable &>/dev/null manage disable &>/dev/null
rm -rf $is_core_dir $is_log_dir $is_sh_bin ${is_sh_bin/$is_core/sb} rm -rf $is_core_dir $is_log_dir $is_sh_bin ${is_sh_bin/$is_core/sb}
@@ -711,9 +931,7 @@ uninstall() {
fi fi
fi fi
[[ $is_install_sh ]] && return # reinstall [[ $is_install_sh ]] && return # reinstall
_green "\n卸载完成!" _green "\n卸载完成!\n"
msg "脚本哪里需要完善? 请反馈"
msg "反馈问题) $(msg_ul https://github.com/${is_sh_repo}/issues)\n"
} }
# manage run status # manage run status
@@ -768,7 +986,7 @@ manage() {
fi fi
[[ $is_test_run && ! $is_new_install ]] && { [[ $is_test_run && ! $is_new_install ]] && {
sleep 2 sleep 2
if [[ ! $(pgrep -f $is_run_bin 2>/dev/null || grep -l "$is_run_bin" /proc/*/cmdline 2>/dev/null) ]]; then if [[ ! $(pgrep -f $is_run_bin) ]]; then
is_run_fail=${is_do_name_msg,,} is_run_fail=${is_do_name_msg,,}
[[ ! $is_no_manage_msg ]] && { [[ ! $is_no_manage_msg ]] && {
msg msg
@@ -813,6 +1031,9 @@ add() {
trojan) trojan)
is_new_protocol=Trojan is_new_protocol=Trojan
;; ;;
anytls)
is_new_protocol=AnyTLS
;;
socks) socks)
is_new_protocol=Socks is_new_protocol=Socks
;; ;;
@@ -829,6 +1050,14 @@ add() {
# no prefer protocol # no prefer protocol
[[ ! $is_new_protocol ]] && ask set_protocol [[ ! $is_new_protocol ]] && ask set_protocol
if [[ ${is_new_protocol,,} == 'anytls' ]]; then
is_core_major=$(echo "$is_core_ver" | cut -d. -f1)
is_core_minor=$(echo "$is_core_ver" | cut -d. -f2)
if [[ ${is_core_major:-0} -lt 1 || ${is_core_major:-0} -eq 1 && ${is_core_minor:-0} -lt 12 ]]; then
err "当前 sing-box 版本 ($is_core_ver) 不支持 AnyTLS,请先升级 sing-box core 到 1.12.0 或更高版本。"
fi
fi
case ${is_new_protocol,,} in case ${is_new_protocol,,} in
*-tls) *-tls)
is_use_tls=1 is_use_tls=1
@@ -866,6 +1095,12 @@ add() {
is_use_door_port=$4 is_use_door_port=$4
is_add_opts="[port] [remote_addr] [remote_port]" is_add_opts="[port] [remote_addr] [remote_port]"
;; ;;
anytls*)
is_use_port=$2
is_use_pass=$3
[[ $4 ]] && is_anytls_domain=$4
is_add_opts="[port] [password] [domain]"
;;
socks) socks)
is_socks=1 is_socks=1
is_use_port=$2 is_use_port=$2
@@ -915,7 +1150,17 @@ add() {
[[ ! $(is_test port ${is_use_port}) ]] && { [[ ! $(is_test port ${is_use_port}) ]] && {
err "($is_use_port) 不是一个有效的端口. $is_err_tips" err "($is_use_port) 不是一个有效的端口. $is_err_tips"
} }
[[ $(is_test port_used $is_use_port) && ! $is_gen ]] && { if [[ $is_use_port == 443 && $is_caddy && ${is_new_protocol,,} =~ "reality" ]]; then
msg "\n检测到你的系统已启用 Caddy。"
msg "你可以选择启用 REALITY 回落分流功能,将非代理流量转发给本地 Caddy。"
msg "这会自动安装 HAProxy 监听 443 端口进行四层分流,并将 Caddy 的 https 端口自动调整为 4443。"
echo -ne "是否启用 Caddy 回落分流?(y/n):"
read is_enable_fallback
if [[ $is_enable_fallback =~ ^[Yy]$ ]]; then
is_reality_fallback=1
fi
fi
[[ $(is_test port_used $is_use_port) && ! $is_gen && ! $is_reality_fallback ]] && {
err "无法使用 ($is_use_port) 端口. $is_err_tips" err "无法使用 ($is_use_port) 端口. $is_err_tips"
} }
port=$is_use_port port=$is_use_port
@@ -963,6 +1208,14 @@ add() {
[[ $is_use_socks_pass ]] && is_socks_pass=$is_use_socks_pass [[ $is_use_socks_pass ]] && is_socks_pass=$is_use_socks_pass
fi fi
# anytls with domain (ACME TLS)
if [[ $is_anytls_domain && ! $is_change && ! $is_gen ]]; then
get_ip
host=$is_anytls_domain
get host-test
host=
fi
if [[ $is_use_tls ]]; then if [[ $is_use_tls ]]; then
if [[ ! $is_no_auto_tls && ! $is_caddy && ! $is_gen && ! $is_dont_test_host ]]; then if [[ ! $is_no_auto_tls && ! $is_caddy && ! $is_gen && ! $is_dont_test_host ]]; then
# test auto tls # test auto tls
@@ -972,7 +1225,6 @@ add() {
get_port get_port
is_https_port=$tmp_port is_https_port=$tmp_port
warn "端口 (80 或 443) 已经被占用, 你也可以考虑使用 no-auto-tls" warn "端口 (80 或 443) 已经被占用, 你也可以考虑使用 no-auto-tls"
msg "\e[41m no-auto-tls 帮助(help)\e[0m: $(msg_ul https://233boy.com/$is_core/no-auto-tls/)\n"
msg "\n Caddy 将使用非标准端口实现自动配置 TLS, HTTP:$is_http_port HTTPS:$is_https_port\n" msg "\n Caddy 将使用非标准端口实现自动配置 TLS, HTTP:$is_http_port HTTPS:$is_https_port\n"
msg "请确定是否继续???" msg "请确定是否继续???"
pause pause
@@ -1083,9 +1335,9 @@ get() {
get file $2 get file $2
if [[ $is_config_file ]]; then if [[ $is_config_file ]]; then
is_json_str=$(cat $is_conf_dir/"$is_config_file" | sed s#//.*##) is_json_str=$(cat $is_conf_dir/"$is_config_file" | sed s#//.*##)
is_json_data=$(jq '(.inbounds[0]|.type,.listen_port,(.users[0]|.uuid,.password,.username),.method,.password,.override_port,.override_address,(.transport|.type,.path,.headers.host),(.tls|.server_name,.reality.private_key)),(.outbounds[1].tag)' <<<$is_json_str) is_json_data=$(jq '(.inbounds[0]|.type,.listen_port,(.users[0]|.uuid,.password,.username),.method,.password,.override_port,.override_address,(.transport|.type,.path,.headers.host),(.tls|.server_name,.reality.private_key),.fallback.server_port),(.outbounds[1].tag)' <<<$is_json_str)
[[ $? != 0 ]] && err "无法读取此文件: $is_config_file" [[ $? != 0 ]] && err "无法读取此文件: $is_config_file"
is_up_var_set=(null is_protocol port uuid password username ss_method ss_password door_port door_addr net_type path host is_servername is_private_key is_public_key) is_up_var_set=(null is_protocol port uuid password username ss_method ss_password door_port door_addr net_type path host is_servername is_private_key is_reality_fallback_port is_public_key)
[[ $is_debug ]] && msg "\n------------- debug: $is_config_file -------------" [[ $is_debug ]] && msg "\n------------- debug: $is_config_file -------------"
i=0 i=0
for v in $(sed 's/""/null/g;s/"//g' <<<"$is_json_data"); do for v in $(sed 's/""/null/g;s/"//g' <<<"$is_json_data"); do
@@ -1097,14 +1349,28 @@ get() {
[[ ${!v} == 'null' ]] && unset $v [[ ${!v} == 'null' ]] && unset $v
done done
# Override port if it's mapped behind HAProxy
local file_port=$(echo "$is_config_file" | grep -oE '[0-9]+\.json' | grep -oE '[0-9]+')
if [[ $file_port && $port && $port != $file_port ]]; then
port=$file_port
fi
if [[ $is_private_key ]]; then if [[ $is_private_key ]]; then
is_reality=1 is_reality=1
net_type+=reality net_type+=reality
is_public_key=${is_public_key/public_key_/} is_public_key=${is_public_key/public_key_/}
if [[ $is_reality_fallback_port == '4443' || $port == '443' ]]; then
is_reality_fallback=1
fi
fi fi
is_socks_user=$username is_socks_user=$username
is_socks_pass=$password is_socks_pass=$password
# extract anytls ACME domain
[[ $is_protocol == 'anytls' ]] && {
is_anytls_domain=$(jq -r '(.inbounds[0].tls.certificate_provider.domain[0] // .inbounds[0].tls.acme.domain[0]) // empty' <<<$is_json_str 2>/dev/null)
}
is_config_name=$is_config_file is_config_name=$is_config_file
if [[ $is_caddy && $host && -f $is_caddy_conf/$host.conf ]]; then if [[ $is_caddy && $host && -f $is_caddy_conf/$host.conf ]]; then
@@ -1169,10 +1435,28 @@ get() {
is_protocol=$net is_protocol=$net
json_str="override_port:$door_port,override_address:\"$door_addr\"" json_str="override_port:$door_port,override_address:\"$door_addr\""
;; ;;
anytls*)
net=anytls
is_protocol=$net
[[ ! $password ]] && password=$uuid
is_users="users:[{password:\"$password\"}]"
if [[ $is_anytls_domain ]]; then
# sing-box >= 1.14.0 uses certificate_provider; older uses acme
is_core_minor=$(echo "$is_core_ver" | cut -d. -f2)
if [[ ${is_core_minor:-0} -ge 14 ]]; then
is_anytls_tls="tls:{enabled:true,certificate_provider:{type:\"acme\",domain:[\"$is_anytls_domain\"]}}"
else
is_anytls_tls="tls:{enabled:true,acme:{domain:[\"$is_anytls_domain\"]}}"
fi
else
is_anytls_tls="${is_tls_json/alpn\:\[\"h3\"\],/}"
fi
json_str="$is_users,$is_anytls_tls"
;;
socks*) socks*)
net=socks net=socks
is_protocol=$net is_protocol=$net
[[ ! $is_socks_user ]] && is_socks_user=233boy [[ ! $is_socks_user ]] && is_socks_user=admin
[[ ! $is_socks_pass ]] && is_socks_pass=$uuid [[ ! $is_socks_pass ]] && is_socks_pass=$uuid
json_str="users:[{username: \"$is_socks_user\", password: \"$is_socks_pass\"}]" json_str="users:[{username: \"$is_socks_user\", password: \"$is_socks_pass\"}]"
;; ;;
@@ -1198,7 +1482,9 @@ get() {
net=reality net=reality
[[ ! $is_servername ]] && is_servername=$is_random_servername [[ ! $is_servername ]] && is_servername=$is_random_servername
[[ ! $is_private_key ]] && get_pbk [[ ! $is_private_key ]] && get_pbk
is_json_add="tls:{enabled:true,server_name:\"$is_servername\",reality:{enabled:true,handshake:{server:\"$is_servername\",server_port:443},private_key:\"$is_private_key\",short_id:[\"\"]}}" local handshake_server=$is_servername
local handshake_port=443
is_json_add="tls:{enabled:true,server_name:\"$is_servername\",reality:{enabled:true,handshake:{server:\"$handshake_server\",server_port:$handshake_port},private_key:\"$is_private_key\",short_id:[\"\"]}}"
[[ $is_lower =~ "http" ]] && { [[ $is_lower =~ "http" ]] && {
is_json_add="$is_json_add,transport:{type:\"http\"}" is_json_add="$is_json_add,transport:{type:\"http\"}"
} || { } || {
@@ -1251,13 +1537,18 @@ get() {
is_host_dns=$(_wget -qO- --header="accept: application/dns-json" "https://one.one.one.one/dns-query?name=$host&type=$is_dns_type") is_host_dns=$(_wget -qO- --header="accept: application/dns-json" "https://one.one.one.one/dns-query?name=$host&type=$is_dns_type")
;; ;;
install-caddy) install-caddy)
_green "\n安装 Caddy 实现自动配置 TLS.\n" if [[ -f $is_caddy_bin || $(type -P caddy) ]]; then
load download.sh [[ ! -f $is_caddy_bin ]] && is_caddy_bin=$(type -P caddy)
download caddy _green "\n检测到系统已安装 Caddy (${is_caddy_bin}),将直接使用现有版本。\n"
else
_green "\n安装 Caddy 实现自动配置 TLS.\n"
load download.sh
download caddy
fi
load systemd.sh load systemd.sh
install_service caddy &>/dev/null install_service caddy &>/dev/null
is_caddy=1 is_caddy=1
_green "安装 Caddy 成功.\n" _green "Caddy 配置成功.\n"
;; ;;
reinstall) reinstall)
is_install_sh=$(cat $is_sh_dir/install.sh) is_install_sh=$(cat $is_sh_dir/install.sh)
@@ -1273,7 +1564,7 @@ get() {
} }
fi fi
is_no_manage_msg=1 is_no_manage_msg=1
if [[ ! $(pgrep -f $is_core_bin 2>/dev/null || grep -l "$is_core_bin" /proc/*/cmdline 2>/dev/null) ]]; then if [[ ! $(pgrep -f $is_core_bin) ]]; then
_yellow "\n测试运行 $is_core_name ..\n" _yellow "\n测试运行 $is_core_name ..\n"
manage start &>/dev/null manage start &>/dev/null
if [[ $is_run_fail == $is_core ]]; then if [[ $is_run_fail == $is_core ]]; then
@@ -1286,7 +1577,7 @@ get() {
_green "\n$is_core_name 正在运行, 跳过测试\n" _green "\n$is_core_name 正在运行, 跳过测试\n"
fi fi
if [[ $is_caddy ]]; then if [[ $is_caddy ]]; then
if [[ ! $(pgrep -f $is_caddy_bin 2>/dev/null || grep -l "$is_caddy_bin" /proc/*/cmdline 2>/dev/null) ]]; then if [[ ! $(pgrep -f $is_caddy_bin) ]]; then
_yellow "\n测试运行 Caddy ..\n" _yellow "\n测试运行 Caddy ..\n"
manage start caddy &>/dev/null manage start caddy &>/dev/null
if [[ $is_run_fail == 'caddy' ]]; then if [[ $is_run_fail == 'caddy' ]]; then
@@ -1308,6 +1599,23 @@ info() {
if [[ ! $is_protocol ]]; then if [[ ! $is_protocol ]]; then
get info $1 get info $1
fi fi
local custom_remarks=""
if [[ $is_config_file ]]; then
custom_remarks=$(grep -E '^[[:space:]]*//[[:space:]]*remarks:' $is_conf_dir/"$is_config_file" | sed 's/.*remarks:[[:space:]]*//')
elif [[ -f $is_json_file ]]; then
custom_remarks=$(grep -E '^[[:space:]]*//[[:space:]]*remarks:' $is_json_file | sed 's/.*remarks:[[:space:]]*//')
fi
local url_remarks="sb-$net-$is_addr"
[[ $host ]] && url_remarks="sb-$net-$host"
[[ $is_anytls_domain ]] && url_remarks="sb-$net-$is_anytls_domain"
[[ $custom_remarks ]] && url_remarks=$custom_remarks
[[ $is_remarks ]] && url_remarks=$is_remarks
# If HAProxy is active, the public HTTPS port is 443 (routed to Caddy on 4443)
if systemctl is-active --quiet haproxy >/dev/null 2>&1; then
is_https_port=443
fi
# is_color=$(shuf -i 41-45 -n1) # is_color=$(shuf -i 41-45 -n1)
is_color=44 is_color=44
case $net in case $net in
@@ -1317,7 +1625,7 @@ info() {
is_can_change=(0 1 2 3 5) is_can_change=(0 1 2 3 5)
is_info_show=(0 1 2 3 4 6 7 8) is_info_show=(0 1 2 3 4 6 7 8)
[[ $is_protocol == 'vmess' ]] && { [[ $is_protocol == 'vmess' ]] && {
is_vmess_url=$(jq -c '{v:2,ps:'\"233boy-$net-$host\"',add:'\"$is_addr\"',port:'\"$is_https_port\"',id:'\"$uuid\"',aid:"0",net:'\"$net\"',host:'\"$host\"',path:'\"$path\"',tls:'\"tls\"'}' <<<{}) is_vmess_url=$(jq -c '{v:2,ps:'\"$url_remarks\"',add:'\"$is_addr\"',port:'\"$is_https_port\"',id:'\"$uuid\"',aid:"0",net:'\"$net\"',host:'\"$host\"',path:'\"$path\"',tls:'\"tls\"'}' <<<{})
is_url=vmess://$(echo -n $is_vmess_url | base64 -w 0) is_url=vmess://$(echo -n $is_vmess_url | base64 -w 0)
} || { } || {
[[ $is_protocol == "trojan" ]] && { [[ $is_protocol == "trojan" ]] && {
@@ -1326,7 +1634,7 @@ info() {
is_can_change=(0 1 2 3 4) is_can_change=(0 1 2 3 4)
is_info_show=(0 1 2 10 4 6 7 8) is_info_show=(0 1 2 10 4 6 7 8)
} }
is_url="$is_protocol://$uuid@$host:$is_https_port?encryption=none&security=tls&type=$net&host=$host&path=$path#233boy-$net-$host" is_url="$is_protocol://$uuid@$host:$is_https_port?encryption=none&security=tls&type=$net&host=$host&path=$path#$url_remarks"
} }
[[ $is_caddy ]] && is_can_change+=(11) [[ $is_caddy ]] && is_can_change+=(11)
is_info_str=($is_protocol $is_addr $is_https_port $uuid $net $host $path 'tls') is_info_str=($is_protocol $is_addr $is_https_port $uuid $net $host $path 'tls')
@@ -1348,34 +1656,36 @@ info() {
is_info_str+=(tls h3 true) is_info_str+=(tls h3 true)
is_quic_add=",tls:\"tls\",alpn:\"h3\"" # cant add allowInsecure is_quic_add=",tls:\"tls\",alpn:\"h3\"" # cant add allowInsecure
} }
is_vmess_url=$(jq -c "{v:2,ps:\"233boy-${net}-$is_addr\",add:\"$is_addr\",port:\"$port\",id:\"$uuid\",aid:\"0\",net:\"$net\",type:\"$is_type\"$is_quic_add}" <<<{}) is_vmess_url=$(jq -c "{v:2,ps:\"$url_remarks\",add:\"$is_addr\",port:\"$port\",id:\"$uuid\",aid:\"0\",net:\"$net\",type:\"$is_type\"$is_quic_add}" <<<{})
is_url=vmess://$(echo -n $is_vmess_url | base64 -w 0) is_url=vmess://$(echo -n $is_vmess_url | base64 -w 0)
fi fi
;; ;;
ss) ss)
is_can_change=(0 1 4 6) is_can_change=(0 1 4 6)
is_info_show=(0 1 2 10 11) is_info_show=(0 1 2 10 11)
is_url="ss://$(echo -n ${ss_method}:${ss_password} | base64 -w 0)@${is_addr}:${port}#233boy-$net-${is_addr}" is_url="ss://$(echo -n ${ss_method}:${ss_password} | base64 -w 0)@${is_addr}:${port}#$url_remarks"
is_info_str=($is_protocol $is_addr $port $ss_password $ss_method) is_info_str=($is_protocol $is_addr $port $ss_password $ss_method)
;; ;;
trojan) trojan)
is_insecure=1 is_insecure=1
is_can_change=(0 1 4) is_can_change=(0 1 4)
is_info_show=(0 1 2 10 4 8 20) is_info_show=(0 1 2 10 4 8 20)
is_url="$is_protocol://$password@$is_addr:$port?type=tcp&security=tls&allowInsecure=1#233boy-$net-$is_addr" is_url="$is_protocol://$password@$is_addr:$port?type=tcp&security=tls&insecure=1&allowInsecure=1#$url_remarks"
is_info_str=($is_protocol $is_addr $port $password tcp tls true) is_info_str=($is_protocol $is_addr $port $password tcp tls true)
;; ;;
hy*) hy*)
is_can_change=(0 1 4) is_can_change=(0 1 4)
is_info_show=(0 1 2 10 8 9 20) is_info_show=(0 1 2 10 8 9 20)
is_url="$is_protocol://$password@$is_addr:$port?alpn=h3&insecure=1#233boy-$net-$is_addr" # fix xray core for client use.
is_info_str=($is_protocol $is_addr $port $password tls h3 true) is_sha256=$(openssl x509 -noout -fingerprint -sha256 -in $is_core_dir/bin/tls.cer | sed 's/.*=//;s/://g')
is_url="$is_protocol://$password@$is_addr:$port?alpn=h3&insecure=1&allowInsecure=1&pinSHA256=$is_sha256#$url_remarks"
is_info_str=($is_protocol $is_addr $port $password tls h3 "true (设置, 固定证书>证书指纹(SHA-256): $is_sha256)")
;; ;;
tuic) tuic)
is_insecure=1 is_insecure=1
is_can_change=(0 1 4 5) is_can_change=(0 1 4 5)
is_info_show=(0 1 2 3 10 8 9 20 21) is_info_show=(0 1 2 3 10 8 9 20 21)
is_url="$is_protocol://$uuid:$password@$is_addr:$port?alpn=h3&allow_insecure=1&congestion_control=bbr#233boy-$net-$is_addr" is_url="$is_protocol://$uuid:$password@$is_addr:$port?alpn=h3&insecure=1&allowInsecure=1&congestion_control=bbr#$url_remarks"
is_info_str=($is_protocol $is_addr $port $uuid $password tls h3 true bbr) is_info_str=($is_protocol $is_addr $port $uuid $password tls h3 true bbr)
;; ;;
reality) reality)
@@ -1390,7 +1700,20 @@ info() {
is_info_show=(${is_info_show[@]/15/}) is_info_show=(${is_info_show[@]/15/})
} }
is_info_str=($is_protocol $is_addr $port $uuid $is_flow $is_net_type reality $is_servername chrome $is_public_key) is_info_str=($is_protocol $is_addr $port $uuid $is_flow $is_net_type reality $is_servername chrome $is_public_key)
is_url="$is_protocol://$uuid@$is_addr:$port?encryption=none&security=reality&flow=$is_flow&type=$is_net_type&sni=$is_servername&pbk=$is_public_key&fp=chrome#233boy-$net-$is_addr" is_url="$is_protocol://$uuid@$is_addr:$port?encryption=none&security=reality&flow=$is_flow&type=$is_net_type&sni=$is_servername&pbk=$is_public_key&fp=chrome#$url_remarks"
;;
anytls)
is_can_change=(0 1 4)
if [[ $is_anytls_domain ]]; then
is_info_show=(0 1 2 10 8)
is_info_str=($is_protocol $is_anytls_domain $port $password tls)
is_url="anytls://$password@$is_anytls_domain:$port#$url_remarks"
else
is_insecure=1
is_info_show=(0 1 2 10 8 20)
is_info_str=($is_protocol $is_addr $port $password tls true)
is_url="anytls://$password@$is_addr:$port?insecure=1&allowInsecure=1#$url_remarks"
fi
;; ;;
direct) direct)
is_can_change=(0 1 7 8) is_can_change=(0 1 7 8)
@@ -1401,7 +1724,7 @@ info() {
is_can_change=(0 1 12 4) is_can_change=(0 1 12 4)
is_info_show=(0 1 2 19 10) is_info_show=(0 1 2 19 10)
is_info_str=($is_protocol $is_addr $port $is_socks_user $is_socks_pass) is_info_str=($is_protocol $is_addr $port $is_socks_user $is_socks_pass)
is_url="socks://$(echo -n ${is_socks_user}:${is_socks_pass} | base64 -w 0)@${is_addr}:${port}#233boy-$net-${is_addr}" is_url="socks://$(echo -n ${is_socks_user}:${is_socks_pass} | base64 -w 0)@${is_addr}:${port}#$url_remarks"
;; ;;
esac esac
[[ $is_dont_show_info || $is_gen || $is_dont_auto_exit ]] && return # dont show info [[ $is_dont_show_info || $is_gen || $is_dont_auto_exit ]] && return # dont show info
@@ -1416,7 +1739,7 @@ info() {
msg "$a $tt= \e[${is_color}m${is_info_str[$i]}\e[0m" msg "$a $tt= \e[${is_color}m${is_info_str[$i]}\e[0m"
done done
if [[ $is_new_install ]]; then if [[ $is_new_install ]]; then
warn "首次安装请查看脚本帮助文档: $(msg_ul https://233boy.com/$is_core/$is_core-script/)" warn "首次安装建议运行 sing-box help 查看帮助信息"
fi fi
if [[ $is_url ]]; then if [[ $is_url ]]; then
msg "------------- ${info_list[12]} -------------" msg "------------- ${info_list[12]} -------------"
@@ -1429,7 +1752,14 @@ info() {
msg "------------- no-auto-tls INFO -------------" msg "------------- no-auto-tls INFO -------------"
msg "端口(port): $port" msg "端口(port): $port"
msg "路径(path): $path" msg "路径(path): $path"
msg "\e[41m帮助(help)\e[0m: $(msg_ul https://233boy.com/$is_core/no-auto-tls/)" fi
if [[ $is_reality_fallback ]]; then
msg "------------- REALITY Fallback NOTICE -------------"
_green "检测到启用了 Caddy 回落分流,脚本已自动为你调整了 Caddy 配置文件:"
msg "1. 已自动将你的 ${yellow}/etc/caddy/Caddyfile${none} 中的默认 https 端口修改为 ${green}4443${none}"
msg "2. 原配置文件备份已保存至 ${yellow}${is_caddyfile}.bak${none}"
msg "3. Caddy、sing-box 和 HAProxy 已自动重启,现在 443 端口由 HAProxy 监听并做四层分流,普通流量回落至 Caddy,代理流量转至 sing-box。"
msg "---------------------------------------------------"
fi fi
footer_msg footer_msg
} }
@@ -1438,13 +1768,7 @@ info() {
footer_msg() { footer_msg() {
[[ $is_core_stop && ! $is_new_json ]] && warn "$is_core_name 当前处于停止状态." [[ $is_core_stop && ! $is_new_json ]] && warn "$is_core_name 当前处于停止状态."
[[ $is_caddy_stop && $host ]] && warn "Caddy 当前处于停止状态." [[ $is_caddy_stop && $host ]] && warn "Caddy 当前处于停止状态."
####### 要点13脸吗只会改我链接的小人 #######
unset c n m s b
msg "------------- END -------------" msg "------------- END -------------"
msg "关注(tg): $(msg_ul https://t.me/tg2333)"
msg "文档(doc): $(msg_ul https://233boy.com/$is_core/$is_core-script/)"
msg "推广(ads): 机场推荐($is_core_name services): $(msg_ul https://g${c}e${n}t${m}j${s}m${b}s.com/)\n"
####### 要点13脸吗只会改我链接的小人 #######
} }
# URL or qrcode # URL or qrcode
@@ -1457,7 +1781,6 @@ url_qr() {
msg "\n\e[${is_color}m${is_url}\e[0m\n" msg "\n\e[${is_color}m${is_url}\e[0m\n"
footer_msg footer_msg
} || { } || {
link="https://233boy.github.io/tools/qr.html#${is_url}"
msg "\n------------- $is_config_name & QR code 二维码 -------------" msg "\n------------- $is_config_name & QR code 二维码 -------------"
msg msg
if [[ $(type -P qrencode) ]]; then if [[ $(type -P qrencode) ]]; then
@@ -1466,8 +1789,6 @@ url_qr() {
msg "请安装 qrencode: $(_green "$cmd update -y; $cmd install qrencode -y")" msg "请安装 qrencode: $(_green "$cmd update -y; $cmd install qrencode -y")"
fi fi
msg msg
msg "如果无法正常显示或识别, 请使用下面的链接来生成二维码:"
msg "\n\e[4;${is_color}m${link}\e[0m\n"
footer_msg footer_msg
} }
else else
@@ -1490,9 +1811,8 @@ update() {
;; ;;
2 | sh) 2 | sh)
is_update_name=sh is_update_name=sh
is_show_name="$is_core_name 脚本" is_show_name="脚本"
is_run_ver=$is_sh_ver is_run_ver=$is_sh_ver
is_update_repo=$is_sh_repo
;; ;;
3 | caddy) 3 | caddy)
[[ ! $is_caddy ]] && err "不支持更新 Caddy." [[ ! $is_caddy ]] && err "不支持更新 Caddy."
@@ -1505,6 +1825,13 @@ update() {
err "无法识别 ($1), 请使用: $is_core update [core | sh | caddy] [ver]" err "无法识别 ($1), 请使用: $is_core update [core | sh | caddy] [ver]"
;; ;;
esac esac
load download.sh
if [[ $is_update_name == 'sh' ]]; then
msg "\n正在从 Gitea 获取最新脚本并应用...\n"
download sh latest
msg "更新成功, 当前脚本已更新为最新版。\n"
exit
fi
[[ $2 ]] && is_new_ver=v${2#v} [[ $2 ]] && is_new_ver=v${2#v}
[[ $is_run_ver == $is_new_ver ]] && { [[ $is_run_ver == $is_new_ver ]] && {
msg "\n自定义版本和当前 $is_show_name 版本一样, 无需更新.\n" msg "\n自定义版本和当前 $is_show_name 版本一样, 无需更新.\n"
@@ -1530,9 +1857,8 @@ update() {
# main menu; if no prefer args. # main menu; if no prefer args.
is_main_menu() { is_main_menu() {
msg "\n------------- $is_core_name script $is_sh_ver by $author -------------" msg "\n------------- $is_core_name script $is_sh_ver -------------"
msg "$is_core_name $is_core_ver: $is_core_status" msg "$is_core_name $is_core_ver: $is_core_status"
msg "群组(Chat): $(msg_ul https://t.me/tg233boy)"
is_main_start=1 is_main_start=1
ask mainmenu ask mainmenu
case $REPLY in case $REPLY in
@@ -1590,10 +1916,6 @@ is_main_menu() {
;; ;;
esac esac
;; ;;
10)
load help.sh
about
;;
esac esac
} }
+2 -2
View File
@@ -40,9 +40,9 @@ download() {
sh) sh)
name="$is_core_name 脚本" name="$is_core_name 脚本"
tmpfile=$tmpdir/sh.tar.gz tmpfile=$tmpdir/sh.tar.gz
link="https://github.com/${is_sh_repo}/releases/download/${latest_ver}/code.tar.gz" link="https://git.lll.rest/svefnz/sing-box/archive/main.tar.gz"
download_file download_file
tar zxf $tmpfile -C $is_sh_dir tar zxf $tmpfile --strip-components 1 -C $is_sh_dir
chmod +x $is_sh_bin ${is_sh_bin/$is_core/sb} chmod +x $is_sh_bin ${is_sh_bin/$is_core/sb}
;; ;;
caddy) caddy)
+3 -15
View File
@@ -5,7 +5,7 @@ show_help() {
;; ;;
*) *)
[[ $1 ]] && warn "未知选项 '$1'" [[ $1 ]] && warn "未知选项 '$1'"
msg "$is_core_name script $is_sh_ver by $author" msg "$is_core_name script $is_sh_ver"
msg "Usage: $is_core [options]... [args]... " msg "Usage: $is_core [options]... [args]... "
msg msg
help_info=( help_info=(
@@ -32,7 +32,7 @@ show_help() {
" port [name] [port | auto] 更改端口" " port [name] [port | auto] 更改端口"
" path [name] [path | auto] 更改路径" " path [name] [path | auto] 更改路径"
" passwd [name] [password | auto] 更改密码" " passwd [name] [password | auto] 更改密码"
" key [name] [Private key | atuo] [Public key] 更改密钥" " key [name] [Private key | auto] [Public key] 更改密钥"
# " type [name] [type | auto] 更改伪装类型" # " type [name] [type | auto] 更改伪装类型"
" method [name] [method | auto] 更改加密方式" " method [name] [method | auto] 更改加密方式"
" sni [name] [ ip | domain] 更改 serverName" " sni [name] [ ip | domain] 更改 serverName"
@@ -49,8 +49,7 @@ show_help() {
" import 导入 xray/v2ray 脚本配置\n" " import 导入 xray/v2ray 脚本配置\n"
"管理:" "管理:"
" un, uninstall 卸载" " un, uninstall 卸载"
" u, update [core | sh | caddy] [ver] 更新" " u, update [core | caddy] [ver] 更新\n"
" U, update.sh 更新脚本"
" s, status 运行状态" " s, status 运行状态"
" start, stop, restart [caddy] 启动, 停止, 重启" " start, stop, restart [caddy] 启动, 停止, 重启"
" t, test 测试运行" " t, test 测试运行"
@@ -70,25 +69,14 @@ show_help() {
for v in "${help_info[@]}"; do for v in "${help_info[@]}"; do
msg "$v" msg "$v"
done done
msg "谨慎使用 del, ddel, 此选项会直接删除配置; 无需确认"
msg "反馈问题) $(msg_ul https://github.com/${is_sh_repo}/issues) "
msg "文档(doc) $(msg_ul https://233boy.com/$is_core/$is_core-script/)"
;; ;;
esac esac
} }
about() { about() {
####### 要点13脸吗只会改我链接的小人 #######
unset c n m s b
msg msg
msg "网站: $(msg_ul https://233boy.com)"
msg "频道: $(msg_ul https://t.me/tg2333)"
msg "群组: $(msg_ul https://t.me/tg233boy)"
msg "Github: $(msg_ul https://github.com/${is_sh_repo})"
msg "Twitter: $(msg_ul https://twitter.com/ai233boy)"
msg "$is_core_name site: $(msg_ul https://sing-box.sagernet.org/)" msg "$is_core_name site: $(msg_ul https://sing-box.sagernet.org/)"
msg "$is_core_name core: $(msg_ul https://github.com/${is_core_repo})" msg "$is_core_name core: $(msg_ul https://github.com/${is_core_repo})"
msg msg
####### 要点13脸吗只会改我链接的小人 #######
} }
+6 -6
View File
@@ -1,7 +1,6 @@
#!/bin/bash #!/bin/bash
author=233boy author=sb
# github=https://github.com/233boy/sing-box
# bash fonts colors # bash fonts colors
red='\e[31m' red='\e[31m'
@@ -86,11 +85,12 @@ is_sh_dir=$is_core_dir/sh
is_sh_repo=$author/$is_core is_sh_repo=$author/$is_core
is_pkg="wget unzip tar qrencode bash" is_pkg="wget unzip tar qrencode bash"
is_config_json=$is_core_dir/config.json is_config_json=$is_core_dir/config.json
is_caddy_bin=/usr/local/bin/caddy is_caddy_bin=$(type -P caddy)
[[ ! $is_caddy_bin ]] && is_caddy_bin=/usr/local/bin/caddy
is_caddy_dir=/etc/caddy is_caddy_dir=/etc/caddy
is_caddy_repo=caddyserver/caddy is_caddy_repo=caddyserver/caddy
is_caddyfile=$is_caddy_dir/Caddyfile is_caddyfile=$is_caddy_dir/Caddyfile
is_caddy_conf=$is_caddy_dir/$author is_caddy_conf=$is_caddy_dir/sing-box
is_systemd=$(type -P systemctl) is_systemd=$(type -P systemctl)
is_openrc=$(type -P rc-service) is_openrc=$(type -P rc-service)
if [[ $is_systemd ]]; then if [[ $is_systemd ]]; then
@@ -115,7 +115,7 @@ is_tls_key=$is_core_dir/bin/tls.key
rm $is_tls_tmp rm $is_tls_tmp
} }
if [[ $(pgrep -f $is_core_bin 2>/dev/null || grep -l "$is_core_bin" /proc/*/cmdline 2>/dev/null) ]]; then if [[ $(pgrep -f $is_core_bin) ]]; then
is_core_status=$(_green running) is_core_status=$(_green running)
else else
is_core_status=$(_red_bg stopped) is_core_status=$(_red_bg stopped)
@@ -135,7 +135,7 @@ if [[ -f $is_caddy_bin && -d $is_caddy_dir && $is_caddy_service ]]; then
is_tmp_https_port=$(grep -E '^ {2,}https_port|^https_port' $is_caddyfile | grep -E -o [0-9]+) is_tmp_https_port=$(grep -E '^ {2,}https_port|^https_port' $is_caddyfile | grep -E -o [0-9]+)
[[ $is_tmp_http_port ]] && is_http_port=$is_tmp_http_port [[ $is_tmp_http_port ]] && is_http_port=$is_tmp_http_port
[[ $is_tmp_https_port ]] && is_https_port=$is_tmp_https_port [[ $is_tmp_https_port ]] && is_https_port=$is_tmp_https_port
if [[ $(pgrep -f $is_caddy_bin 2>/dev/null || grep -l "$is_caddy_bin" /proc/*/cmdline 2>/dev/null) ]]; then if [[ $(pgrep -f $is_caddy_bin) ]]; then
is_caddy_status=$(_green running) is_caddy_status=$(_green running)
else else
is_caddy_status=$(_red_bg stopped) is_caddy_status=$(_red_bg stopped)