├── sing-box.sh ├── src ├── bbr.sh ├── log.sh ├── systemd.sh ├── caddy.sh ├── download.sh ├── dns.sh ├── import.sh ├── init.sh ├── help.sh └── core.sh ├── .github └── workflows │ └── release.yml ├── README.md ├── install.sh └── LICENSE /sing-box.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | args=$@ 4 | is_sh_ver=v1.13 5 | 6 | . /etc/sing-box/sh/src/init.sh -------------------------------------------------------------------------------- /src/bbr.sh: -------------------------------------------------------------------------------- 1 | _open_bbr() { 2 | sed -i '/net.ipv4.tcp_congestion_control/d' /etc/sysctl.conf 3 | sed -i '/net.core.default_qdisc/d' /etc/sysctl.conf 4 | echo "net.ipv4.tcp_congestion_control = bbr" >>/etc/sysctl.conf 5 | echo "net.core.default_qdisc = fq" >>/etc/sysctl.conf 6 | sysctl -p &>/dev/null 7 | echo 8 | _green "..已经启用 BBR 优化...." 9 | echo 10 | } 11 | 12 | _try_enable_bbr() { 13 | local _test1=$(uname -r | cut -d\. -f1) 14 | local _test2=$(uname -r | cut -d\. -f2) 15 | if [[ $_test1 -eq 4 && $_test2 -ge 9 ]] || [[ $_test1 -ge 5 ]]; then 16 | _open_bbr 17 | else 18 | err "不支持启用 BBR 优化." 19 | fi 20 | } 21 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Main 2 | 3 | on: push 4 | 5 | permissions: 6 | contents: write 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: checkout 13 | uses: actions/checkout@v3 14 | with: 15 | fetch-depth: 0 16 | - name: get ver 17 | run: | 18 | echo "$(cat *.sh | grep is_sh_ver=)" >> $GITHUB_ENV 19 | echo "old=$(git tag | tail -n1)" >> $GITHUB_ENV 20 | # - name: test 21 | # if: env.is_sh_ver == env.old 22 | # run: | 23 | # echo not found new version. 24 | # exit 1 25 | - name: tar 26 | run: tar zcvf code.tar.gz ./* 27 | - name: release 28 | uses: softprops/action-gh-release@v1 29 | with: 30 | files: code.tar.gz 31 | tag_name: ${{ env.is_sh_ver }} 32 | -------------------------------------------------------------------------------- /src/log.sh: -------------------------------------------------------------------------------- 1 | is_log_level_list=( 2 | trace 3 | debug 4 | info 5 | warn 6 | error 7 | fatal 8 | panic 9 | none 10 | del 11 | ) 12 | log_set() { 13 | if [[ $1 ]]; then 14 | for v in ${is_log_level_list[@]}; do 15 | [[ $(grep -E -i "^${1,,}$" <<<$v) ]] && is_log_level_use=$v && break 16 | done 17 | [[ ! $is_log_level_use ]] && { 18 | err "无法识别 log 参数: $@ \n请使用 $is_core log [${is_log_level_list[@]}] 进行相关设定.\n备注: del 参数仅临时删除 log 文件; none 参数将不会生成 log 文件." 19 | } 20 | case $is_log_level_use in 21 | del) 22 | rm -rf $is_log_dir/*.log 23 | msg "\n $(_green 已临时删除 log 文件, 如果你想要完全禁止生成 log 文件请使用: $is_core log none)\n" 24 | ;; 25 | none) 26 | rm -rf $is_log_dir/*.log 27 | cat <<<$(jq '.log={"disabled":true}' $is_config_json) >$is_config_json 28 | ;; 29 | *) 30 | cat <<<$(jq '.log={output:"/var/log/'$is_core'/access.log",level:"'$is_log_level_use'","timestamp":true}' $is_config_json) >$is_config_json 31 | ;; 32 | esac 33 | 34 | manage restart & 35 | [[ $1 != 'del' ]] && msg "\n已更新 Log 设定为: $(_green $is_log_level_use)\n" 36 | else 37 | if [[ -f $is_log_dir/access.log ]]; then 38 | msg "\n 提醒: 按 $(_green Ctrl + C) 退出\n" 39 | tail -f $is_log_dir/access.log 40 | else 41 | err "无法找到 log 文件." 42 | fi 43 | fi 44 | } -------------------------------------------------------------------------------- /src/systemd.sh: -------------------------------------------------------------------------------- 1 | install_service() { 2 | case $1 in 3 | $is_core) 4 | is_doc_site=https://sing-box.sagernet.org/ 5 | cat >/lib/systemd/system/$is_core.service <<<" 6 | [Unit] 7 | Description=$is_core_name Service 8 | Documentation=$is_doc_site 9 | After=network.target nss-lookup.target 10 | 11 | [Service] 12 | #User=nobody 13 | User=root 14 | NoNewPrivileges=true 15 | ExecStart=$is_core_bin run -c $is_config_json -C $is_conf_dir 16 | Restart=on-failure 17 | RestartPreventExitStatus=23 18 | LimitNPROC=10000 19 | LimitNOFILE=1048576 20 | PrivateTmp=true 21 | ProtectSystem=full 22 | #CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE 23 | #AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE 24 | 25 | [Install] 26 | WantedBy=multi-user.target" 27 | ;; 28 | caddy) 29 | cat >/lib/systemd/system/caddy.service <<<" 30 | #https://github.com/caddyserver/dist/blob/master/init/caddy.service 31 | [Unit] 32 | Description=Caddy 33 | Documentation=https://caddyserver.com/docs/ 34 | After=network.target network-online.target 35 | Requires=network-online.target 36 | 37 | [Service] 38 | Type=notify 39 | User=root 40 | Group=root 41 | ExecStart=$is_caddy_bin run --environ --config $is_caddyfile --adapter caddyfile 42 | ExecReload=$is_caddy_bin reload --config $is_caddyfile --adapter caddyfile 43 | TimeoutStopSec=5s 44 | LimitNPROC=10000 45 | LimitNOFILE=1048576 46 | PrivateTmp=true 47 | ProtectSystem=full 48 | #AmbientCapabilities=CAP_NET_BIND_SERVICE 49 | 50 | [Install] 51 | WantedBy=multi-user.target" 52 | ;; 53 | esac 54 | 55 | # enable, reload 56 | systemctl enable $1 57 | systemctl daemon-reload 58 | } 59 | -------------------------------------------------------------------------------- /src/caddy.sh: -------------------------------------------------------------------------------- 1 | caddy_config() { 2 | is_caddy_site_file=$is_caddy_conf/${host}.conf 3 | case $1 in 4 | new) 5 | mkdir -p $is_caddy_dir $is_caddy_dir/sites $is_caddy_conf 6 | cat >$is_caddyfile <<-EOF 7 | # don't edit this file # 8 | # for more info, see https://233boy.com/$is_core/caddy-auto-tls/ 9 | # 不要编辑这个文件 # 10 | # 更多相关请阅读此文章: https://233boy.com/$is_core/caddy-auto-tls/ 11 | # https://caddyserver.com/docs/caddyfile/options 12 | { 13 | admin off 14 | http_port $is_http_port 15 | https_port $is_https_port 16 | } 17 | import $is_caddy_conf/*.conf 18 | import $is_caddy_dir/sites/*.conf 19 | EOF 20 | ;; 21 | *ws* | *http*) 22 | cat >${is_caddy_site_file} <<<" 23 | ${host}:${is_https_port} { 24 | reverse_proxy ${path} 127.0.0.1:${port} 25 | import ${is_caddy_site_file}.add 26 | }" 27 | ;; 28 | *h2*) 29 | cat >${is_caddy_site_file} <<<" 30 | ${host}:${is_https_port} { 31 | reverse_proxy ${path} h2c://127.0.0.1:${port} { 32 | transport http { 33 | tls_insecure_skip_verify 34 | } 35 | } 36 | import ${is_caddy_site_file}.add 37 | }" 38 | ;; 39 | *grpc*) 40 | cat >${is_caddy_site_file} <<<" 41 | ${host}:${is_https_port} { 42 | reverse_proxy /${path}/* h2c://127.0.0.1:${port} 43 | import ${is_caddy_site_file}.add 44 | }" 45 | ;; 46 | proxy) 47 | 48 | cat >${is_caddy_site_file}.add <<<" 49 | reverse_proxy https://$proxy_site { 50 | header_up Host {upstream_hostport} 51 | }" 52 | ;; 53 | esac 54 | [[ $1 != "new" && $1 != 'proxy' ]] && { 55 | [[ ! -f ${is_caddy_site_file}.add ]] && echo "# see https://233boy.com/$is_core/caddy-auto-tls/" >${is_caddy_site_file}.add 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/download.sh: -------------------------------------------------------------------------------- 1 | get_latest_version() { 2 | case $1 in 3 | core) 4 | name=$is_core_name 5 | url="https://api.github.com/repos/${is_core_repo}/releases/latest?v=$RANDOM" 6 | ;; 7 | sh) 8 | name="$is_core_name 脚本" 9 | url="https://api.github.com/repos/$is_sh_repo/releases/latest?v=$RANDOM" 10 | ;; 11 | caddy) 12 | name="Caddy" 13 | url="https://api.github.com/repos/$is_caddy_repo/releases/latest?v=$RANDOM" 14 | ;; 15 | esac 16 | latest_ver=$(_wget -qO- $url | grep tag_name | grep -E -o 'v([0-9.]+)') 17 | [[ ! $latest_ver ]] && { 18 | err "获取 ${name} 最新版本失败." 19 | } 20 | unset name url 21 | } 22 | download() { 23 | latest_ver=$2 24 | [[ ! $latest_ver ]] && get_latest_version $1 25 | # tmp dir 26 | tmpdir=$(mktemp -u) 27 | [[ ! $tmpdir ]] && { 28 | tmpdir=/tmp/tmp-$RANDOM 29 | } 30 | mkdir -p $tmpdir 31 | case $1 in 32 | core) 33 | name=$is_core_name 34 | tmpfile=$tmpdir/$is_core.tar.gz 35 | link="https://github.com/${is_core_repo}/releases/download/${latest_ver}/${is_core}-${latest_ver:1}-linux-${is_arch}.tar.gz" 36 | download_file 37 | tar zxf $tmpfile --strip-components 1 -C $is_core_dir/bin 38 | chmod +x $is_core_bin 39 | ;; 40 | sh) 41 | name="$is_core_name 脚本" 42 | tmpfile=$tmpdir/sh.tar.gz 43 | link="https://github.com/${is_sh_repo}/releases/download/${latest_ver}/code.tar.gz" 44 | download_file 45 | tar zxf $tmpfile -C $is_sh_dir 46 | chmod +x $is_sh_bin ${is_sh_bin/$is_core/sb} 47 | ;; 48 | caddy) 49 | name="Caddy" 50 | tmpfile=$tmpdir/caddy.tar.gz 51 | # https://github.com/caddyserver/caddy/releases/download/v2.6.4/caddy_2.6.4_linux_amd64.tar.gz 52 | link="https://github.com/${is_caddy_repo}/releases/download/${latest_ver}/caddy_${latest_ver:1}_linux_${is_arch}.tar.gz" 53 | download_file 54 | tar zxf $tmpfile -C $tmpdir 55 | cp -f $tmpdir/caddy $is_caddy_bin 56 | chmod +x $is_caddy_bin 57 | ;; 58 | esac 59 | rm -rf $tmpdir 60 | unset latest_ver 61 | } 62 | download_file() { 63 | if ! _wget -t 5 -c $link -O $tmpfile; then 64 | rm -rf $tmpdir 65 | err "\n下载 ${name} 失败.\n" 66 | fi 67 | } 68 | -------------------------------------------------------------------------------- /src/dns.sh: -------------------------------------------------------------------------------- 1 | is_dns_list=( 2 | 1.1.1.1 3 | 8.8.8.8 4 | h3://dns.google/dns-query 5 | h3://cloudflare-dns.com/dns-query 6 | h3://family.cloudflare-dns.com/dns-query 7 | set 8 | none 9 | ) 10 | dns_set() { 11 | if [[ $(echo -e "1.11.99\n$is_core_ver" | sort -V | head -n1) == '1.11.99' ]]; then 12 | is_dns_new=1 13 | fi 14 | if [[ $1 ]]; then 15 | case ${1,,} in 16 | 11 | 1111) 17 | is_dns_use=${is_dns_list[0]} 18 | ;; 19 | 88 | 8888) 20 | is_dns_use=${is_dns_list[1]} 21 | ;; 22 | gg | google) 23 | is_dns_use=${is_dns_list[2]} 24 | ;; 25 | cf | cloudflare) 26 | is_dns_use=${is_dns_list[3]} 27 | ;; 28 | nosex | family) 29 | is_dns_use=${is_dns_list[4]} 30 | ;; 31 | set) 32 | if [[ $2 ]]; then 33 | is_dns_use=${2,,} 34 | else 35 | ask string is_dns_use "请输入 DNS: " 36 | fi 37 | ;; 38 | none) 39 | is_dns_use=none 40 | ;; 41 | *) 42 | err "无法识别 DNS 参数: $@" 43 | ;; 44 | esac 45 | else 46 | is_tmp_list=(${is_dns_list[@]}) 47 | ask list is_dns_use null "\n请选择 DNS:\n" 48 | if [[ $is_dns_use == "set" ]]; then 49 | ask string is_dns_use "请输入 DNS: " 50 | fi 51 | fi 52 | is_dns_use_bak=$is_dns_use 53 | if [[ $is_dns_use == "none" ]]; then 54 | cat <<<$(jq '.dns={}' $is_config_json) >$is_config_json 55 | else 56 | if [[ $is_dns_new ]]; then 57 | dns_set_server $is_dns_use 58 | cat <<<$(jq '.dns.servers=[{type:"'$is_dns_type'",server:"'$is_dns_use'",domain_resolver:"local"},{tag:"local",type:"local"}]' $is_config_json) >$is_config_json 59 | else 60 | cat <<<$(jq '.dns.servers=[{address:"'$is_dns_use'",address_resolver:"local"},{tag:"local",address:"local"}]' $is_config_json) >$is_config_json 61 | fi 62 | fi 63 | manage restart & 64 | msg "\n已更新 DNS 为: $(_green $is_dns_use_bak)\n" 65 | } 66 | dns_set_server() { 67 | if [[ $(grep '://' <<<$1) ]]; then 68 | is_tmp_dns_set=($(awk -F '://|/' '{print $1, $2}' <<<${1,,})) 69 | case ${is_tmp_dns_set[0]} in 70 | tcp | udp | tls | https | quic | h3) 71 | is_dns_use=${is_tmp_dns_set[1]} 72 | is_dns_type=${is_tmp_dns_set[0]} 73 | ;; 74 | *) 75 | err "无法识别 DNS 类型!" 76 | ;; 77 | esac 78 | else 79 | is_dns_use=$1 80 | is_dns_type=udp 81 | fi 82 | } -------------------------------------------------------------------------------- /src/import.sh: -------------------------------------------------------------------------------- 1 | is_xray_sh=/etc/xray/sh/src/core.sh 2 | is_v2ray_sh=/etc/v2ray/sh/src/core.sh 3 | is_xray_conf=/etc/xray/conf 4 | is_v2ray_conf=/etc/v2ray/conf 5 | in_conf() { 6 | is_conf_args=$(jq '.inbounds[0]|.protocol,.port,(.settings|(.clients[0]|.id,.password),.method,.password,.port,.address,(.accounts[0]|.user,.pass)),(.streamSettings|.network,.security,.tcpSettings.header.type,(.wsSettings|.path,.headers.Host),(.httpSettings|.path,.host[0]),(.realitySettings|.serverNames[0],.publicKey,.privateKey))' $1) 7 | [[ $? != 0 ]] && warn "无法读取此文件: $1" && return 8 | is_up_var_set=(null is_protocol port uuid trojan_password ss_method ss_password door_port door_addr is_socks_user is_socks_pass net is_reality net_type ws_path ws_host h2_path h2_host is_servername is_public_key is_private_key) 9 | i=0 10 | for v in $(sed 's/""/null/g;s/"//g' <<<"$is_conf_args"); do 11 | ((i++)) 12 | export ${is_up_var_set[$i]}="${v}" 13 | done 14 | for v in ${is_up_var_set[@]}; do 15 | [[ ${!v} == 'null' ]] && unset $v 16 | done 17 | path="${ws_path}${h2_path}" 18 | host="${ws_host}${h2_host}" 19 | [[ ! $uuid ]] && uuid=$trojan_password 20 | if [[ $host ]]; then 21 | if [[ $is_caddy && -f $is_caddy_conf/$host.conf ]]; then 22 | tmp_tlsport=$(grep -E -o "$host:[1-9][0-9]?+" $is_caddy_conf/$host.conf | sed s/.*://) 23 | fi 24 | [[ $tmp_tlsport ]] && https_port=$tmp_tlsport 25 | add $is_protocol-$net-tls 26 | else 27 | case $is_protocol in 28 | vmess | vless) 29 | [[ $net_type == "http" ]] && { 30 | net=http 31 | is_tips_msg="新配置文件名: (VMess-HTTP-$port.json)" 32 | } 33 | [[ $is_reality == "reality" ]] && net=reality 34 | add $net 35 | ;; 36 | dokodemo-door) 37 | add door 38 | is_tips_msg="新配置文件名: (Direct-$port.json)" 39 | ;; 40 | *socks*) 41 | add $is_protocol 42 | ;; 43 | *) 44 | is_not_in_conf=1 45 | msg "不支持导入 $1" 46 | ;; 47 | 48 | esac 49 | fi 50 | [[ ! $is_not_in_conf ]] && msg "导入: $1 $is_tips_msg" && rm $1 51 | } 52 | is_change=1 53 | is_dont_auto_exit=1 54 | is_dont_test_host=1 55 | if [[ -f $is_xray_sh && -d $is_xray_conf ]]; then 56 | is_list=($(ls $is_xray_conf | grep .json | grep -E -iv 'kcp|grpc|dynamic|quic' | sed "s#^#$is_xray_conf/#")) 57 | fi 58 | if [[ -f $is_v2ray_sh && -d $is_v2ray_conf ]]; then 59 | is_list+=($(ls $is_v2ray_conf | grep .json | grep -E -iv 'kcp|grpc|dynamic|quic' | sed "s#^#$is_v2ray_conf/#")) 60 | fi 61 | [[ ${is_list[@]} =~ "xray" ]] && is_xray_in=1 62 | [[ ${is_list[@]} =~ "v2ray" ]] && is_v2ray_in=1 63 | [[ $is_xray_in ]] && xray stop 64 | [[ $is_v2ray_in ]] && v2ray stop 65 | if [[ ${is_list[@]} ]]; then 66 | msg "开始导入配置..." 67 | for i in ${is_list[@]}; do 68 | in_conf $i & 69 | done 70 | wait 71 | is_dont_auto_exit= 72 | manage restart & 73 | [[ $is_xray_in ]] && xray restart & 74 | [[ $is_v2ray_in ]] && v2ray restart & 75 | [[ ${is_list[@],,} =~ "tls" && $is_caddy ]] && manage restart caddy & 76 | 77 | else 78 | err "没有找到可导入的配置..." 79 | fi -------------------------------------------------------------------------------- /src/init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | author=233boy 4 | # github=https://github.com/233boy/sing-box 5 | 6 | # bash fonts colors 7 | red='\e[31m' 8 | yellow='\e[33m' 9 | gray='\e[90m' 10 | green='\e[92m' 11 | blue='\e[94m' 12 | magenta='\e[95m' 13 | cyan='\e[96m' 14 | none='\e[0m' 15 | 16 | _red() { echo -e ${red}$@${none}; } 17 | _blue() { echo -e ${blue}$@${none}; } 18 | _cyan() { echo -e ${cyan}$@${none}; } 19 | _green() { echo -e ${green}$@${none}; } 20 | _yellow() { echo -e ${yellow}$@${none}; } 21 | _magenta() { echo -e ${magenta}$@${none}; } 22 | _red_bg() { echo -e "\e[41m$@${none}"; } 23 | 24 | _rm() { 25 | rm -rf "$@" 26 | } 27 | _cp() { 28 | cp -rf "$@" 29 | } 30 | _sed() { 31 | sed -i "$@" 32 | } 33 | _mkdir() { 34 | mkdir -p "$@" 35 | } 36 | 37 | is_err=$(_red_bg 错误!) 38 | is_warn=$(_red_bg 警告!) 39 | 40 | err() { 41 | echo -e "\n$is_err $@\n" 42 | [[ $is_dont_auto_exit ]] && return 43 | exit 1 44 | } 45 | 46 | warn() { 47 | echo -e "\n$is_warn $@\n" 48 | } 49 | 50 | # load bash script. 51 | load() { 52 | . $is_sh_dir/src/$1 53 | } 54 | 55 | # wget add --no-check-certificate 56 | _wget() { 57 | # [[ $proxy ]] && export https_proxy=$proxy 58 | wget --no-check-certificate "$@" 59 | } 60 | 61 | # yum or apt-get 62 | cmd=$(type -P apt-get || type -P yum) 63 | 64 | # x64 65 | case $(arch) in 66 | amd64 | x86_64) 67 | is_arch="amd64" 68 | ;; 69 | *aarch64* | *armv8*) 70 | is_arch="arm64" 71 | ;; 72 | *) 73 | err "此脚本仅支持 64 位系统..." 74 | ;; 75 | esac 76 | 77 | is_core=sing-box 78 | is_core_name=sing-box 79 | is_core_dir=/etc/$is_core 80 | is_core_bin=$is_core_dir/bin/$is_core 81 | is_core_repo=SagerNet/$is_core 82 | is_conf_dir=$is_core_dir/conf 83 | is_log_dir=/var/log/$is_core 84 | is_sh_bin=/usr/local/bin/$is_core 85 | is_sh_dir=$is_core_dir/sh 86 | is_sh_repo=$author/$is_core 87 | is_pkg="wget unzip tar qrencode" 88 | is_config_json=$is_core_dir/config.json 89 | is_caddy_bin=/usr/local/bin/caddy 90 | is_caddy_dir=/etc/caddy 91 | is_caddy_repo=caddyserver/caddy 92 | is_caddyfile=$is_caddy_dir/Caddyfile 93 | is_caddy_conf=$is_caddy_dir/$author 94 | is_caddy_service=$(systemctl list-units --full -all | grep caddy.service) 95 | is_http_port=80 96 | is_https_port=443 97 | 98 | # core ver 99 | is_core_ver=$($is_core_bin version | head -n1 | cut -d " " -f3) 100 | 101 | # tmp tls key 102 | is_tls_cer=$is_core_dir/bin/tls.cer 103 | is_tls_key=$is_core_dir/bin/tls.key 104 | [[ ! -f $is_tls_cer || ! -f $is_tls_key ]] && { 105 | is_tls_tmp=${is_tls_key/key/tmp} 106 | $is_core_bin generate tls-keypair tls -m 456 >$is_tls_tmp 107 | awk '/BEGIN PRIVATE KEY/,/END PRIVATE KEY/' $is_tls_tmp >$is_tls_key 108 | awk '/BEGIN CERTIFICATE/,/END CERTIFICATE/' $is_tls_tmp >$is_tls_cer 109 | rm $is_tls_tmp 110 | } 111 | 112 | if [[ $(pgrep -f $is_core_bin) ]]; then 113 | is_core_status=$(_green running) 114 | else 115 | is_core_status=$(_red_bg stopped) 116 | is_core_stop=1 117 | fi 118 | if [[ -f $is_caddy_bin && -d $is_caddy_dir && $is_caddy_service ]]; then 119 | is_caddy=1 120 | # fix caddy run; ver >= 2.8.2 121 | [[ ! $(grep '\-\-adapter caddyfile' /lib/systemd/system/caddy.service) ]] && { 122 | load systemd.sh 123 | install_service caddy 124 | systemctl restart caddy & 125 | } 126 | is_caddy_ver=$($is_caddy_bin version | head -n1 | cut -d " " -f1) 127 | is_tmp_http_port=$(grep -E '^ {2,}http_port|^http_port' $is_caddyfile | grep -E -o [0-9]+) 128 | is_tmp_https_port=$(grep -E '^ {2,}https_port|^https_port' $is_caddyfile | grep -E -o [0-9]+) 129 | [[ $is_tmp_http_port ]] && is_http_port=$is_tmp_http_port 130 | [[ $is_tmp_https_port ]] && is_https_port=$is_tmp_https_port 131 | if [[ $(pgrep -f $is_caddy_bin) ]]; then 132 | is_caddy_status=$(_green running) 133 | else 134 | is_caddy_status=$(_red_bg stopped) 135 | is_caddy_stop=1 136 | fi 137 | fi 138 | 139 | load core.sh 140 | [[ ! $args ]] && args=main 141 | main $args 142 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 介绍 2 | 3 | 最好用的 sing-box 一键安装脚本 & 管理脚本 4 | 5 | # 特点 6 | 7 | - 快速安装 8 | - 无敌好用 9 | - 零学习成本 10 | - 自动化 TLS 11 | - 简化所有流程 12 | - 兼容 sing-box 命令 13 | - 强大的快捷参数 14 | - 支持所有常用协议 15 | - 一键添加 VLESS-REALITY (默认) 16 | - 一键添加 TUIC 17 | - 一键添加 Trojan 18 | - 一键添加 Hysteria2 19 | - 一键添加 Shadowsocks 2022 20 | - 一键添加 VMess-(TCP/HTTP/QUIC) 21 | - 一键添加 VMess-(WS/H2/HTTPUpgrade)-TLS 22 | - 一键添加 VLESS-(WS/H2/HTTPUpgrade)-TLS 23 | - 一键添加 Trojan-(WS/H2/HTTPUpgrade)-TLS 24 | - 一键启用 BBR 25 | - 一键更改伪装网站 26 | - 一键更改 (端口/UUID/密码/域名/路径/加密方式/SNI/等...) 27 | - 还有更多... 28 | 29 | # 设计理念 30 | 31 | 设计理念为:**高效率,超快速,极易用** 32 | 33 | 脚本基于作者的自身使用需求,以 **多配置同时运行** 为核心设计 34 | 35 | 并且专门优化了,添加、更改、查看、删除、这四项常用功能 36 | 37 | 你只需要一条命令即可完成 添加、更改、查看、删除、等操作 38 | 39 | 例如,添加一个配置仅需不到 1 秒!瞬间完成添加!其他操作亦是如此! 40 | 41 | 脚本的参数非常高效率并且超级易用,请掌握参数的使用 42 | 43 | # 文档 44 | 45 | 安装及使用:https://233boy.com/sing-box/sing-box-script/ 46 | 47 | # 帮助 48 | 49 | 使用:`sing-box help` 50 | 51 | ``` 52 | sing-box script v1.0 by 233boy 53 | Usage: sing-box [options]... [args]... 54 | 55 | 基本: 56 | v, version 显示当前版本 57 | ip 返回当前主机的 IP 58 | pbk 同等于 sing-box generate reality-keypair 59 | get-port 返回一个可用的端口 60 | ss2022 返回一个可用于 Shadowsocks 2022 的密码 61 | 62 | 一般: 63 | a, add [protocol] [args... | auto] 添加配置 64 | c, change [name] [option] [args... | auto] 更改配置 65 | d, del [name] 删除配置** 66 | i, info [name] 查看配置 67 | qr [name] 二维码信息 68 | url [name] URL 信息 69 | log 查看日志 70 | 更改: 71 | full [name] [...] 更改多个参数 72 | id [name] [uuid | auto] 更改 UUID 73 | host [name] [domain] 更改域名 74 | port [name] [port | auto] 更改端口 75 | path [name] [path | auto] 更改路径 76 | passwd [name] [password | auto] 更改密码 77 | key [name] [Private key | atuo] [Public key] 更改密钥 78 | method [name] [method | auto] 更改加密方式 79 | sni [name] [ ip | domain] 更改 serverName 80 | new [name] [...] 更改协议 81 | web [name] [domain] 更改伪装网站 82 | 83 | 进阶: 84 | dns [...] 设置 DNS 85 | dd, ddel [name...] 删除多个配置** 86 | fix [name] 修复一个配置 87 | fix-all 修复全部配置 88 | fix-caddyfile 修复 Caddyfile 89 | fix-config.json 修复 config.json 90 | import 导入 sing-box/v2ray 脚本配置 91 | 92 | 管理: 93 | un, uninstall 卸载 94 | u, update [core | sh | caddy] [ver] 更新 95 | U, update.sh 更新脚本 96 | s, status 运行状态 97 | start, stop, restart [caddy] 启动, 停止, 重启 98 | t, test 测试运行 99 | reinstall 重装脚本 100 | 101 | 测试: 102 | debug [name] 显示一些 debug 信息, 仅供参考 103 | gen [...] 同等于 add, 但只显示 JSON 内容, 不创建文件, 测试使用 104 | no-auto-tls [...] 同等于 add, 但禁止自动配置 TLS, 可用于 *TLS 相关协议 105 | 其他: 106 | bbr 启用 BBR, 如果支持 107 | bin [...] 运行 sing-box 命令, 例如: sing-box bin help 108 | [...] [...] 兼容绝大多数的 sing-box 命令, 例如: sing-box generate uuid 109 | h, help 显示此帮助界面 110 | 111 | 谨慎使用 del, ddel, 此选项会直接删除配置; 无需确认 112 | 反馈问题) https://github.com/233boy/sing-box/issues 113 | 文档(doc) https://233boy.com/sing-box/sing-box-script/ 114 | ``` -------------------------------------------------------------------------------- /src/help.sh: -------------------------------------------------------------------------------- 1 | show_help() { 2 | case $1 in 3 | api | x25519 | tls | run | uuid | version) 4 | $is_core_bin help $1 ${@:2} 5 | ;; 6 | *) 7 | [[ $1 ]] && warn "未知选项 '$1'" 8 | msg "$is_core_name script $is_sh_ver by $author" 9 | msg "Usage: $is_core [options]... [args]... " 10 | msg 11 | help_info=( 12 | "基本:" 13 | " v, version 显示当前版本" 14 | " ip 返回当前主机的 IP" 15 | " pbk 同等于 $is_core generate reality-keypair" 16 | " get-port 返回一个可用的端口" 17 | " ss2022 返回一个可用于 Shadowsocks 2022 的密码\n" 18 | "一般:" 19 | " a, add [protocol] [args... | auto] 添加配置" 20 | " c, change [name] [option] [args... | auto] 更改配置" 21 | " d, del [name] 删除配置**" 22 | " i, info [name] 查看配置" 23 | " qr [name] 二维码信息" 24 | " url [name] URL 信息" 25 | " log 查看日志" 26 | # " logerr 查看错误日志\n" 27 | "更改:" 28 | # " dp, dynamicport [name] [start | auto] [end] 更改动态端口" 29 | " full [name] [...] 更改多个参数" 30 | " id [name] [uuid | auto] 更改 UUID" 31 | " host [name] [domain] 更改域名" 32 | " port [name] [port | auto] 更改端口" 33 | " path [name] [path | auto] 更改路径" 34 | " passwd [name] [password | auto] 更改密码" 35 | " key [name] [Private key | atuo] [Public key] 更改密钥" 36 | # " type [name] [type | auto] 更改伪装类型" 37 | " method [name] [method | auto] 更改加密方式" 38 | " sni [name] [ ip | domain] 更改 serverName" 39 | # " seed [name] [seed | auto] 更改 mKCP seed" 40 | " new [name] [...] 更改协议" 41 | " web [name] [domain] 更改伪装网站\n" 42 | "进阶:" 43 | " dns [...] 设置 DNS" 44 | " dd, ddel [name...] 删除多个配置**" 45 | " fix [name] 修复一个配置" 46 | " fix-all 修复全部配置" 47 | " fix-caddyfile 修复 Caddyfile" 48 | " fix-config.json 修复 config.json" 49 | " import 导入 xray/v2ray 脚本配置\n" 50 | "管理:" 51 | " un, uninstall 卸载" 52 | " u, update [core | sh | caddy] [ver] 更新" 53 | " U, update.sh 更新脚本" 54 | " s, status 运行状态" 55 | " start, stop, restart [caddy] 启动, 停止, 重启" 56 | " t, test 测试运行" 57 | " reinstall 重装脚本\n" 58 | "测试:" 59 | # " client, genc [name] 显示用于客户端 JSON, 仅供参考" 60 | " debug [name] 显示一些 debug 信息, 仅供参考" 61 | " gen [...] 同等于 add, 但只显示 JSON 内容, 不创建文件, 测试使用" 62 | " no-auto-tls [...] 同等于 add, 但禁止自动配置 TLS, 可用于 *TLS 相关协议" 63 | # " xapi [...] 同等于 $is_core api, 但 API 后端使用当前运行的 $is_core_name 服务\n" 64 | "其他:" 65 | " bbr 启用 BBR, 如果支持" 66 | " bin [...] 运行 $is_core_name 命令, 例如: $is_core bin help" 67 | " [...] [...] 兼容绝大多数的 $is_core_name 命令, 例如: $is_core_name generate uuid" 68 | " h, help 显示此帮助界面\n" 69 | ) 70 | for v in "${help_info[@]}"; do 71 | msg "$v" 72 | done 73 | msg "谨慎使用 del, ddel, 此选项会直接删除配置; 无需确认" 74 | msg "反馈问题) $(msg_ul https://github.com/${is_sh_repo}/issues) " 75 | msg "文档(doc) $(msg_ul https://233boy.com/$is_core/$is_core-script/)" 76 | ;; 77 | 78 | esac 79 | } 80 | 81 | about() { 82 | ####### 要点13脸吗只会改我链接的小人 ####### 83 | unset c n m s b 84 | msg 85 | msg "网站: $(msg_ul https://233boy.com)" 86 | msg "频道: $(msg_ul https://t.me/tg2333)" 87 | msg "群组: $(msg_ul https://t.me/tg233boy)" 88 | msg "Github: $(msg_ul https://github.com/${is_sh_repo})" 89 | msg "Twitter: $(msg_ul https://twitter.com/ai233boy)" 90 | msg "$is_core_name site: $(msg_ul https://sing-box.sagernet.org/)" 91 | msg "$is_core_name core: $(msg_ul https://github.com/${is_core_repo})" 92 | msg 93 | ####### 要点13脸吗只会改我链接的小人 ####### 94 | } 95 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | author=233boy 4 | # github=https://github.com/233boy/sing-box 5 | 6 | # bash fonts colors 7 | red='\e[31m' 8 | yellow='\e[33m' 9 | gray='\e[90m' 10 | green='\e[92m' 11 | blue='\e[94m' 12 | magenta='\e[95m' 13 | cyan='\e[96m' 14 | none='\e[0m' 15 | _red() { echo -e ${red}$@${none}; } 16 | _blue() { echo -e ${blue}$@${none}; } 17 | _cyan() { echo -e ${cyan}$@${none}; } 18 | _green() { echo -e ${green}$@${none}; } 19 | _yellow() { echo -e ${yellow}$@${none}; } 20 | _magenta() { echo -e ${magenta}$@${none}; } 21 | _red_bg() { echo -e "\e[41m$@${none}"; } 22 | 23 | is_err=$(_red_bg 错误!) 24 | is_warn=$(_red_bg 警告!) 25 | 26 | err() { 27 | echo -e "\n$is_err $@\n" && exit 1 28 | } 29 | 30 | warn() { 31 | echo -e "\n$is_warn $@\n" 32 | } 33 | 34 | # root 35 | [[ $EUID != 0 ]] && err "当前非 ${yellow}ROOT用户.${none}" 36 | 37 | # yum or apt-get, ubuntu/debian/centos 38 | cmd=$(type -P apt-get || type -P yum) 39 | [[ ! $cmd ]] && err "此脚本仅支持 ${yellow}(Ubuntu or Debian or CentOS)${none}." 40 | 41 | # systemd 42 | [[ ! $(type -P systemctl) ]] && { 43 | err "此系统缺少 ${yellow}(systemctl)${none}, 请尝试执行:${yellow} ${cmd} update -y;${cmd} install systemd -y ${none}来修复此错误." 44 | } 45 | 46 | # wget installed or none 47 | is_wget=$(type -P wget) 48 | 49 | # x64 50 | case $(uname -m) in 51 | amd64 | x86_64) 52 | is_arch=amd64 53 | ;; 54 | *aarch64* | *armv8*) 55 | is_arch=arm64 56 | ;; 57 | *) 58 | err "此脚本仅支持 64 位系统..." 59 | ;; 60 | esac 61 | 62 | is_core=sing-box 63 | is_core_name=sing-box 64 | is_core_dir=/etc/$is_core 65 | is_core_bin=$is_core_dir/bin/$is_core 66 | is_core_repo=SagerNet/$is_core 67 | is_conf_dir=$is_core_dir/conf 68 | is_log_dir=/var/log/$is_core 69 | is_sh_bin=/usr/local/bin/$is_core 70 | is_sh_dir=$is_core_dir/sh 71 | is_sh_repo=$author/$is_core 72 | is_pkg="wget tar" 73 | is_config_json=$is_core_dir/config.json 74 | tmp_var_lists=( 75 | tmpcore 76 | tmpsh 77 | tmpjq 78 | is_core_ok 79 | is_sh_ok 80 | is_jq_ok 81 | is_pkg_ok 82 | ) 83 | 84 | # tmp dir 85 | tmpdir=$(mktemp -u) 86 | [[ ! $tmpdir ]] && { 87 | tmpdir=/tmp/tmp-$RANDOM 88 | } 89 | 90 | # set up var 91 | for i in ${tmp_var_lists[*]}; do 92 | export $i=$tmpdir/$i 93 | done 94 | 95 | # load bash script. 96 | load() { 97 | . $is_sh_dir/src/$1 98 | } 99 | 100 | # wget add --no-check-certificate 101 | _wget() { 102 | [[ $proxy ]] && export https_proxy=$proxy 103 | wget --no-check-certificate $* 104 | } 105 | 106 | # print a mesage 107 | msg() { 108 | case $1 in 109 | warn) 110 | local color=$yellow 111 | ;; 112 | err) 113 | local color=$red 114 | ;; 115 | ok) 116 | local color=$green 117 | ;; 118 | esac 119 | 120 | echo -e "${color}$(date +'%T')${none}) ${2}" 121 | } 122 | 123 | # show help msg 124 | show_help() { 125 | echo -e "Usage: $0 [-f xxx | -l | -p xxx | -v xxx | -h]" 126 | echo -e " -f, --core-file 自定义 $is_core_name 文件路径, e.g., -f /root/$is_core-linux-amd64.tar.gz" 127 | echo -e " -l, --local-install 本地获取安装脚本, 使用当前目录" 128 | echo -e " -p, --proxy 使用代理下载, e.g., -p http://127.0.0.1:2333" 129 | echo -e " -v, --core-version 自定义 $is_core_name 版本, e.g., -v v1.8.13" 130 | echo -e " -h, --help 显示此帮助界面\n" 131 | 132 | exit 0 133 | } 134 | 135 | # install dependent pkg 136 | install_pkg() { 137 | cmd_not_found= 138 | for i in $*; do 139 | [[ ! $(type -P $i) ]] && cmd_not_found="$cmd_not_found,$i" 140 | done 141 | if [[ $cmd_not_found ]]; then 142 | pkg=$(echo $cmd_not_found | sed 's/,/ /g') 143 | msg warn "安装依赖包 >${pkg}" 144 | $cmd install -y $pkg &>/dev/null 145 | if [[ $? != 0 ]]; then 146 | [[ $cmd =~ yum ]] && yum install epel-release -y &>/dev/null 147 | $cmd update -y &>/dev/null 148 | $cmd install -y $pkg &>/dev/null 149 | [[ $? == 0 ]] && >$is_pkg_ok 150 | else 151 | >$is_pkg_ok 152 | fi 153 | else 154 | >$is_pkg_ok 155 | fi 156 | } 157 | 158 | # download file 159 | download() { 160 | case $1 in 161 | core) 162 | [[ ! $is_core_ver ]] && is_core_ver=$(_wget -qO- "https://api.github.com/repos/${is_core_repo}/releases/latest?v=$RANDOM" | grep tag_name | grep -E -o 'v([0-9.]+)') 163 | [[ $is_core_ver ]] && link="https://github.com/${is_core_repo}/releases/download/${is_core_ver}/${is_core}-${is_core_ver:1}-linux-${is_arch}.tar.gz" 164 | name=$is_core_name 165 | tmpfile=$tmpcore 166 | is_ok=$is_core_ok 167 | ;; 168 | sh) 169 | link=https://github.com/${is_sh_repo}/releases/latest/download/code.tar.gz 170 | name="$is_core_name 脚本" 171 | tmpfile=$tmpsh 172 | is_ok=$is_sh_ok 173 | ;; 174 | jq) 175 | link=https://github.com/jqlang/jq/releases/download/jq-1.7.1/jq-linux-$is_arch 176 | name="jq" 177 | tmpfile=$tmpjq 178 | is_ok=$is_jq_ok 179 | ;; 180 | esac 181 | 182 | [[ $link ]] && { 183 | msg warn "下载 ${name} > ${link}" 184 | if _wget -t 3 -q -c $link -O $tmpfile; then 185 | mv -f $tmpfile $is_ok 186 | fi 187 | } 188 | } 189 | 190 | # get server ip 191 | get_ip() { 192 | export "$(_wget -4 -qO- https://one.one.one.one/cdn-cgi/trace | grep ip=)" &>/dev/null 193 | [[ -z $ip ]] && export "$(_wget -6 -qO- https://one.one.one.one/cdn-cgi/trace | grep ip=)" &>/dev/null 194 | } 195 | 196 | # check background tasks status 197 | check_status() { 198 | # dependent pkg install fail 199 | [[ ! -f $is_pkg_ok ]] && { 200 | msg err "安装依赖包失败" 201 | msg err "请尝试手动安装依赖包: $cmd update -y; $cmd install -y $is_pkg" 202 | is_fail=1 203 | } 204 | 205 | # download file status 206 | if [[ $is_wget ]]; then 207 | [[ ! -f $is_core_ok ]] && { 208 | msg err "下载 ${is_core_name} 失败" 209 | is_fail=1 210 | } 211 | [[ ! -f $is_sh_ok ]] && { 212 | msg err "下载 ${is_core_name} 脚本失败" 213 | is_fail=1 214 | } 215 | [[ ! -f $is_jq_ok ]] && { 216 | msg err "下载 jq 失败" 217 | is_fail=1 218 | } 219 | else 220 | [[ ! $is_fail ]] && { 221 | is_wget=1 222 | [[ ! $is_core_file ]] && download core & 223 | [[ ! $local_install ]] && download sh & 224 | [[ $jq_not_found ]] && download jq & 225 | get_ip 226 | wait 227 | check_status 228 | } 229 | fi 230 | 231 | # found fail status, remove tmp dir and exit. 232 | [[ $is_fail ]] && { 233 | exit_and_del_tmpdir 234 | } 235 | } 236 | 237 | # parameters check 238 | pass_args() { 239 | while [[ $# -gt 0 ]]; do 240 | case $1 in 241 | -f | --core-file) 242 | [[ -z $2 ]] && { 243 | err "($1) 缺少必需参数, 正确使用示例: [$1 /root/$is_core-linux-amd64.tar.gz]" 244 | } || [[ ! -f $2 ]] && { 245 | err "($2) 不是一个常规的文件." 246 | } 247 | is_core_file=$2 248 | shift 2 249 | ;; 250 | -l | --local-install) 251 | [[ ! -f ${PWD}/src/core.sh || ! -f ${PWD}/$is_core.sh ]] && { 252 | err "当前目录 (${PWD}) 非完整的脚本目录." 253 | } 254 | local_install=1 255 | shift 1 256 | ;; 257 | -p | --proxy) 258 | [[ -z $2 ]] && { 259 | err "($1) 缺少必需参数, 正确使用示例: [$1 http://127.0.0.1:2333 or -p socks5://127.0.0.1:2333]" 260 | } 261 | proxy=$2 262 | shift 2 263 | ;; 264 | -v | --core-version) 265 | [[ -z $2 ]] && { 266 | err "($1) 缺少必需参数, 正确使用示例: [$1 v1.8.13]" 267 | } 268 | is_core_ver=v${2//v/} 269 | shift 2 270 | ;; 271 | -h | --help) 272 | show_help 273 | ;; 274 | *) 275 | echo -e "\n${is_err} ($@) 为未知参数...\n" 276 | show_help 277 | ;; 278 | esac 279 | done 280 | [[ $is_core_ver && $is_core_file ]] && { 281 | err "无法同时自定义 ${is_core_name} 版本和 ${is_core_name} 文件." 282 | } 283 | } 284 | 285 | # exit and remove tmpdir 286 | exit_and_del_tmpdir() { 287 | rm -rf $tmpdir 288 | [[ ! $1 ]] && { 289 | msg err "哦豁.." 290 | msg err "安装过程出现错误..." 291 | echo -e "反馈问题) https://github.com/${is_sh_repo}/issues" 292 | echo 293 | exit 1 294 | } 295 | exit 296 | } 297 | 298 | # main 299 | main() { 300 | 301 | # check old version 302 | [[ -f $is_sh_bin && -d $is_core_dir/bin && -d $is_sh_dir && -d $is_conf_dir ]] && { 303 | err "检测到脚本已安装, 如需重装请使用${green} ${is_core} reinstall ${none}命令." 304 | } 305 | 306 | # check parameters 307 | [[ $# -gt 0 ]] && pass_args $@ 308 | 309 | # show welcome msg 310 | clear 311 | echo 312 | echo "........... $is_core_name script by $author .........." 313 | echo 314 | 315 | # start installing... 316 | msg warn "开始安装..." 317 | [[ $is_core_ver ]] && msg warn "${is_core_name} 版本: ${yellow}$is_core_ver${none}" 318 | [[ $proxy ]] && msg warn "使用代理: ${yellow}$proxy${none}" 319 | # create tmpdir 320 | mkdir -p $tmpdir 321 | # if is_core_file, copy file 322 | [[ $is_core_file ]] && { 323 | cp -f $is_core_file $is_core_ok 324 | msg warn "${yellow}${is_core_name} 文件使用 > $is_core_file${none}" 325 | } 326 | # local dir install sh script 327 | [[ $local_install ]] && { 328 | >$is_sh_ok 329 | msg warn "${yellow}本地获取安装脚本 > $PWD ${none}" 330 | } 331 | 332 | timedatectl set-ntp true &>/dev/null 333 | [[ $? != 0 ]] && { 334 | is_ntp_on=1 335 | } 336 | 337 | # install dependent pkg 338 | install_pkg $is_pkg & 339 | 340 | # jq 341 | if [[ $(type -P jq) ]]; then 342 | >$is_jq_ok 343 | else 344 | jq_not_found=1 345 | fi 346 | # if wget installed. download core, sh, jq, get ip 347 | [[ $is_wget ]] && { 348 | [[ ! $is_core_file ]] && download core & 349 | [[ ! $local_install ]] && download sh & 350 | [[ $jq_not_found ]] && download jq & 351 | get_ip 352 | } 353 | 354 | # waiting for background tasks is done 355 | wait 356 | 357 | # check background tasks status 358 | check_status 359 | 360 | # test $is_core_file 361 | if [[ $is_core_file ]]; then 362 | mkdir -p $tmpdir/testzip 363 | tar zxf $is_core_ok --strip-components 1 -C $tmpdir/testzip &>/dev/null 364 | [[ $? != 0 ]] && { 365 | msg err "${is_core_name} 文件无法通过测试." 366 | exit_and_del_tmpdir 367 | } 368 | [[ ! -f $tmpdir/testzip/$is_core ]] && { 369 | msg err "${is_core_name} 文件无法通过测试." 370 | exit_and_del_tmpdir 371 | } 372 | fi 373 | 374 | # get server ip. 375 | [[ ! $ip ]] && { 376 | msg err "获取服务器 IP 失败." 377 | exit_and_del_tmpdir 378 | } 379 | 380 | # create sh dir... 381 | mkdir -p $is_sh_dir 382 | 383 | # copy sh file or unzip sh zip file. 384 | if [[ $local_install ]]; then 385 | cp -rf $PWD/* $is_sh_dir 386 | else 387 | tar zxf $is_sh_ok -C $is_sh_dir 388 | fi 389 | 390 | # create core bin dir 391 | mkdir -p $is_core_dir/bin 392 | # copy core file or unzip core zip file 393 | if [[ $is_core_file ]]; then 394 | cp -rf $tmpdir/testzip/* $is_core_dir/bin 395 | else 396 | tar zxf $is_core_ok --strip-components 1 -C $is_core_dir/bin 397 | fi 398 | 399 | # add alias 400 | echo "alias sb=$is_sh_bin" >>/root/.bashrc 401 | echo "alias $is_core=$is_sh_bin" >>/root/.bashrc 402 | 403 | # core command 404 | ln -sf $is_sh_dir/$is_core.sh $is_sh_bin 405 | ln -sf $is_sh_dir/$is_core.sh ${is_sh_bin/$is_core/sb} 406 | 407 | # jq 408 | [[ $jq_not_found ]] && mv -f $is_jq_ok /usr/bin/jq 409 | 410 | # chmod 411 | chmod +x $is_core_bin $is_sh_bin /usr/bin/jq ${is_sh_bin/$is_core/sb} 412 | 413 | # create log dir 414 | mkdir -p $is_log_dir 415 | 416 | # show a tips msg 417 | msg ok "生成配置文件..." 418 | 419 | # create systemd service 420 | load systemd.sh 421 | is_new_install=1 422 | install_service $is_core &>/dev/null 423 | 424 | # create condf dir 425 | mkdir -p $is_conf_dir 426 | 427 | load core.sh 428 | # create a reality config 429 | add reality 430 | # remove tmp dir and exit. 431 | exit_and_del_tmpdir ok 432 | } 433 | 434 | # start. 435 | main $@ 436 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /src/core.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | protocol_list=( 4 | TUIC 5 | Trojan 6 | Hysteria2 7 | VMess-WS 8 | VMess-TCP 9 | VMess-HTTP 10 | VMess-QUIC 11 | Shadowsocks 12 | VMess-H2-TLS 13 | VMess-WS-TLS 14 | VLESS-H2-TLS 15 | VLESS-WS-TLS 16 | Trojan-H2-TLS 17 | Trojan-WS-TLS 18 | VMess-HTTPUpgrade-TLS 19 | VLESS-HTTPUpgrade-TLS 20 | Trojan-HTTPUpgrade-TLS 21 | VLESS-REALITY 22 | VLESS-HTTP2-REALITY 23 | # Direct 24 | Socks 25 | ) 26 | ss_method_list=( 27 | aes-128-gcm 28 | aes-256-gcm 29 | chacha20-ietf-poly1305 30 | xchacha20-ietf-poly1305 31 | 2022-blake3-aes-128-gcm 32 | 2022-blake3-aes-256-gcm 33 | 2022-blake3-chacha20-poly1305 34 | ) 35 | mainmenu=( 36 | "添加配置" 37 | "更改配置" 38 | "查看配置" 39 | "删除配置" 40 | "运行管理" 41 | "更新" 42 | "卸载" 43 | "帮助" 44 | "其他" 45 | "关于" 46 | ) 47 | info_list=( 48 | "协议 (protocol)" 49 | "地址 (address)" 50 | "端口 (port)" 51 | "用户ID (id)" 52 | "传输协议 (network)" 53 | "伪装类型 (type)" 54 | "伪装域名 (host)" 55 | "路径 (path)" 56 | "传输层安全 (TLS)" 57 | "应用层协议协商 (Alpn)" 58 | "密码 (password)" 59 | "加密方式 (encryption)" 60 | "链接 (URL)" 61 | "目标地址 (remote addr)" 62 | "目标端口 (remote port)" 63 | "流控 (flow)" 64 | "SNI (serverName)" 65 | "指纹 (Fingerprint)" 66 | "公钥 (Public key)" 67 | "用户名 (Username)" 68 | "跳过证书验证 (allowInsecure)" 69 | "拥塞控制算法 (congestion_control)" 70 | ) 71 | change_list=( 72 | "更改协议" 73 | "更改端口" 74 | "更改域名" 75 | "更改路径" 76 | "更改密码" 77 | "更改 UUID" 78 | "更改加密方式" 79 | "更改目标地址" 80 | "更改目标端口" 81 | "更改密钥" 82 | "更改 SNI (serverName)" 83 | "更改伪装网站" 84 | "更改用户名 (Username)" 85 | ) 86 | servername_list=( 87 | www.amazon.com 88 | www.ebay.com 89 | www.paypal.com 90 | www.cloudflare.com 91 | dash.cloudflare.com 92 | aws.amazon.com 93 | ) 94 | 95 | is_random_ss_method=${ss_method_list[$(shuf -i 4-6 -n1)]} # random only use ss2022 96 | is_random_servername=${servername_list[$(shuf -i 0-${#servername_list[@]} -n1) - 1]} 97 | 98 | msg() { 99 | echo -e "$@" 100 | } 101 | 102 | msg_ul() { 103 | echo -e "\e[4m$@\e[0m" 104 | } 105 | 106 | # pause 107 | pause() { 108 | echo 109 | echo -ne "按 $(_green Enter 回车键) 继续, 或按 $(_red Ctrl + C) 取消." 110 | read -rs -d $'\n' 111 | echo 112 | } 113 | 114 | get_uuid() { 115 | tmp_uuid=$(cat /proc/sys/kernel/random/uuid) 116 | } 117 | 118 | get_ip() { 119 | [[ $ip || $is_no_auto_tls || $is_gen || $is_dont_get_ip ]] && return 120 | export "$(_wget -4 -qO- https://one.one.one.one/cdn-cgi/trace | grep ip=)" &>/dev/null 121 | [[ ! $ip ]] && export "$(_wget -6 -qO- https://one.one.one.one/cdn-cgi/trace | grep ip=)" &>/dev/null 122 | [[ ! $ip ]] && { 123 | err "获取服务器 IP 失败.." 124 | } 125 | } 126 | 127 | get_port() { 128 | is_count=0 129 | while :; do 130 | ((is_count++)) 131 | if [[ $is_count -ge 233 ]]; then 132 | err "自动获取可用端口失败次数达到 233 次, 请检查端口占用情况." 133 | fi 134 | tmp_port=$(shuf -i 445-65535 -n 1) 135 | [[ ! $(is_test port_used $tmp_port) && $tmp_port != $port ]] && break 136 | done 137 | } 138 | 139 | get_pbk() { 140 | is_tmp_pbk=($($is_core_bin generate reality-keypair | sed 's/.*://')) 141 | is_public_key=${is_tmp_pbk[1]} 142 | is_private_key=${is_tmp_pbk[0]} 143 | } 144 | 145 | show_list() { 146 | PS3='' 147 | COLUMNS=1 148 | select i in "$@"; do echo; done & 149 | wait 150 | # i=0 151 | # for v in "$@"; do 152 | # ((i++)) 153 | # echo "$i) $v" 154 | # done 155 | # echo 156 | 157 | } 158 | 159 | is_test() { 160 | case $1 in 161 | number) 162 | echo $2 | grep -E '^[1-9][0-9]?+$' 163 | ;; 164 | port) 165 | if [[ $(is_test number $2) ]]; then 166 | [[ $2 -le 65535 ]] && echo ok 167 | fi 168 | ;; 169 | port_used) 170 | [[ $(is_port_used $2) && ! $is_cant_test_port ]] && echo ok 171 | ;; 172 | domain) 173 | echo $2 | grep -E -i '^\w(\w|\-|\.)?+\.\w+$' 174 | ;; 175 | path) 176 | echo $2 | grep -E -i '^\/\w(\w|\-|\/)?+\w$' 177 | ;; 178 | uuid) 179 | echo $2 | grep -E -i '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}' 180 | ;; 181 | esac 182 | 183 | } 184 | 185 | is_port_used() { 186 | if [[ $(type -P netstat) ]]; then 187 | [[ ! $is_used_port ]] && is_used_port="$(netstat -tunlp | sed -n 's/.*:\([0-9]\+\).*/\1/p' | sort -nu)" 188 | echo $is_used_port | sed 's/ /\n/g' | grep ^${1}$ 189 | return 190 | fi 191 | if [[ $(type -P ss) ]]; then 192 | [[ ! $is_used_port ]] && is_used_port="$(ss -tunlp | sed -n 's/.*:\([0-9]\+\).*/\1/p' | sort -nu)" 193 | echo $is_used_port | sed 's/ /\n/g' | grep ^${1}$ 194 | return 195 | fi 196 | is_cant_test_port=1 197 | msg "$is_warn 无法检测端口是否可用." 198 | msg "请执行: $(_yellow "${cmd} update -y; ${cmd} install net-tools -y") 来修复此问题." 199 | } 200 | 201 | # ask input a string or pick a option for list. 202 | ask() { 203 | case $1 in 204 | set_ss_method) 205 | is_tmp_list=(${ss_method_list[@]}) 206 | is_default_arg=$is_random_ss_method 207 | is_opt_msg="\n请选择加密方式:\n" 208 | is_opt_input_msg="(默认\e[92m $is_default_arg\e[0m):" 209 | is_ask_set=ss_method 210 | ;; 211 | set_protocol) 212 | is_tmp_list=(${protocol_list[@]}) 213 | [[ $is_no_auto_tls ]] && { 214 | unset is_tmp_list 215 | for v in ${protocol_list[@]}; do 216 | [[ $(grep -i tls$ <<<$v) ]] && is_tmp_list=(${is_tmp_list[@]} $v) 217 | done 218 | } 219 | is_opt_msg="\n请选择协议:\n" 220 | is_ask_set=is_new_protocol 221 | ;; 222 | set_change_list) 223 | is_tmp_list=() 224 | for v in ${is_can_change[@]}; do 225 | is_tmp_list+=("${change_list[$v]}") 226 | done 227 | is_opt_msg="\n请选择更改:\n" 228 | is_ask_set=is_change_str 229 | is_opt_input_msg=$3 230 | ;; 231 | string) 232 | is_ask_set=$2 233 | is_opt_input_msg=$3 234 | ;; 235 | list) 236 | is_ask_set=$2 237 | [[ ! $is_tmp_list ]] && is_tmp_list=($3) 238 | is_opt_msg=$4 239 | is_opt_input_msg=$5 240 | ;; 241 | get_config_file) 242 | is_tmp_list=("${is_all_json[@]}") 243 | is_opt_msg="\n请选择配置:\n" 244 | is_ask_set=is_config_file 245 | ;; 246 | mainmenu) 247 | is_tmp_list=("${mainmenu[@]}") 248 | is_ask_set=is_main_pick 249 | is_emtpy_exit=1 250 | ;; 251 | esac 252 | msg $is_opt_msg 253 | [[ ! $is_opt_input_msg ]] && is_opt_input_msg="请选择 [\e[91m1-${#is_tmp_list[@]}\e[0m]:" 254 | [[ $is_tmp_list ]] && show_list "${is_tmp_list[@]}" 255 | while :; do 256 | echo -ne $is_opt_input_msg 257 | read REPLY 258 | [[ ! $REPLY && $is_emtpy_exit ]] && exit 259 | [[ ! $REPLY && $is_default_arg ]] && export $is_ask_set=$is_default_arg && break 260 | [[ "$REPLY" == "${is_str}2${is_get}3${is_opt}3" && $is_ask_set == 'is_main_pick' ]] && { 261 | msg "\n${is_get}2${is_str}3${is_msg}3b${is_tmp}o${is_opt}y\n" && exit 262 | } 263 | if [[ ! $is_tmp_list ]]; then 264 | [[ $(grep port <<<$is_ask_set) ]] && { 265 | [[ ! $(is_test port "$REPLY") ]] && { 266 | msg "$is_err 请输入正确的端口, 可选(1-65535)" 267 | continue 268 | } 269 | if [[ $(is_test port_used $REPLY) && $is_ask_set != 'door_port' ]]; then 270 | msg "$is_err 无法使用 ($REPLY) 端口." 271 | continue 272 | fi 273 | } 274 | [[ $(grep path <<<$is_ask_set) && ! $(is_test path "$REPLY") ]] && { 275 | [[ ! $tmp_uuid ]] && get_uuid 276 | msg "$is_err 请输入正确的路径, 例如: /$tmp_uuid" 277 | continue 278 | } 279 | [[ $(grep uuid <<<$is_ask_set) && ! $(is_test uuid "$REPLY") ]] && { 280 | [[ ! $tmp_uuid ]] && get_uuid 281 | msg "$is_err 请输入正确的 UUID, 例如: $tmp_uuid" 282 | continue 283 | } 284 | [[ $(grep ^y$ <<<$is_ask_set) ]] && { 285 | [[ $(grep -i ^y$ <<<"$REPLY") ]] && break 286 | msg "请输入 (y)" 287 | continue 288 | } 289 | [[ $REPLY ]] && export $is_ask_set=$REPLY && msg "使用: ${!is_ask_set}" && break 290 | else 291 | [[ $(is_test number "$REPLY") ]] && is_ask_result=${is_tmp_list[$REPLY - 1]} 292 | [[ $is_ask_result ]] && export $is_ask_set="$is_ask_result" && msg "选择: ${!is_ask_set}" && break 293 | fi 294 | 295 | msg "输入${is_err}" 296 | done 297 | unset is_opt_msg is_opt_input_msg is_tmp_list is_ask_result is_default_arg is_emtpy_exit 298 | } 299 | 300 | # create file 301 | create() { 302 | case $1 in 303 | server) 304 | is_tls=none 305 | get new 306 | # listen 307 | is_listen='listen: "::"' 308 | # file name 309 | if [[ $host ]]; then 310 | is_config_name=$2-${host}.json 311 | is_listen='listen: "127.0.0.1"' 312 | else 313 | is_config_name=$2-${port}.json 314 | fi 315 | is_json_file=$is_conf_dir/$is_config_name 316 | # get json 317 | [[ $is_change || ! $json_str ]] && get protocol $2 318 | [[ $net == "reality" ]] && is_add_public_key=",outbounds:[{type:\"direct\"},{tag:\"public_key_$is_public_key\",type:\"direct\"}]" 319 | is_new_json=$(jq "{inbounds:[{tag:\"$is_config_name\",type:\"$is_protocol\",$is_listen,listen_port:$port,$json_str}]$is_add_public_key}" <<<{}) 320 | [[ $is_test_json ]] && return # tmp test 321 | # only show json, dont save to file. 322 | [[ $is_gen ]] && { 323 | msg 324 | jq <<<$is_new_json 325 | msg 326 | return 327 | } 328 | # del old file 329 | [[ $is_config_file ]] && is_no_del_msg=1 && del $is_config_file 330 | # save json to file 331 | cat <<<$is_new_json >$is_json_file 332 | if [[ $is_new_install ]]; then 333 | # config.json 334 | create config.json 335 | fi 336 | # caddy auto tls 337 | [[ $is_caddy && $host && ! $is_no_auto_tls ]] && { 338 | create caddy $net 339 | } 340 | # restart core 341 | manage restart & 342 | ;; 343 | client) 344 | is_tls=tls 345 | is_client=1 346 | get info $2 347 | [[ ! $is_client_id_json ]] && err "($is_config_name) 不支持生成客户端配置." 348 | is_new_json=$(jq '{outbounds:[{tag:'\"$is_config_name\"',protocol:'\"$is_protocol\"','"$is_client_id_json"','"$is_stream"'}]}' <<<{}) 349 | msg 350 | jq <<<$is_new_json 351 | msg 352 | ;; 353 | caddy) 354 | load caddy.sh 355 | [[ $is_install_caddy ]] && caddy_config new 356 | [[ ! $(grep "$is_caddy_conf" $is_caddyfile) ]] && { 357 | msg "import $is_caddy_conf/*.conf" >>$is_caddyfile 358 | } 359 | [[ ! -d $is_caddy_conf ]] && mkdir -p $is_caddy_conf 360 | caddy_config $2 361 | manage restart caddy & 362 | ;; 363 | config.json) 364 | is_log='log:{output:"/var/log/'$is_core'/access.log",level:"info","timestamp":true}' 365 | is_dns='dns:{}' 366 | is_ntp='ntp:{"enabled":true,"server":"time.apple.com"},' 367 | if [[ -f $is_config_json ]]; then 368 | [[ $(jq .ntp.enabled $is_config_json) != "true" ]] && is_ntp= 369 | else 370 | [[ ! $is_ntp_on ]] && is_ntp= 371 | fi 372 | is_outbounds='outbounds:[{tag:"direct",type:"direct"}]' 373 | is_server_config_json=$(jq "{$is_log,$is_dns,$is_ntp$is_outbounds}" <<<{}) 374 | cat <<<$is_server_config_json >$is_config_json 375 | manage restart & 376 | ;; 377 | esac 378 | } 379 | 380 | # change config file 381 | change() { 382 | is_change=1 383 | is_dont_show_info=1 384 | if [[ $2 ]]; then 385 | case ${2,,} in 386 | full) 387 | is_change_id=full 388 | ;; 389 | new) 390 | is_change_id=0 391 | ;; 392 | port) 393 | is_change_id=1 394 | ;; 395 | host) 396 | is_change_id=2 397 | ;; 398 | path) 399 | is_change_id=3 400 | ;; 401 | pass | passwd | password) 402 | is_change_id=4 403 | ;; 404 | id | uuid) 405 | is_change_id=5 406 | ;; 407 | ssm | method | ss-method | ss_method) 408 | is_change_id=6 409 | ;; 410 | dda | door-addr | door_addr) 411 | is_change_id=7 412 | ;; 413 | ddp | door-port | door_port) 414 | is_change_id=8 415 | ;; 416 | key | publickey | privatekey) 417 | is_change_id=9 418 | ;; 419 | sni | servername | servernames) 420 | is_change_id=10 421 | ;; 422 | web | proxy-site) 423 | is_change_id=11 424 | ;; 425 | *) 426 | [[ $is_try_change ]] && return 427 | err "无法识别 ($2) 更改类型." 428 | ;; 429 | esac 430 | fi 431 | [[ $is_try_change ]] && return 432 | [[ $is_dont_auto_exit ]] && { 433 | get info $1 434 | } || { 435 | [[ $is_change_id ]] && { 436 | is_change_msg=${change_list[$is_change_id]} 437 | [[ $is_change_id == 'full' ]] && { 438 | [[ $3 ]] && is_change_msg="更改多个参数" || is_change_msg= 439 | } 440 | [[ $is_change_msg ]] && _green "\n快速执行: $is_change_msg" 441 | } 442 | info $1 443 | [[ $is_auto_get_config ]] && msg "\n自动选择: $is_config_file" 444 | } 445 | is_old_net=$net 446 | [[ $is_tcp_http ]] && net=http 447 | [[ $host ]] && net=$is_protocol-$net-tls 448 | [[ $is_reality && $net_type =~ 'http' ]] && net=rh2 449 | 450 | [[ $3 == 'auto' ]] && is_auto=1 451 | # if is_dont_show_info exist, cant show info. 452 | is_dont_show_info= 453 | # if not prefer args, show change list and then get change id. 454 | [[ ! $is_change_id ]] && { 455 | ask set_change_list 456 | is_change_id=${is_can_change[$REPLY - 1]} 457 | } 458 | case $is_change_id in 459 | full) 460 | add $net ${@:3} 461 | ;; 462 | 0) 463 | # new protocol 464 | is_set_new_protocol=1 465 | add ${@:3} 466 | ;; 467 | 1) 468 | # new port 469 | is_new_port=$3 470 | [[ $host && ! $is_caddy || $is_no_auto_tls ]] && err "($is_config_file) 不支持更改端口, 因为没啥意义." 471 | if [[ $is_new_port && ! $is_auto ]]; then 472 | [[ ! $(is_test port $is_new_port) ]] && err "请输入正确的端口, 可选(1-65535)" 473 | [[ $is_new_port != 443 && $(is_test port_used $is_new_port) ]] && err "无法使用 ($is_new_port) 端口" 474 | fi 475 | [[ $is_auto ]] && get_port && is_new_port=$tmp_port 476 | [[ ! $is_new_port ]] && ask string is_new_port "请输入新端口:" 477 | if [[ $is_caddy && $host ]]; then 478 | net=$is_old_net 479 | is_https_port=$is_new_port 480 | load caddy.sh 481 | caddy_config $net 482 | manage restart caddy & 483 | info 484 | else 485 | add $net $is_new_port 486 | fi 487 | ;; 488 | 2) 489 | # new host 490 | is_new_host=$3 491 | [[ ! $host ]] && err "($is_config_file) 不支持更改域名." 492 | [[ ! $is_new_host ]] && ask string is_new_host "请输入新域名:" 493 | old_host=$host # del old host 494 | add $net $is_new_host 495 | ;; 496 | 3) 497 | # new path 498 | is_new_path=$3 499 | [[ ! $path ]] && err "($is_config_file) 不支持更改路径." 500 | [[ $is_auto ]] && get_uuid && is_new_path=/$tmp_uuid 501 | [[ ! $is_new_path ]] && ask string is_new_path "请输入新路径:" 502 | add $net auto auto $is_new_path 503 | ;; 504 | 4) 505 | # new password 506 | is_new_pass=$3 507 | if [[ $ss_password || $password ]]; then 508 | [[ $is_auto ]] && { 509 | get_uuid && is_new_pass=$tmp_uuid 510 | [[ $ss_password ]] && is_new_pass=$(get ss2022) 511 | } 512 | else 513 | err "($is_config_file) 不支持更改密码." 514 | fi 515 | [[ ! $is_new_pass ]] && ask string is_new_pass "请输入新密码:" 516 | password=$is_new_pass 517 | ss_password=$is_new_pass 518 | is_socks_pass=$is_new_pass 519 | add $net 520 | ;; 521 | 5) 522 | # new uuid 523 | is_new_uuid=$3 524 | [[ ! $uuid ]] && err "($is_config_file) 不支持更改 UUID." 525 | [[ $is_auto ]] && get_uuid && is_new_uuid=$tmp_uuid 526 | [[ ! $is_new_uuid ]] && ask string is_new_uuid "请输入新 UUID:" 527 | add $net auto $is_new_uuid 528 | ;; 529 | 6) 530 | # new method 531 | is_new_method=$3 532 | [[ $net != 'ss' ]] && err "($is_config_file) 不支持更改加密方式." 533 | [[ $is_auto ]] && is_new_method=$is_random_ss_method 534 | [[ ! $is_new_method ]] && { 535 | ask set_ss_method 536 | is_new_method=$ss_method 537 | } 538 | add $net auto auto $is_new_method 539 | ;; 540 | 7) 541 | # new remote addr 542 | is_new_door_addr=$3 543 | [[ $net != 'direct' ]] && err "($is_config_file) 不支持更改目标地址." 544 | [[ ! $is_new_door_addr ]] && ask string is_new_door_addr "请输入新的目标地址:" 545 | door_addr=$is_new_door_addr 546 | add $net 547 | ;; 548 | 8) 549 | # new remote port 550 | is_new_door_port=$3 551 | [[ $net != 'direct' ]] && err "($is_config_file) 不支持更改目标端口." 552 | [[ ! $is_new_door_port ]] && { 553 | ask string door_port "请输入新的目标端口:" 554 | is_new_door_port=$door_port 555 | } 556 | add $net auto auto $is_new_door_port 557 | ;; 558 | 9) 559 | # new is_private_key is_public_key 560 | is_new_private_key=$3 561 | is_new_public_key=$4 562 | [[ ! $is_reality ]] && err "($is_config_file) 不支持更改密钥." 563 | if [[ $is_auto ]]; then 564 | get_pbk 565 | add $net 566 | else 567 | [[ $is_new_private_key && ! $is_new_public_key ]] && { 568 | err "无法找到 Public key." 569 | } 570 | [[ ! $is_new_private_key ]] && ask string is_new_private_key "请输入新 Private key:" 571 | [[ ! $is_new_public_key ]] && ask string is_new_public_key "请输入新 Public key:" 572 | if [[ $is_new_private_key == $is_new_public_key ]]; then 573 | err "Private key 和 Public key 不能一样." 574 | fi 575 | is_tmp_json=$is_conf_dir/$is_config_file-$uuid 576 | cp -f $is_conf_dir/$is_config_file $is_tmp_json 577 | sed -i s#$is_private_key #$is_new_private_key# $is_tmp_json 578 | $is_core_bin check -c $is_tmp_json &>/dev/null 579 | if [[ $? != 0 ]]; then 580 | is_key_err=1 581 | is_key_err_msg="Private key 无法通过测试." 582 | fi 583 | sed -i s#$is_new_private_key #$is_new_public_key# $is_tmp_json 584 | $is_core_bin check -c $is_tmp_json &>/dev/null 585 | if [[ $? != 0 ]]; then 586 | is_key_err=1 587 | is_key_err_msg+="Public key 无法通过测试." 588 | fi 589 | rm $is_tmp_json 590 | [[ $is_key_err ]] && err $is_key_err_msg 591 | is_private_key=$is_new_private_key 592 | is_public_key=$is_new_public_key 593 | is_test_json= 594 | add $net 595 | fi 596 | ;; 597 | 10) 598 | # new serverName 599 | is_new_servername=$3 600 | [[ ! $is_reality ]] && err "($is_config_file) 不支持更改 serverName." 601 | [[ $is_auto ]] && is_new_servername=$is_random_servername 602 | [[ ! $is_new_servername ]] && ask string is_new_servername "请输入新的 serverName:" 603 | is_servername=$is_new_servername 604 | [[ $(grep -i "^233boy.com$" <<<$is_servername) ]] && { 605 | err "你干嘛~哎呦~" 606 | } 607 | add $net 608 | ;; 609 | 11) 610 | # new proxy site 611 | is_new_proxy_site=$3 612 | [[ ! $is_caddy && ! $host ]] && { 613 | err "($is_config_file) 不支持更改伪装网站." 614 | } 615 | [[ ! -f $is_caddy_conf/${host}.conf.add ]] && err "无法配置伪装网站." 616 | [[ ! $is_new_proxy_site ]] && ask string is_new_proxy_site "请输入新的伪装网站 (例如 example.com):" 617 | proxy_site=$(sed 's#^.*//##;s#/$##' <<<$is_new_proxy_site) 618 | [[ $(grep -i "^233boy.com$" <<<$proxy_site) ]] && { 619 | err "你干嘛~哎呦~" 620 | } || { 621 | load caddy.sh 622 | caddy_config proxy 623 | manage restart caddy & 624 | } 625 | msg "\n已更新伪装网站为: $(_green $proxy_site) \n" 626 | ;; 627 | 12) 628 | # new socks user 629 | [[ ! $is_socks_user ]] && err "($is_config_file) 不支持更改用户名 (Username)." 630 | ask string is_socks_user "请输入新用户名 (Username):" 631 | add $net 632 | ;; 633 | esac 634 | } 635 | 636 | # delete config. 637 | del() { 638 | # dont get ip 639 | is_dont_get_ip=1 640 | [[ $is_conf_dir_empty ]] && return # not found any json file. 641 | # get a config file 642 | [[ ! $is_config_file ]] && get info $1 643 | if [[ $is_config_file ]]; then 644 | if [[ $is_main_start && ! $is_no_del_msg ]]; then 645 | msg "\n是否删除配置文件?: $is_config_file" 646 | pause 647 | fi 648 | rm -rf $is_conf_dir/"$is_config_file" 649 | [[ ! $is_new_json ]] && manage restart & 650 | [[ ! $is_no_del_msg ]] && _green "\n已删除: $is_config_file\n" 651 | 652 | [[ $is_caddy ]] && { 653 | is_del_host=$host 654 | [[ $is_change ]] && { 655 | [[ ! $old_host ]] && return # no host exist or not set new host; 656 | is_del_host=$old_host 657 | } 658 | [[ $is_del_host && $host != $old_host && -f $is_caddy_conf/$is_del_host.conf ]] && { 659 | rm -rf $is_caddy_conf/$is_del_host.conf $is_caddy_conf/$is_del_host.conf.add 660 | [[ ! $is_new_json ]] && manage restart caddy & 661 | } 662 | } 663 | fi 664 | if [[ ! $(ls $is_conf_dir | grep .json) && ! $is_change ]]; then 665 | warn "当前配置目录为空! 因为你刚刚删除了最后一个配置文件." 666 | is_conf_dir_empty=1 667 | fi 668 | unset is_dont_get_ip 669 | [[ $is_dont_auto_exit ]] && unset is_config_file 670 | } 671 | 672 | # uninstall 673 | uninstall() { 674 | if [[ $is_caddy ]]; then 675 | is_tmp_list=("卸载 $is_core_name" "卸载 ${is_core_name} & Caddy") 676 | ask list is_do_uninstall 677 | else 678 | ask string y "是否卸载 ${is_core_name}? [y]:" 679 | fi 680 | manage stop &>/dev/null 681 | manage disable &>/dev/null 682 | rm -rf $is_core_dir $is_log_dir $is_sh_bin ${is_sh_bin/$is_core/sb} /lib/systemd/system/$is_core.service 683 | sed -i "/alias $is_core=/d" /root/.bashrc 684 | # uninstall caddy; 2 is ask result 685 | if [[ $REPLY == '2' ]]; then 686 | manage stop caddy &>/dev/null 687 | manage disable caddy &>/dev/null 688 | rm -rf $is_caddy_dir $is_caddy_bin /lib/systemd/system/caddy.service 689 | fi 690 | [[ $is_install_sh ]] && return # reinstall 691 | _green "\n卸载完成!" 692 | msg "脚本哪里需要完善? 请反馈" 693 | msg "反馈问题) $(msg_ul https://github.com/${is_sh_repo}/issues)\n" 694 | } 695 | 696 | # manage run status 697 | manage() { 698 | [[ $is_dont_auto_exit ]] && return 699 | case $1 in 700 | 1 | start) 701 | is_do=start 702 | is_do_msg=启动 703 | is_test_run=1 704 | ;; 705 | 2 | stop) 706 | is_do=stop 707 | is_do_msg=停止 708 | ;; 709 | 3 | r | restart) 710 | is_do=restart 711 | is_do_msg=重启 712 | is_test_run=1 713 | ;; 714 | *) 715 | is_do=$1 716 | is_do_msg=$1 717 | ;; 718 | esac 719 | case $2 in 720 | caddy) 721 | is_do_name=$2 722 | is_run_bin=$is_caddy_bin 723 | is_do_name_msg=Caddy 724 | ;; 725 | *) 726 | is_do_name=$is_core 727 | is_run_bin=$is_core_bin 728 | is_do_name_msg=$is_core_name 729 | ;; 730 | esac 731 | systemctl $is_do $is_do_name 732 | [[ $is_test_run && ! $is_new_install ]] && { 733 | sleep 2 734 | if [[ ! $(pgrep -f $is_run_bin) ]]; then 735 | is_run_fail=${is_do_name_msg,,} 736 | [[ ! $is_no_manage_msg ]] && { 737 | msg 738 | warn "($is_do_msg) $is_do_name_msg 失败" 739 | _yellow "检测到运行失败, 自动执行测试运行." 740 | get test-run 741 | _yellow "测试结束, 请按 Enter 退出." 742 | } 743 | fi 744 | } 745 | } 746 | 747 | # add a config 748 | add() { 749 | is_lower=${1,,} 750 | if [[ $is_lower ]]; then 751 | case $is_lower in 752 | ws | tcp | quic | http) 753 | is_new_protocol=VMess-${is_lower^^} 754 | ;; 755 | wss | h2 | hu | vws | vh2 | vhu | tws | th2 | thu) 756 | is_new_protocol=$(sed -E "s/^V/VLESS-/;s/^T/Trojan-/;/^(W|H)/{s/^/VMess-/};s/WSS/WS/;s/HU/HTTPUpgrade/" <<<${is_lower^^})-TLS 757 | ;; 758 | r | reality) 759 | is_new_protocol=VLESS-REALITY 760 | ;; 761 | rh2) 762 | is_new_protocol=VLESS-HTTP2-REALITY 763 | ;; 764 | ss) 765 | is_new_protocol=Shadowsocks 766 | ;; 767 | door | direct) 768 | is_new_protocol=Direct 769 | ;; 770 | tuic) 771 | is_new_protocol=TUIC 772 | ;; 773 | hy | hy2 | hysteria*) 774 | is_new_protocol=Hysteria2 775 | ;; 776 | trojan) 777 | is_new_protocol=Trojan 778 | ;; 779 | socks) 780 | is_new_protocol=Socks 781 | ;; 782 | *) 783 | for v in ${protocol_list[@]}; do 784 | [[ $(grep -E -i "^$is_lower$" <<<$v) ]] && is_new_protocol=$v && break 785 | done 786 | 787 | [[ ! $is_new_protocol ]] && err "无法识别 ($1), 请使用: $is_core add [protocol] [args... | auto]" 788 | ;; 789 | esac 790 | fi 791 | 792 | # no prefer protocol 793 | [[ ! $is_new_protocol ]] && ask set_protocol 794 | 795 | case ${is_new_protocol,,} in 796 | *-tls) 797 | is_use_tls=1 798 | is_use_host=$2 799 | is_use_uuid=$3 800 | is_use_path=$4 801 | is_add_opts="[host] [uuid] [/path]" 802 | ;; 803 | vmess* | tuic*) 804 | is_use_port=$2 805 | is_use_uuid=$3 806 | is_add_opts="[port] [uuid]" 807 | ;; 808 | trojan* | hysteria*) 809 | is_use_port=$2 810 | is_use_pass=$3 811 | is_add_opts="[port] [password]" 812 | ;; 813 | *reality*) 814 | is_reality=1 815 | is_use_port=$2 816 | is_use_uuid=$3 817 | is_use_servername=$4 818 | is_add_opts="[port] [uuid] [sni]" 819 | ;; 820 | shadowsocks) 821 | is_use_port=$2 822 | is_use_pass=$3 823 | is_use_method=$4 824 | is_add_opts="[port] [password] [method]" 825 | ;; 826 | direct) 827 | is_use_port=$2 828 | is_use_door_addr=$3 829 | is_use_door_port=$4 830 | is_add_opts="[port] [remote_addr] [remote_port]" 831 | ;; 832 | socks) 833 | is_socks=1 834 | is_use_port=$2 835 | is_use_socks_user=$3 836 | is_use_socks_pass=$4 837 | is_add_opts="[port] [username] [password]" 838 | ;; 839 | esac 840 | 841 | [[ $1 && ! $is_change ]] && { 842 | msg "\n使用协议: $is_new_protocol" 843 | # err msg tips 844 | is_err_tips="\n\n请使用: $(_green $is_core add $1 $is_add_opts) 来添加 $is_new_protocol 配置" 845 | } 846 | 847 | # remove old protocol args 848 | if [[ $is_set_new_protocol ]]; then 849 | case $is_old_net in 850 | h2 | ws | httpupgrade) 851 | old_host=$host 852 | [[ ! $is_use_tls ]] && unset host is_no_auto_tls 853 | ;; 854 | reality) 855 | net_type= 856 | [[ ! $(grep -i reality <<<$is_new_protocol) ]] && is_reality= 857 | ;; 858 | ss) 859 | [[ $(is_test uuid $ss_password) ]] && uuid=$ss_password 860 | ;; 861 | esac 862 | [[ ! $(is_test uuid $uuid) ]] && uuid= 863 | [[ $(is_test uuid $password) ]] && uuid=$password 864 | fi 865 | 866 | # no-auto-tls only use h2,ws,grpc 867 | if [[ $is_no_auto_tls && ! $is_use_tls ]]; then 868 | err "$is_new_protocol 不支持手动配置 tls." 869 | fi 870 | 871 | # prefer args. 872 | if [[ $2 ]]; then 873 | for v in is_use_port is_use_uuid is_use_host is_use_path is_use_pass is_use_method is_use_door_addr is_use_door_port; do 874 | [[ ${!v} == 'auto' ]] && unset $v 875 | done 876 | 877 | if [[ $is_use_port ]]; then 878 | [[ ! $(is_test port ${is_use_port}) ]] && { 879 | err "($is_use_port) 不是一个有效的端口. $is_err_tips" 880 | } 881 | [[ $(is_test port_used $is_use_port) && ! $is_gen ]] && { 882 | err "无法使用 ($is_use_port) 端口. $is_err_tips" 883 | } 884 | port=$is_use_port 885 | fi 886 | if [[ $is_use_door_port ]]; then 887 | [[ ! $(is_test port ${is_use_door_port}) ]] && { 888 | err "(${is_use_door_port}) 不是一个有效的目标端口. $is_err_tips" 889 | } 890 | door_port=$is_use_door_port 891 | fi 892 | if [[ $is_use_uuid ]]; then 893 | [[ ! $(is_test uuid $is_use_uuid) ]] && { 894 | err "($is_use_uuid) 不是一个有效的 UUID. $is_err_tips" 895 | } 896 | uuid=$is_use_uuid 897 | fi 898 | if [[ $is_use_path ]]; then 899 | [[ ! $(is_test path $is_use_path) ]] && { 900 | err "($is_use_path) 不是有效的路径. $is_err_tips" 901 | } 902 | path=$is_use_path 903 | fi 904 | if [[ $is_use_method ]]; then 905 | is_tmp_use_name=加密方式 906 | is_tmp_list=${ss_method_list[@]} 907 | for v in ${is_tmp_list[@]}; do 908 | [[ $(grep -E -i "^${is_use_method}$" <<<$v) ]] && is_tmp_use_type=$v && break 909 | done 910 | [[ ! ${is_tmp_use_type} ]] && { 911 | warn "(${is_use_method}) 不是一个可用的${is_tmp_use_name}." 912 | msg "${is_tmp_use_name}可用如下: " 913 | for v in ${is_tmp_list[@]}; do 914 | msg "\t\t$v" 915 | done 916 | msg "$is_err_tips\n" 917 | exit 1 918 | } 919 | ss_method=$is_tmp_use_type 920 | fi 921 | [[ $is_use_pass ]] && ss_password=$is_use_pass && password=$is_use_pass 922 | [[ $is_use_host ]] && host=$is_use_host 923 | [[ $is_use_door_addr ]] && door_addr=$is_use_door_addr 924 | [[ $is_use_servername ]] && is_servername=$is_use_servername 925 | [[ $is_use_socks_user ]] && is_socks_user=$is_use_socks_user 926 | [[ $is_use_socks_pass ]] && is_socks_pass=$is_use_socks_pass 927 | fi 928 | 929 | if [[ $is_use_tls ]]; then 930 | if [[ ! $is_no_auto_tls && ! $is_caddy && ! $is_gen && ! $is_dont_test_host ]]; then 931 | # test auto tls 932 | [[ $(is_test port_used 80) || $(is_test port_used 443) ]] && { 933 | get_port 934 | is_http_port=$tmp_port 935 | get_port 936 | is_https_port=$tmp_port 937 | warn "端口 (80 或 443) 已经被占用, 你也可以考虑使用 no-auto-tls" 938 | msg "\e[41m no-auto-tls 帮助(help)\e[0m: $(msg_ul https://233boy.com/$is_core/no-auto-tls/)\n" 939 | msg "\n Caddy 将使用非标准端口实现自动配置 TLS, HTTP:$is_http_port HTTPS:$is_https_port\n" 940 | msg "请确定是否继续???" 941 | pause 942 | } 943 | is_install_caddy=1 944 | fi 945 | # set host 946 | [[ ! $host ]] && ask string host "请输入域名:" 947 | # test host dns 948 | get host-test 949 | else 950 | # for main menu start, dont auto create args 951 | if [[ $is_main_start ]]; then 952 | 953 | # set port 954 | [[ ! $port ]] && ask string port "请输入端口:" 955 | 956 | case ${is_new_protocol,,} in 957 | socks) 958 | # set user 959 | [[ ! $is_socks_user ]] && ask string is_socks_user "请设置用户名:" 960 | # set password 961 | [[ ! $is_socks_pass ]] && ask string is_socks_pass "请设置密码:" 962 | ;; 963 | shadowsocks) 964 | # set method 965 | [[ ! $ss_method ]] && ask set_ss_method 966 | # set password 967 | [[ ! $ss_password ]] && ask string ss_password "请设置密码:" 968 | ;; 969 | esac 970 | 971 | fi 972 | fi 973 | 974 | # Dokodemo-Door 975 | if [[ $is_new_protocol == 'Direct' ]]; then 976 | # set remote addr 977 | [[ ! $door_addr ]] && ask string door_addr "请输入目标地址:" 978 | # set remote port 979 | [[ ! $door_port ]] && ask string door_port "请输入目标端口:" 980 | fi 981 | 982 | # Shadowsocks 2022 983 | if [[ $(grep 2022 <<<$ss_method) ]]; then 984 | # test ss2022 password 985 | [[ $ss_password ]] && { 986 | is_test_json=1 987 | create server Shadowsocks 988 | [[ ! $tmp_uuid ]] && get_uuid 989 | is_test_json_save=$is_conf_dir/tmp-test-$tmp_uuid 990 | cat <<<"$is_new_json" >$is_test_json_save 991 | $is_core_bin check -c $is_test_json_save &>/dev/null 992 | if [[ $? != 0 ]]; then 993 | warn "Shadowsocks 协议 ($ss_method) 不支持使用密码 ($(_red_bg $ss_password))\n\n你可以使用命令: $(_green $is_core ss2022) 生成支持的密码.\n\n脚本将自动创建可用密码:)" 994 | ss_password= 995 | # create new json. 996 | json_str= 997 | fi 998 | is_test_json= 999 | rm -f $is_test_json_save 1000 | } 1001 | 1002 | fi 1003 | 1004 | # install caddy 1005 | if [[ $is_install_caddy ]]; then 1006 | get install-caddy 1007 | fi 1008 | 1009 | # create json 1010 | create server $is_new_protocol 1011 | 1012 | # show config info. 1013 | info 1014 | } 1015 | 1016 | # get config info 1017 | # or somes required args 1018 | get() { 1019 | case $1 in 1020 | addr) 1021 | is_addr=$host 1022 | [[ ! $is_addr ]] && { 1023 | get_ip 1024 | is_addr=$ip 1025 | [[ $(grep ":" <<<$ip) ]] && is_addr="[$ip]" 1026 | } 1027 | ;; 1028 | new) 1029 | [[ ! $host ]] && get_ip 1030 | [[ ! $port ]] && get_port && port=$tmp_port 1031 | [[ ! $uuid ]] && get_uuid && uuid=$tmp_uuid 1032 | ;; 1033 | file) 1034 | is_file_str=$2 1035 | [[ ! $is_file_str ]] && is_file_str='.json$' 1036 | # is_all_json=("$(ls $is_conf_dir | grep -E $is_file_str)") 1037 | readarray -t is_all_json <<<"$(ls $is_conf_dir | grep -E -i "$is_file_str" | sed '/dynamic-port-.*-link/d' | head -233)" # limit max 233 lines for show. 1038 | [[ ! $is_all_json ]] && err "无法找到相关的配置文件: $2" 1039 | [[ ${#is_all_json[@]} -eq 1 ]] && is_config_file=$is_all_json && is_auto_get_config=1 1040 | [[ ! $is_config_file ]] && { 1041 | [[ $is_dont_auto_exit ]] && return 1042 | ask get_config_file 1043 | } 1044 | ;; 1045 | info) 1046 | get file $2 1047 | if [[ $is_config_file ]]; then 1048 | is_json_str=$(cat $is_conf_dir/"$is_config_file" | sed s#//.*##) 1049 | 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) 1050 | [[ $? != 0 ]] && err "无法读取此文件: $is_config_file" 1051 | 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) 1052 | [[ $is_debug ]] && msg "\n------------- debug: $is_config_file -------------" 1053 | i=0 1054 | for v in $(sed 's/""/null/g;s/"//g' <<<"$is_json_data"); do 1055 | ((i++)) 1056 | [[ $is_debug ]] && msg "$i-${is_up_var_set[$i]}: $v" 1057 | export ${is_up_var_set[$i]}="${v}" 1058 | done 1059 | for v in ${is_up_var_set[@]}; do 1060 | [[ ${!v} == 'null' ]] && unset $v 1061 | done 1062 | 1063 | if [[ $is_private_key ]]; then 1064 | is_reality=1 1065 | net_type+=reality 1066 | is_public_key=${is_public_key/public_key_/} 1067 | fi 1068 | is_socks_user=$username 1069 | is_socks_pass=$password 1070 | 1071 | is_config_name=$is_config_file 1072 | 1073 | if [[ $is_caddy && $host && -f $is_caddy_conf/$host.conf ]]; then 1074 | is_tmp_https_port=$(grep -E -o "$host:[1-9][0-9]?+" $is_caddy_conf/$host.conf | sed s/.*://) 1075 | fi 1076 | if [[ $host && ! -f $is_caddy_conf/$host.conf ]]; then 1077 | is_no_auto_tls=1 1078 | fi 1079 | [[ $is_tmp_https_port ]] && is_https_port=$is_tmp_https_port 1080 | [[ $is_client && $host ]] && port=$is_https_port 1081 | get protocol $is_protocol-$net_type 1082 | fi 1083 | ;; 1084 | protocol) 1085 | get addr # get host or server ip 1086 | is_lower=${2,,} 1087 | net= 1088 | is_users="users:[{uuid:\"$uuid\"}]" 1089 | is_tls_json='tls:{enabled:true,alpn:["h3"],key_path:"'$is_tls_key'",certificate_path:"'$is_tls_cer'"}' 1090 | case $is_lower in 1091 | vmess*) 1092 | is_protocol=vmess 1093 | [[ $is_lower =~ "tcp" || ! $net_type && $is_up_var_set ]] && net=tcp && json_str=$is_users 1094 | ;; 1095 | vless*) 1096 | is_protocol=vless 1097 | ;; 1098 | tuic*) 1099 | net=tuic 1100 | is_protocol=$net 1101 | [[ ! $password ]] && password=$uuid 1102 | is_users="users:[{uuid:\"$uuid\",password:\"$password\"}]" 1103 | json_str="$is_users,congestion_control:\"bbr\",$is_tls_json" 1104 | ;; 1105 | trojan*) 1106 | is_protocol=trojan 1107 | [[ ! $password ]] && password=$uuid 1108 | is_users="users:[{password:\"$password\"}]" 1109 | [[ ! $host ]] && { 1110 | net=trojan 1111 | json_str="$is_users,${is_tls_json/alpn\:\[\"h3\"\],/}" 1112 | } 1113 | ;; 1114 | hysteria2*) 1115 | net=hysteria2 1116 | is_protocol=$net 1117 | [[ ! $password ]] && password=$uuid 1118 | json_str="users:[{password:\"$password\"}],$is_tls_json" 1119 | ;; 1120 | shadowsocks*) 1121 | net=ss 1122 | is_protocol=shadowsocks 1123 | [[ ! $ss_method ]] && ss_method=$is_random_ss_method 1124 | [[ ! $ss_password ]] && { 1125 | ss_password=$uuid 1126 | [[ $(grep 2022 <<<$ss_method) ]] && ss_password=$(get ss2022) 1127 | } 1128 | json_str="method:\"$ss_method\",password:\"$ss_password\"" 1129 | ;; 1130 | direct*) 1131 | net=direct 1132 | is_protocol=$net 1133 | json_str="override_port:$door_port,override_address:\"$door_addr\"" 1134 | ;; 1135 | socks*) 1136 | net=socks 1137 | is_protocol=$net 1138 | [[ ! $is_socks_user ]] && is_socks_user=233boy 1139 | [[ ! $is_socks_pass ]] && is_socks_pass=$uuid 1140 | json_str="users:[{username: \"$is_socks_user\", password: \"$is_socks_pass\"}]" 1141 | ;; 1142 | *) 1143 | err "无法识别协议: $is_config_file" 1144 | ;; 1145 | esac 1146 | [[ $net ]] && return # if net exist, dont need more json args 1147 | [[ $host && $is_lower =~ "tls" ]] && { 1148 | [[ ! $path ]] && path="/$uuid" 1149 | is_path_host_json=",path:\"$path\",headers:{host:\"$host\"}" 1150 | } 1151 | case $is_lower in 1152 | *quic*) 1153 | net=quic 1154 | is_json_add="$is_tls_json,transport:{type:\"$net\"}" 1155 | ;; 1156 | *ws*) 1157 | net=ws 1158 | is_json_add="transport:{type:\"$net\"$is_path_host_json,early_data_header_name:\"Sec-WebSocket-Protocol\"}" 1159 | ;; 1160 | *reality*) 1161 | net=reality 1162 | [[ ! $is_servername ]] && is_servername=$is_random_servername 1163 | [[ ! $is_private_key ]] && get_pbk 1164 | 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:[\"\"]}}" 1165 | [[ $is_lower =~ "http" ]] && { 1166 | is_json_add="$is_json_add,transport:{type:\"http\"}" 1167 | } || { 1168 | is_users=${is_users/uuid/flow:\"xtls-rprx-vision\",uuid} 1169 | } 1170 | ;; 1171 | *http* | *h2*) 1172 | net=http 1173 | [[ $is_lower =~ "up" ]] && net=httpupgrade 1174 | is_json_add="transport:{type:\"$net\"$is_path_host_json}" 1175 | [[ $is_lower =~ "h2" || ! $is_lower =~ "httpupgrade" && $host ]] && { 1176 | net=h2 1177 | is_json_add="${is_tls_json/alpn\:\[\"h3\"\],/},$is_json_add" 1178 | } 1179 | ;; 1180 | *) 1181 | err "无法识别传输协议: $is_config_file" 1182 | ;; 1183 | esac 1184 | json_str="$is_users,$is_json_add" 1185 | ;; 1186 | host-test) # test host dns record; for auto *tls required. 1187 | [[ $is_no_auto_tls || $is_gen || $is_dont_test_host ]] && return 1188 | get_ip 1189 | get ping 1190 | if [[ ! $(grep $ip <<<$is_host_dns) ]]; then 1191 | msg "\n请将 ($(_red_bg $host)) 解析到 ($(_red_bg $ip))" 1192 | msg "\n如果使用 Cloudflare, 在 DNS 那; 关闭 (Proxy status / 代理状态), 即是 (DNS only / 仅限 DNS)" 1193 | ask string y "我已经确定解析 [y]:" 1194 | get ping 1195 | if [[ ! $(grep $ip <<<$is_host_dns) ]]; then 1196 | _cyan "\n测试结果: $is_host_dns" 1197 | err "域名 ($host) 没有解析到 ($ip)" 1198 | fi 1199 | fi 1200 | ;; 1201 | ssss | ss2022) 1202 | if [[ $(grep 128 <<<$ss_method) ]]; then 1203 | $is_core_bin generate rand 16 --base64 1204 | else 1205 | $is_core_bin generate rand 32 --base64 1206 | fi 1207 | ;; 1208 | ping) 1209 | # is_ip_type="-4" 1210 | # [[ $(grep ":" <<<$ip) ]] && is_ip_type="-6" 1211 | # is_host_dns=$(ping $host $is_ip_type -c 1 -W 2 | head -1) 1212 | is_dns_type="a" 1213 | [[ $(grep ":" <<<$ip) ]] && is_dns_type="aaaa" 1214 | is_host_dns=$(_wget -qO- --header="accept: application/dns-json" "https://one.one.one.one/dns-query?name=$host&type=$is_dns_type") 1215 | ;; 1216 | install-caddy) 1217 | _green "\n安装 Caddy 实现自动配置 TLS.\n" 1218 | load download.sh 1219 | download caddy 1220 | load systemd.sh 1221 | install_service caddy &>/dev/null 1222 | is_caddy=1 1223 | _green "安装 Caddy 成功.\n" 1224 | ;; 1225 | reinstall) 1226 | is_install_sh=$(cat $is_sh_dir/install.sh) 1227 | uninstall 1228 | bash <<<$is_install_sh 1229 | ;; 1230 | test-run) 1231 | systemctl list-units --full -all &>/dev/null 1232 | [[ $? != 0 ]] && { 1233 | _yellow "\n无法执行测试, 请检查 systemctl 状态.\n" 1234 | return 1235 | } 1236 | is_no_manage_msg=1 1237 | if [[ ! $(pgrep -f $is_core_bin) ]]; then 1238 | _yellow "\n测试运行 $is_core_name ..\n" 1239 | manage start &>/dev/null 1240 | if [[ $is_run_fail == $is_core ]]; then 1241 | _red "$is_core_name 运行失败信息:" 1242 | $is_core_bin run -c $is_config_json -C $is_conf_dir 1243 | else 1244 | _green "\n测试通过, 已启动 $is_core_name ..\n" 1245 | fi 1246 | else 1247 | _green "\n$is_core_name 正在运行, 跳过测试\n" 1248 | fi 1249 | if [[ $is_caddy ]]; then 1250 | if [[ ! $(pgrep -f $is_caddy_bin) ]]; then 1251 | _yellow "\n测试运行 Caddy ..\n" 1252 | manage start caddy &>/dev/null 1253 | if [[ $is_run_fail == 'caddy' ]]; then 1254 | _red "Caddy 运行失败信息:" 1255 | $is_caddy_bin run --config $is_caddyfile 1256 | else 1257 | _green "\n测试通过, 已启动 Caddy ..\n" 1258 | fi 1259 | else 1260 | _green "\nCaddy 正在运行, 跳过测试\n" 1261 | fi 1262 | fi 1263 | ;; 1264 | esac 1265 | } 1266 | 1267 | # show info 1268 | info() { 1269 | if [[ ! $is_protocol ]]; then 1270 | get info $1 1271 | fi 1272 | # is_color=$(shuf -i 41-45 -n1) 1273 | is_color=44 1274 | case $net in 1275 | ws | tcp | h2 | quic | http*) 1276 | if [[ $host ]]; then 1277 | is_color=45 1278 | is_can_change=(0 1 2 3 5) 1279 | is_info_show=(0 1 2 3 4 6 7 8) 1280 | [[ $is_protocol == 'vmess' ]] && { 1281 | 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\"'}' <<<{}) 1282 | is_url=vmess://$(echo -n $is_vmess_url | base64 -w 0) 1283 | } || { 1284 | [[ $is_protocol == "trojan" ]] && { 1285 | uuid=$password 1286 | # is_info_str=($is_protocol $is_addr $is_https_port $password $net $host $path 'tls') 1287 | is_can_change=(0 1 2 3 4) 1288 | is_info_show=(0 1 2 10 4 6 7 8) 1289 | } 1290 | is_url="$is_protocol://$uuid@$host:$is_https_port?encryption=none&security=tls&type=$net&host=$host&path=$path#233boy-$net-$host" 1291 | } 1292 | [[ $is_caddy ]] && is_can_change+=(11) 1293 | is_info_str=($is_protocol $is_addr $is_https_port $uuid $net $host $path 'tls') 1294 | else 1295 | is_type=none 1296 | is_can_change=(0 1 5) 1297 | is_info_show=(0 1 2 3 4) 1298 | is_info_str=($is_protocol $is_addr $port $uuid $net) 1299 | [[ $net == "http" ]] && { 1300 | net=tcp 1301 | is_type=http 1302 | is_tcp_http=1 1303 | is_info_show+=(5) 1304 | is_info_str=(${is_info_str[@]/http/tcp http}) 1305 | } 1306 | [[ $net == "quic" ]] && { 1307 | is_insecure=1 1308 | is_info_show+=(8 9 20) 1309 | is_info_str+=(tls h3 true) 1310 | is_quic_add=",tls:\"tls\",alpn:\"h3\"" # cant add allowInsecure 1311 | } 1312 | 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}" <<<{}) 1313 | is_url=vmess://$(echo -n $is_vmess_url | base64 -w 0) 1314 | fi 1315 | ;; 1316 | ss) 1317 | is_can_change=(0 1 4 6) 1318 | is_info_show=(0 1 2 10 11) 1319 | is_url="ss://$(echo -n ${ss_method}:${ss_password} | base64 -w 0)@${is_addr}:${port}#233boy-$net-${is_addr}" 1320 | is_info_str=($is_protocol $is_addr $port $ss_password $ss_method) 1321 | ;; 1322 | trojan) 1323 | is_insecure=1 1324 | is_can_change=(0 1 4) 1325 | is_info_show=(0 1 2 10 4 8 20) 1326 | is_url="$is_protocol://$password@$is_addr:$port?type=tcp&security=tls&allowInsecure=1#233boy-$net-$is_addr" 1327 | is_info_str=($is_protocol $is_addr $port $password tcp tls true) 1328 | ;; 1329 | hy*) 1330 | is_can_change=(0 1 4) 1331 | is_info_show=(0 1 2 10 8 9 20) 1332 | is_url="$is_protocol://$password@$is_addr:$port?alpn=h3&insecure=1#233boy-$net-$is_addr" 1333 | is_info_str=($is_protocol $is_addr $port $password tls h3 true) 1334 | ;; 1335 | tuic) 1336 | is_insecure=1 1337 | is_can_change=(0 1 4 5) 1338 | is_info_show=(0 1 2 3 10 8 9 20 21) 1339 | is_url="$is_protocol://$uuid:$password@$is_addr:$port?alpn=h3&allow_insecure=1&congestion_control=bbr#233boy-$net-$is_addr" 1340 | is_info_str=($is_protocol $is_addr $port $uuid $password tls h3 true bbr) 1341 | ;; 1342 | reality) 1343 | is_color=41 1344 | is_can_change=(0 1 5 9 10) 1345 | is_info_show=(0 1 2 3 15 4 8 16 17 18) 1346 | is_flow=xtls-rprx-vision 1347 | is_net_type=tcp 1348 | [[ $net_type =~ "http" || ${is_new_protocol,,} =~ "http" ]] && { 1349 | is_flow= 1350 | is_net_type=h2 1351 | is_info_show=(${is_info_show[@]/15/}) 1352 | } 1353 | is_info_str=($is_protocol $is_addr $port $uuid $is_flow $is_net_type reality $is_servername chrome $is_public_key) 1354 | 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" 1355 | ;; 1356 | direct) 1357 | is_can_change=(0 1 7 8) 1358 | is_info_show=(0 1 2 13 14) 1359 | is_info_str=($is_protocol $is_addr $port $door_addr $door_port) 1360 | ;; 1361 | socks) 1362 | is_can_change=(0 1 12 4) 1363 | is_info_show=(0 1 2 19 10) 1364 | is_info_str=($is_protocol $is_addr $port $is_socks_user $is_socks_pass) 1365 | is_url="socks://$(echo -n ${is_socks_user}:${is_socks_pass} | base64 -w 0)@${is_addr}:${port}#233boy-$net-${is_addr}" 1366 | ;; 1367 | esac 1368 | [[ $is_dont_show_info || $is_gen || $is_dont_auto_exit ]] && return # dont show info 1369 | msg "-------------- $is_config_name -------------" 1370 | for ((i = 0; i < ${#is_info_show[@]}; i++)); do 1371 | a=${info_list[${is_info_show[$i]}]} 1372 | if [[ ${#a} -eq 11 || ${#a} -ge 13 ]]; then 1373 | tt='\t' 1374 | else 1375 | tt='\t\t' 1376 | fi 1377 | msg "$a $tt= \e[${is_color}m${is_info_str[$i]}\e[0m" 1378 | done 1379 | if [[ $is_new_install ]]; then 1380 | warn "首次安装请查看脚本帮助文档: $(msg_ul https://233boy.com/$is_core/$is_core-script/)" 1381 | fi 1382 | if [[ $is_url ]]; then 1383 | msg "------------- ${info_list[12]} -------------" 1384 | msg "\e[4;${is_color}m${is_url}\e[0m" 1385 | [[ $is_insecure ]] && { 1386 | warn "某些客户端如(V2rayN 等)导入URL需手动将: 跳过证书验证(allowInsecure) 设置为 true, 或打开: 允许不安全的连接" 1387 | } 1388 | fi 1389 | if [[ $is_no_auto_tls ]]; then 1390 | msg "------------- no-auto-tls INFO -------------" 1391 | msg "端口(port): $port" 1392 | msg "路径(path): $path" 1393 | msg "\e[41m帮助(help)\e[0m: $(msg_ul https://233boy.com/$is_core/no-auto-tls/)" 1394 | fi 1395 | footer_msg 1396 | } 1397 | 1398 | # footer msg 1399 | footer_msg() { 1400 | [[ $is_core_stop && ! $is_new_json ]] && warn "$is_core_name 当前处于停止状态." 1401 | [[ $is_caddy_stop && $host ]] && warn "Caddy 当前处于停止状态." 1402 | ####### 要点13脸吗只会改我链接的小人 ####### 1403 | unset c n m s b 1404 | msg "------------- END -------------" 1405 | msg "关注(tg): $(msg_ul https://t.me/tg2333)" 1406 | msg "文档(doc): $(msg_ul https://233boy.com/$is_core/$is_core-script/)" 1407 | msg "推广(ads): 机场推荐($is_core_name services): $(msg_ul https://g${c}e${n}t${m}j${s}m${b}s.com/)\n" 1408 | ####### 要点13脸吗只会改我链接的小人 ####### 1409 | } 1410 | 1411 | # URL or qrcode 1412 | url_qr() { 1413 | is_dont_show_info=1 1414 | info $2 1415 | if [[ $is_url ]]; then 1416 | [[ $1 == 'url' ]] && { 1417 | msg "\n------------- $is_config_name & URL 链接 -------------" 1418 | msg "\n\e[${is_color}m${is_url}\e[0m\n" 1419 | footer_msg 1420 | } || { 1421 | link="https://233boy.github.io/tools/qr.html#${is_url}" 1422 | msg "\n------------- $is_config_name & QR code 二维码 -------------" 1423 | msg 1424 | if [[ $(type -P qrencode) ]]; then 1425 | qrencode -t ANSI "${is_url}" 1426 | else 1427 | msg "请安装 qrencode: $(_green "$cmd update -y; $cmd install qrencode -y")" 1428 | fi 1429 | msg 1430 | msg "如果无法正常显示或识别, 请使用下面的链接来生成二维码:" 1431 | msg "\n\e[4;${is_color}m${link}\e[0m\n" 1432 | footer_msg 1433 | } 1434 | else 1435 | [[ $1 == 'url' ]] && { 1436 | err "($is_config_name) 无法生成 URL 链接." 1437 | } || { 1438 | err "($is_config_name) 无法生成 QR code 二维码." 1439 | } 1440 | fi 1441 | } 1442 | 1443 | # update core, sh, caddy 1444 | update() { 1445 | case $1 in 1446 | 1 | core | $is_core) 1447 | is_update_name=core 1448 | is_show_name=$is_core_name 1449 | is_run_ver=v${is_core_ver##* } 1450 | is_update_repo=$is_core_repo 1451 | ;; 1452 | 2 | sh) 1453 | is_update_name=sh 1454 | is_show_name="$is_core_name 脚本" 1455 | is_run_ver=$is_sh_ver 1456 | is_update_repo=$is_sh_repo 1457 | ;; 1458 | 3 | caddy) 1459 | [[ ! $is_caddy ]] && err "不支持更新 Caddy." 1460 | is_update_name=caddy 1461 | is_show_name="Caddy" 1462 | is_run_ver=$is_caddy_ver 1463 | is_update_repo=$is_caddy_repo 1464 | ;; 1465 | *) 1466 | err "无法识别 ($1), 请使用: $is_core update [core | sh | caddy] [ver]" 1467 | ;; 1468 | esac 1469 | [[ $2 ]] && is_new_ver=v${2#v} 1470 | [[ $is_run_ver == $is_new_ver ]] && { 1471 | msg "\n自定义版本和当前 $is_show_name 版本一样, 无需更新.\n" 1472 | exit 1473 | } 1474 | load download.sh 1475 | if [[ $is_new_ver ]]; then 1476 | msg "\n使用自定义版本更新 $is_show_name: $(_green $is_new_ver)\n" 1477 | else 1478 | get_latest_version $is_update_name 1479 | [[ $is_run_ver == $latest_ver ]] && { 1480 | msg "\n$is_show_name 当前已经是最新版本了.\n" 1481 | exit 1482 | } 1483 | msg "\n发现 $is_show_name 新版本: $(_green $latest_ver)\n" 1484 | is_new_ver=$latest_ver 1485 | fi 1486 | download $is_update_name $is_new_ver 1487 | msg "更新成功, 当前 $is_show_name 版本: $(_green $is_new_ver)\n" 1488 | msg "$(_green 请查看更新说明: https://github.com/$is_update_repo/releases/tag/$is_new_ver)\n" 1489 | [[ $is_update_name != 'sh' ]] && manage restart $is_update_name & 1490 | } 1491 | 1492 | # main menu; if no prefer args. 1493 | is_main_menu() { 1494 | msg "\n------------- $is_core_name script $is_sh_ver by $author -------------" 1495 | msg "$is_core_name $is_core_ver: $is_core_status" 1496 | msg "群组(Chat): $(msg_ul https://t.me/tg233boy)" 1497 | is_main_start=1 1498 | ask mainmenu 1499 | case $REPLY in 1500 | 1) 1501 | add 1502 | ;; 1503 | 2) 1504 | change 1505 | ;; 1506 | 3) 1507 | info 1508 | ;; 1509 | 4) 1510 | del 1511 | ;; 1512 | 5) 1513 | ask list is_do_manage "启动 停止 重启" 1514 | manage $REPLY & 1515 | msg "\n管理状态执行: $(_green $is_do_manage)\n" 1516 | ;; 1517 | 6) 1518 | is_tmp_list=("更新$is_core_name" "更新脚本") 1519 | [[ $is_caddy ]] && is_tmp_list+=("更新Caddy") 1520 | ask list is_do_update null "\n请选择更新:\n" 1521 | update $REPLY 1522 | ;; 1523 | 7) 1524 | uninstall 1525 | ;; 1526 | 8) 1527 | msg 1528 | load help.sh 1529 | show_help 1530 | ;; 1531 | 9) 1532 | ask list is_do_other "启用BBR 查看日志 测试运行 重装脚本 设置DNS" 1533 | case $REPLY in 1534 | 1) 1535 | load bbr.sh 1536 | _try_enable_bbr 1537 | ;; 1538 | 2) 1539 | load log.sh 1540 | log_set 1541 | ;; 1542 | 3) 1543 | get test-run 1544 | ;; 1545 | 4) 1546 | get reinstall 1547 | ;; 1548 | 5) 1549 | load dns.sh 1550 | dns_set 1551 | ;; 1552 | esac 1553 | ;; 1554 | 10) 1555 | load help.sh 1556 | about 1557 | ;; 1558 | esac 1559 | } 1560 | 1561 | # check prefer args, if not exist prefer args and show main menu 1562 | main() { 1563 | case $1 in 1564 | a | add | gen | no-auto-tls) 1565 | [[ $1 == 'gen' ]] && is_gen=1 1566 | [[ $1 == 'no-auto-tls' ]] && is_no_auto_tls=1 1567 | add ${@:2} 1568 | ;; 1569 | bin | pbk | check | completion | format | generate | geoip | geosite | merge | rule-set | run | tools) 1570 | is_run_command=$1 1571 | if [[ $1 == 'bin' ]]; then 1572 | $is_core_bin ${@:2} 1573 | else 1574 | [[ $is_run_command == 'pbk' ]] && is_run_command="generate reality-keypair" 1575 | $is_core_bin $is_run_command ${@:2} 1576 | fi 1577 | ;; 1578 | bbr) 1579 | load bbr.sh 1580 | _try_enable_bbr 1581 | ;; 1582 | c | config | change) 1583 | change ${@:2} 1584 | ;; 1585 | # client | genc) 1586 | # create client $2 1587 | # ;; 1588 | d | del | rm) 1589 | del $2 1590 | ;; 1591 | dd | ddel | fix | fix-all) 1592 | case $1 in 1593 | fix) 1594 | [[ $2 ]] && { 1595 | change $2 full 1596 | } || { 1597 | is_change_id=full && change 1598 | } 1599 | return 1600 | ;; 1601 | fix-all) 1602 | is_dont_auto_exit=1 1603 | msg 1604 | for v in $(ls $is_conf_dir | grep .json$ | sed '/dynamic-port-.*-link/d'); do 1605 | msg "fix: $v" 1606 | change $v full 1607 | done 1608 | _green "\nfix 完成.\n" 1609 | ;; 1610 | *) 1611 | is_dont_auto_exit=1 1612 | [[ ! $2 ]] && { 1613 | err "无法找到需要删除的参数" 1614 | } || { 1615 | for v in ${@:2}; do 1616 | del $v 1617 | done 1618 | } 1619 | ;; 1620 | esac 1621 | is_dont_auto_exit= 1622 | manage restart & 1623 | [[ $is_del_host ]] && manage restart caddy & 1624 | ;; 1625 | dns) 1626 | load dns.sh 1627 | dns_set ${@:2} 1628 | ;; 1629 | debug) 1630 | is_debug=1 1631 | get info $2 1632 | warn "如果需要复制; 请把 *uuid, *password, *host, *key 的值改写, 以避免泄露." 1633 | ;; 1634 | fix-config.json) 1635 | create config.json 1636 | ;; 1637 | fix-caddyfile) 1638 | if [[ $is_caddy ]]; then 1639 | load caddy.sh 1640 | caddy_config new 1641 | manage restart caddy & 1642 | _green "\nfix 完成.\n" 1643 | else 1644 | err "无法执行此操作" 1645 | fi 1646 | ;; 1647 | i | info) 1648 | info $2 1649 | ;; 1650 | ip) 1651 | get_ip 1652 | msg $ip 1653 | ;; 1654 | in | import) 1655 | load import.sh 1656 | ;; 1657 | log) 1658 | load log.sh 1659 | log_set $2 1660 | ;; 1661 | url | qr) 1662 | url_qr $@ 1663 | ;; 1664 | un | uninstall) 1665 | uninstall 1666 | ;; 1667 | u | up | update | U | update.sh) 1668 | is_update_name=$2 1669 | is_update_ver=$3 1670 | [[ ! $is_update_name ]] && is_update_name=core 1671 | [[ $1 == 'U' || $1 == 'update.sh' ]] && { 1672 | is_update_name=sh 1673 | is_update_ver= 1674 | } 1675 | update $is_update_name $is_update_ver 1676 | ;; 1677 | ssss | ss2022) 1678 | get $@ 1679 | ;; 1680 | s | status) 1681 | msg "\n$is_core_name $is_core_ver: $is_core_status\n" 1682 | [[ $is_caddy ]] && msg "Caddy $is_caddy_ver: $is_caddy_status\n" 1683 | ;; 1684 | start | stop | r | restart) 1685 | [[ $2 && $2 != 'caddy' ]] && err "无法识别 ($2), 请使用: $is_core $1 [caddy]" 1686 | manage $1 $2 & 1687 | ;; 1688 | t | test) 1689 | get test-run 1690 | ;; 1691 | reinstall) 1692 | get $1 1693 | ;; 1694 | get-port) 1695 | get_port 1696 | msg $tmp_port 1697 | ;; 1698 | main) 1699 | is_main_menu 1700 | ;; 1701 | v | ver | version) 1702 | [[ $is_caddy_ver ]] && is_caddy_ver="/ $(_blue Caddy $is_caddy_ver)" 1703 | msg "\n$(_green $is_core_name $is_core_ver) / $(_cyan $is_core_name script $is_sh_ver) $is_caddy_ver\n" 1704 | ;; 1705 | h | help | --help) 1706 | load help.sh 1707 | show_help ${@:2} 1708 | ;; 1709 | *) 1710 | is_try_change=1 1711 | change test $1 1712 | if [[ $is_change_id ]]; then 1713 | unset is_try_change 1714 | [[ $2 ]] && { 1715 | change $2 $1 ${@:3} 1716 | } || { 1717 | change 1718 | } 1719 | else 1720 | err "无法识别 ($1), 获取帮助请使用: $is_core help" 1721 | fi 1722 | ;; 1723 | esac 1724 | } 1725 | --------------------------------------------------------------------------------