├── runit ├── udp2raw1 │ └── run ├── udpspeeder │ └── run ├── udp2raw2 │ └── run ├── tinymapper1 │ └── run ├── tinymapper2 │ └── run ├── kcptun │ └── run ├── shadowsocks │ └── run └── bbr │ └── run ├── calc_packetloss.py ├── Dockerfile ├── entrypoint.sh ├── README.md └── generate.py /runit/udp2raw1/run: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | exec 2>&1 4 | 5 | if [ -n "${UDP2RAW_CONFIG_ONE}" ]; then 6 | echo -e "starting first udp2raw... command: ${UDP2RAW_MODULE} ${UDP2RAW_CONFIG_ONE}" 7 | exec chpst ${UDP2RAW_MODULE} ${UDP2RAW_CONFIG_ONE} 8 | else 9 | echo "first udp2raw not started." 10 | exec sv stop udp2raw1 11 | exit 0 12 | fi 13 | -------------------------------------------------------------------------------- /runit/udpspeeder/run: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | exec 2>&1 4 | 5 | if [ -n "${UDPSPEEDER_CONFIG}" ]; then 6 | echo -e "starting UDPspeeder... command: ${UDPSPEEDER_MODULE} ${UDPSPEEDER_CONFIG}" 7 | exec chpst ${UDPSPEEDER_MODULE} ${UDPSPEEDER_CONFIG} 8 | else 9 | echo "UDPspeeder not started." 10 | exec sv stop udpspeeder 11 | exit 0 12 | fi 13 | -------------------------------------------------------------------------------- /runit/udp2raw2/run: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | exec 2>&1 4 | 5 | if [ -n "${UDP2RAW_CONFIG_TWO}" ]; then 6 | sleep 1 7 | echo -e "starting second udp2raw... command: ${UDP2RAW_MODULE} ${UDP2RAW_CONFIG_TWO}" 8 | exec chpst ${UDP2RAW_MODULE} ${UDP2RAW_CONFIG_TWO} 9 | else 10 | echo "second udp2raw not started." 11 | exec sv stop udp2raw2 12 | exit 0 13 | fi 14 | -------------------------------------------------------------------------------- /runit/tinymapper1/run: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | exec 2>&1 4 | 5 | if [ -n "${TINY_MAPPER_CONFIG_ONE}" ]; then 6 | echo -e "starting first tinyPortMapper... command: ${TINY_MAPPER_MODULE} ${TINY_MAPPER_CONFIG_ONE} " 7 | exec chpst ${TINY_MAPPER_MODULE} ${TINY_MAPPER_CONFIG_ONE} 8 | else 9 | echo "first tinyPortMapper not started. " 10 | exec sv stop tinymapper1 11 | exit 0 12 | fi 13 | -------------------------------------------------------------------------------- /runit/tinymapper2/run: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | exec 2>&1 4 | 5 | if [ -n "${TINY_MAPPER_CONFIG_TWO}" ]; then 6 | echo -e "starting second tinyPortMapper... command: ${TINY_MAPPER_MODULE} ${TINY_MAPPER_CONFIG_TWO} " 7 | exec chpst ${TINY_MAPPER_MODULE} ${TINY_MAPPER_CONFIG_TWO} 8 | else 9 | echo "second tinyPortMapper not started. " 10 | exec sv stop tinymapper2 11 | exit 0 12 | fi 13 | -------------------------------------------------------------------------------- /runit/kcptun/run: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | exec 2>&1 4 | 5 | if [ -n "${KCP_CONFIG}" ]; then 6 | 7 | if [ -z "${KCP_MODULE}" ]; then 8 | echo "Warning: KCP_MODULE is empty, default to kcpserver!" 9 | KCP_MODULE="kcpserver" 10 | fi 11 | 12 | echo -e "starting Kcptun... command: ${KCP_MODULE} ${KCP_CONFIG}" 13 | exec chpst -u kcptun ${KCP_MODULE} ${KCP_CONFIG} 14 | else 15 | echo "Kcptun not started." 16 | exec sv stop kcptun 17 | exit 0 18 | fi 19 | -------------------------------------------------------------------------------- /runit/shadowsocks/run: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | exec 2>&1 4 | 5 | if [ -n "${SS_CONFIG}" ]; then 6 | if [ -z "${SS_MODULE}" ]; then 7 | echo "Warning: SS_MODULE is empty, default to ss-server!" 8 | SS_MODULE="ss-server" 9 | fi 10 | echo -e "starting Shadowsocks... command: ${SS_MODULE} ${SS_CONFIG}" 11 | exec chpst -u shadowsocks ${SS_MODULE} ${SS_CONFIG} 12 | else 13 | echo "Shadowsocks not started." 14 | exec sv stop shadowsocks 15 | exit 0 16 | fi 17 | -------------------------------------------------------------------------------- /calc_packetloss.py: -------------------------------------------------------------------------------- 1 | import math 2 | 3 | #在丢包率为P的情况下,n个包中至少到达m个的概率 4 | def f0(n,m,p): 5 | sum=0 6 | for k in range(m,n+1): 7 | sum+=C(k,n)*math.pow(1-p,k)*math.pow(p,n-k) 8 | return sum 9 | 10 | def C(n,m): 11 | return math.factorial(m)/(math.factorial(n)*math.factorial(m-n)) 12 | 13 | def calc(x, y, p): 14 | return 1-f0(x+y,x,p) 15 | 16 | def predict_loss(fec,packet_loss): 17 | x,y=fec.split(":") 18 | pred= calc(int(x), int(y), packet_loss / 100.0) * 100 19 | print(f"{x}:{y} 可以将 {packet_loss}% 的丢包率降为 "+"%.2f%%"%pred) 20 | 21 | def calc_fec_param(target_loss,origin_loss,num=20): 22 | str="-f" 23 | origin_loss/=100.0 24 | target_loss/=100.0 25 | num+=1 26 | map=dict() 27 | for x in range(1,num): 28 | for y in range(1,num): 29 | if calc(x, y, origin_loss) < target_loss: 30 | map[y]=x 31 | break 32 | return str+",".join(f"{map[k]}:{k}" for k in sorted(map.keys())) 33 | 34 | if __name__ == '__main__': 35 | predict_loss("20:19",30) 36 | print(calc_fec_param(0.5,30)) 37 | 38 | 39 | -------------------------------------------------------------------------------- /runit/bbr/run: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | exec 2>&1 4 | IFACE=$(ip -4 addr | awk '{if ($1 ~ /inet/ && $NF ~ /^[ve]/) {a=$NF}} END{print a}') 5 | BBR_COMMAND="-f -c /etc/rinetd.conf raw ${IFACE}" 6 | 7 | if [ -n "${BBR_MODULE}" ]; then 8 | sleep 2 9 | if [ "${SS_MODULE}" = "ss-server" ]; then 10 | if [ ! -f "/usr/bin/${BBR_MODULE}" ]; then 11 | echo -e "Warning: bbr module ${BBR_MODULE} doesn't exist, default to rinetd-bbr!" 12 | BBR_MODULE="rinetd-bbr" 13 | fi 14 | if [ -z "${BBR_CONFIG}" ]; then 15 | BBR_PORT=$(echo ${SS_CONFIG} | sed -nE "s/.*-p\s+([0-9]+)\s+.*/\1/p") 16 | echo -e "${BBR_MODULE} enabled on port ${BBR_PORT}" 17 | echo "0.0.0.0 ${BBR_PORT} 0.0.0.0 ${BBR_PORT} " > /etc/rinetd.conf 18 | else 19 | echo -e "${BBR_MODULE} using config:\n${BBR_CONFIG}" 20 | echo ${BBR_CONFIG} > /etc/rinetd.conf 21 | fi; 22 | echo -e "starting ${BBR_MODULE}... command: ${BBR_MODULE} ${BBR_COMMAND}" 23 | exec chpst ${BBR_MODULE} ${BBR_COMMAND} 24 | else 25 | echo "bbr should be run on the server side." 26 | exit 0 27 | fi; 28 | else 29 | echo "bbr not started." 30 | exec sv stop bbr 31 | exit 0 32 | fi 33 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | 2 | FROM alpine:3.12 as builder 3 | 4 | LABEL maintainer="sola97 " 5 | 6 | ENV RINETD_BBR_POWERED_DOWNLOAD_URL https://github.com/linhua55/lkl_study/releases/download/v1.2/rinetd_bbr_powered 7 | ENV RINETD_BBR_DOWNLOAD_URL https://github.com/linhua55/lkl_study/releases/download/v1.2/rinetd_bbr 8 | ENV RINETD_PCC_DOWNLOAD_URL https://github.com/linhua55/lkl_study/releases/download/v1.2/rinetd_pcc 9 | 10 | WORKDIR / 11 | 12 | RUN apk update && \ 13 | apk add --no-cache git build-base linux-headers wget && \ 14 | git clone https://github.com/wangyu-/udp2raw-tunnel.git && \ 15 | cd udp2raw-tunnel && \ 16 | make dynamic && \ 17 | mv udp2raw_dynamic /bin/udp2raw && \ 18 | cd / && \ 19 | git clone https://github.com/wangyu-/UDPspeeder.git && \ 20 | cd UDPspeeder && \ 21 | make && \ 22 | install speederv2 /bin && \ 23 | git clone https://github.com/wangyu-/tinyPortMapper.git && \ 24 | cd tinyPortMapper && \ 25 | make && \ 26 | install tinymapper /bin && \ 27 | wget ${RINETD_BBR_POWERED_DOWNLOAD_URL} -qO /bin/rinetd-bbr-powered && \ 28 | wget ${RINETD_BBR_DOWNLOAD_URL} -qO /bin/rinetd-bbr && \ 29 | wget ${RINETD_PCC_DOWNLOAD_URL} -qO /bin/rinetd-pcc && \ 30 | chmod +x /bin/rinetd-* 31 | 32 | 33 | FROM mritd/shadowsocks:3.3.4-20200701 34 | 35 | SHELL ["/bin/bash", "-c"] 36 | 37 | RUN apk update && \ 38 | apk add --no-cache libstdc++ iptables && \ 39 | rm -rf /var/cache/apk/* && \ 40 | mkdir -p /etc/v2ray-plugin 41 | COPY --from=builder /bin/udp2raw /usr/bin 42 | COPY --from=builder /bin/speederv2 /usr/bin 43 | COPY --from=builder /bin/tinymapper /usr/bin 44 | COPY --from=builder /bin/rinetd-bbr /usr/bin 45 | COPY --from=builder /bin/rinetd-bbr-powered /usr/bin 46 | COPY --from=builder /bin/rinetd-pcc /usr/bin 47 | 48 | COPY runit /etc/service 49 | COPY entrypoint.sh /entrypoint.sh 50 | 51 | ENTRYPOINT ["/entrypoint.sh"] 52 | -------------------------------------------------------------------------------- /entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SS_CONFIG=${SS_CONFIG:-""} 4 | SS_MODULE=${SS_MODULE:-""} 5 | KCP_CONFIG=${KCP_CONFIG:-""} 6 | KCP_MODULE=${KCP_MODULE:-""} 7 | UDPSPEEDER_MODULE="speederv2" 8 | UDPSPEEDER_CONFIG=${UDPSPEEDER_CONFIG:-""} 9 | TINY_MAPPER_MODULE="tinymapper" 10 | TINY_MAPPER_CONFIG_ONE=${TINY_MAPPER_CONFIG_ONE:-""} 11 | TINY_MAPPER_CONFIG_TWO=${TINY_MAPPER_CONFIG_TWO:-""} 12 | UDP2RAW_MODULE="udp2raw" 13 | UDP2RAW_CONFIG_ONE=${UDP2RAW_CONFIG_ONE:-""} 14 | UDP2RAW_CONFIG_TWO=${UDP2RAW_CONFIG_TWO:-""} 15 | BBR_MODULE=${BBR_MODULE:-""} 16 | BBR_CONFIG=${BBR_CONFIG:-""} 17 | 18 | while getopts "S:s:K:k:u:t:T:b:B:m:M:" OPT; do 19 | case $OPT in 20 | S) 21 | SS_CONFIG=$OPTARG;; 22 | s) 23 | SS_MODULE=$OPTARG;; 24 | K) 25 | KCP_CONFIG=$OPTARG;; 26 | k) 27 | KCP_MODULE=$OPTARG;; 28 | u) 29 | UDPSPEEDER_CONFIG=$OPTARG;; 30 | t) 31 | UDP2RAW_CONFIG_ONE=$OPTARG;; 32 | T) 33 | UDP2RAW_CONFIG_TWO=$OPTARG;; 34 | b) 35 | BBR_MODULE=$OPTARG;; 36 | B) 37 | BBR_CONFIG=$OPTARG;; 38 | m) 39 | TINY_MAPPER_CONFIG_ONE=$OPTARG;; 40 | M) 41 | TINY_MAPPER_CONFIG_TWO=$OPTARG;; 42 | esac 43 | done 44 | 45 | export SS_CONFIG=${SS_CONFIG} 46 | export SS_MODULE=${SS_MODULE} 47 | export KCP_CONFIG=${KCP_CONFIG} 48 | export KCP_MODULE=${KCP_MODULE} 49 | export UDPSPEEDER_MODULE=${UDPSPEEDER_MODULE} 50 | export UDPSPEEDER_CONFIG=${UDPSPEEDER_CONFIG} 51 | export UDP2RAW_MODULE=${UDP2RAW_MODULE} 52 | export UDP2RAW_CONFIG_ONE=${UDP2RAW_CONFIG_ONE} 53 | export UDP2RAW_CONFIG_TWO=${UDP2RAW_CONFIG_TWO} 54 | export TINY_MAPPER_MODULE=${TINY_MAPPER_MODULE} 55 | export TINY_MAPPER_CONFIG_ONE=${TINY_MAPPER_CONFIG_ONE} 56 | export TINY_MAPPER_CONFIG_TWO=${TINY_MAPPER_CONFIG_TWO} 57 | export BBR_MODULE=${BBR_MODULE} 58 | export BBR_CONFIG=${BBR_CONFIG} 59 | 60 | exec runsvdir -P /etc/service 61 | 62 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Docker集成 2 | - **bbr、bbr魔改版(南琴浪)、pcc** 3 | - **shadowsocks-libev 版本: 3.3.4** 4 | - **kcptun 版本: 20200701** 5 | - **udpspeederv2 版本: 20200714.0** 6 | - **udp2raw 版本: 20200727.0** 7 | - **tinyPortMapper 版本: 20180620.0** 8 | 9 | **基于[mritd/shadowsocks](https://github.com/mritd/dockerfile/tree/master/shadowsocks)镜像制作** 10 | 11 | ### 打开姿势 12 | 1. 下载脚本 `curl -L https://raw.githubusercontent.com/sola97/docker-ss-kcp-udpspeeder/master/generate.py > generate.py` 13 | 2. `python3 generate.py`运行,要求python3.6+ 14 | 3. 输入IP和端口等后得到生成的客户端和服务端命令 15 | 4. 手动粘贴运行 16 | 17 | ### 支持选项 18 | 各模块可以单独启用 19 | - `-s` : 指定 shadowsocks 命令,默认为 `ss-server` 20 | - `-S` : shadowsocks-libev 参数字符串 21 | - `-k` : 指定 kcptun 命令,默认为 `kcpserver` 22 | - `-K` : kcptun 参数字符串 23 | - `-u` : udpspeederv2 的参数字符串 24 | - `-t` : first udp2raw 参数字符串 25 | - `-T` : second udp2raw 参数字符串 26 | - `-b` : 指定要启用的bbr模块 27 | - `-B` : `/etc/rinetd.conf` 配置文件内容 28 | - `-m` : first tinyPortMappper的参数字符串 29 | - `-M` : second tinyPortMappper的参数字符串 30 | ### 选项描述 31 | 32 | - `-s` : 参数后指定一个 shadowsocks 命令,如 ss-local,不写默认为 ss-server;该参数用于 shadowsocks 在客户端和服务端工作模式间切换,可选项如下: `ss-local`、`ss-manager`、`ss-nat`、`ss-redir`、`ss-server`、`ss-tunnel` 33 | - `-S` : 参数后指定一个 shadowsocks-libev 的参数字符串,所有参数将被拼接到 `ss-server` 后 34 | - `-k` : 参数后指定一个 kcptun 命令,如 kcpclient,不写默认为 kcpserver;该参数用于 kcptun 在客户端和服务端工作模式间切换,可选项如下: `kcpserver`、`kcpclient` 35 | - `-K` : 参数后指定一个 kcptun 的参数字符串,所有参数将被拼接到 `kcptun` 后;不写默认为禁用; 36 | - `-u` : 参数后指定一个 udpspeederv2 的参数字符串,所有参数将被拼接到 `udpspeederv2` 后;不写默认为禁用; 37 | - `-t` : 参数后指定一个 udp2raw 的参数字符串,所有参数将被拼接到 `udp2raw` 后;不写默认为禁用; 38 | - `-T` : 第二个 udp2raw 进程的参数字符串;同上,不写默认为禁用; 39 | - `-b` : 选择启用的bbr模块,可选的有`rinetd-bbr`(原版)、`rinetd-bbr-powered`(魔改版)、`rinetd-pcc`(另一个TCP拥塞控制算法) 40 | - `-B` : `/etc/rinetd.conf`的配置,留空自动根据ss监听端口生成,示例:`0.0.0.0 6443 0.0.0.0 6443` 41 | - `-m` : 参数后指定一个tinyPortMappper的参数字符串,所有参数将被拼接到 `tinymaper` 后;不写默认为禁用; 42 | - `-M` : 第二个 tinyPortMappper进程的参数字符串,同上,不写默认为禁用; 43 | 44 | 45 | 46 | ### 方案一 SS+BBR 47 | **方案说明** 48 | 只启用BBR加速 49 | 50 | **Server 端** 51 | 52 | ``` sh 53 | docker run -dt \ 54 | --cap-add=NET_ADMIN \ 55 | --restart=always \ 56 | --name ssserver \ 57 | -p 6443:6443 \ 58 | -p 6443:6443/udp \ 59 | sola97/shadowsocks \ 60 | -s "ss-server" \ 61 | -S "-s 0.0.0.0 -p 6443 -m rc4-md5 -k passwd -u --fast-open" \ 62 | -b "rinetd-bbr" \ 63 | -B "0.0.0.0 6443 0.0.0.0 6443" //此行可选 64 | ``` 65 | 66 | **以上命令相当于执行了** 67 | 68 | ``` sh 69 | ss-server -s 0.0.0.0 -p 6443 -m rc4-md5 -k passwd -u --fast-open 70 | /usr/bin/rinetd-bbr -f -c /etc/rinetd.conf raw eth0 71 | cat <> /etc/rinetd.conf 72 | 0.0.0.0 6443 0.0.0.0 6443 73 | EOF 74 | ``` 75 | 76 | **Client 端** 77 | 78 | ``` sh 79 | docker run -dt \ 80 | --restart=always \ 81 | --name ssclient \ 82 | -p 1080:1080 \ 83 | -p 1080:1080/udp \ 84 | sola97/shadowsocks \ 85 | -s "ss-local" \ 86 | -S "-s $SS_SERVER_IP -p 6443 -b 0.0.0.0 -l 1080 -u -m rc4-md5 -k passwd --fast-open" 87 | ``` 88 | 89 | **以上命令相当于执行了** 90 | 91 | ``` sh 92 | ss-local -s $SS_SERVER_IP -p 6443 -b 0.0.0.0 -l 1080 -u -m rc4-md5 -k passwd --fast-open 93 | ``` 94 | 95 | 96 | ### 方案二 SS+v2ray-plugin(ws+tls)+BBR 97 | **方案说明** 98 | SS + v2ray-plugin + websocket + tls + bbr 99 | 100 | **Server 端** 101 | 102 | ``` sh 103 | docker run -dt \ 104 | --cap-add=NET_ADMIN \ 105 | --restart=always \ 106 | --name ssserver_https \ 107 | -p 443:6443 \ 108 | -p 443:6443/udp \ 109 | -v /path/fullchain.cer:/etc/v2ray-plugin/fullchain.cer \ //域名的fullchain证书 110 | -v /path/private.key:/etc/v2ray-plugin/private.key \ //域名的private.key证书 111 | sola97/shadowsocks \ 112 | -s "ss-server" \ 113 | -S "-s 0.0.0.0 -p 6443 -m rc4-md5 -k passwd -u --fast-open 114 | --plugin v2ray-plugin --plugin-opts=server;tls;host=$server_domain;cert=/etc/v2ray-plugin/fullchain.cer;key=/etc/v2ray-plugin/private.key" \ 115 | -b "rinetd-bbr" 116 | ``` 117 | 118 | **Client 端** 119 | 120 | ``` sh 121 | docker run -dt \ 122 | --restart=always \ 123 | --name ssclient \ 124 | -p 1080:1080 \ 125 | -p 1080:1080/udp \ 126 | sola97/shadowsocks \ 127 | -s "ss-local" \ 128 | -S "-s $server_domain -p 443 -b 0.0.0.0 -l 1080 -u -m rc4-md5 -k passwd --fast-open --plugin v2ray-plugin --plugin-opts=tls;host=$server_domain" 129 | ``` 130 | 131 | 132 | ### 方案三 SS+KCP+UDPspeeder+BBR 133 | **方案说明** 134 | 135 | [UDPspeeder kcptun finalspeed $$ 同时加速tcp和udp流量](https://github.com/wangyu-/UDPspeeder/wiki/UDPspeeder---kcptun-finalspeed---$$-%E5%90%8C%E6%97%B6%E5%8A%A0%E9%80%9Ftcp%E5%92%8Cudp%E6%B5%81%E9%87%8F) 136 | 137 | ![SS+KCP+UDPspeeder](https://github.com/wangyu-/UDPspeeder/raw/master/images/cn/speeder_kcptun.PNG) 138 | 139 | **Server 端** 140 | 141 | ``` sh 142 | docker run -dt \ 143 | --restart=always \ 144 | --name ssserver \ 145 | -p 6443:6443 \ 146 | -p 6443:6443/udp \ //暴露SS端口用于直连 147 | -p 6500:6500/udp \ 148 | -p 6501:6501/udp \ 149 | sola97/shadowsocks \ 150 | -s "ss-server" \ 151 | -S "-s 0.0.0.0 -p 6443 -m rc4-md5 -k passwd -u --fast-open" \ 152 | -k "kcpserver" \ 153 | -K "-l 0.0.0.0:6500 -t 127.0.0.1:6443 --mode fast2 --mtu 1300" \ 154 | -u "-s -l0.0.0.0:6501 -r 127.0.0.1:6443 -f1:3,2:4,8:6,20:10 -k passwd " 155 | ``` 156 | 157 | **以上命令相当于执行了** 158 | 159 | ``` sh 160 | ss-server -s 0.0.0.0 -p 6443 -m rc4-md5 -k passwd -u --fast-open 161 | kcpserver -l 0.0.0.0:6500 -t 127.0.0.1:6443 --mode fast2 --mtu 1300 162 | speederv2 -s -l0.0.0.0:6501 -r 127.0.0.1:6443 -f1:3,2:4,8:6,20:10 -k passwd 163 | ``` 164 | 165 | **Client 端** 166 | 167 | ``` sh 168 | docker run -dt \ 169 | --restart=always \ 170 | --name ssclient \ 171 | -p 6500:6500 \ 172 | -p 6500:6500/udp \ 173 | -p 1080:1080 \ 174 | -p 1080:1080/udp \ 175 | sola97/shadowsocks \ 176 | -s "ss-local" \ 177 | -S "-s 127.0.0.1 -p 6500 -b 0.0.0.0 -l 1080 -u -m rc4-md5 -k passwd --fast-open" \ 178 | -k "kcpclient" \ 179 | -K "-l :6500 -r $SS_SERVER_IP:6500 --mode fast2 --mtu 1300" \ 180 | -u "-c -l[::]:6500 -r$SS_SERVER_IP:6501 -f1:3,2:4,8:6,20:10 -k passwd" 181 | ``` 182 | 183 | **以上命令相当于执行了** 184 | 185 | ``` sh 186 | ss-local -s 127.0.0.1 -p 6500 -b 0.0.0.0 -l 1080 -u -m rc4-md5 -k passwd --fast-open 187 | kcpclient -l :6500 -r $SS_SERVER_IP:6500 --mode fast2 --mtu 1300 188 | speederv2 -c -l[::]:6500 -r$SS_SERVER_IP:6501 -f1:3,2:4,8:6,20:10 -k passwd 189 | ``` 190 | 191 | 192 | ### 方案四 SS+KCP+UDPspeeder+双Udp2raw 193 | **方案说明** 194 | 195 | 在方案三的基础上将两路UDP流量用udp2raw伪装成TCP 196 | 197 | kcptun client---->udp2raw client--------------->udp2raw server---->kcptun server 198 | UDPspeeder client---->udp2raw client--------------->udp2raw server---->UDPspeeder server 199 | 200 | **Server 端** 201 | 202 | ``` sh 203 | docker run -dt \ 204 | --restart=always \ 205 | --cap-add=NET_ADMIN \ 206 | --name ssserver \ 207 | -p 6443:6443 \ 208 | -p 6443:6443/udp \ 209 | -p 4096:4096 \ 210 | -p 4097:4097 \ 211 | sola97/shadowsocks \ 212 | -s "ss-server" \ 213 | -S "-s 0.0.0.0 -p 6443 -m rc4-md5 -k passwd -u --fast-open" \ 214 | -k "kcpserver" \ 215 | -K "-l 0.0.0.0:6500 -t 127.0.0.1:6443 --mode fast2 --mtu 1300" \ 216 | -u "-s -l0.0.0.0:6501 -r 127.0.0.1:6443 -f1:3,2:4,8:6,20:10 -k passwd " \ 217 | -t "-s -l0.0.0.0:4096 -r 127.0.0.1:6500 -k passwd --cipher-mode xor --auth-mode simple --raw-mode faketcp -a" \ 218 | -T "-s -l0.0.0.0:4097 -r 127.0.0.1:6501 -k passwd --cipher-mode xor --auth-mode simple --raw-mode faketcp -a" 219 | ``` 220 | 221 | **以上命令相当于执行了** 222 | 223 | ``` sh 224 | ss-server -s 0.0.0.0 -p 6443 -m rc4-md5 -k passwd -u --fast-open 225 | kcpserver -l 0.0.0.0:6500 -t 127.0.0.1:6443 --mode fast2 --mtu 1300 226 | speederv2 -s -l0.0.0.0:6501 -r 127.0.0.1:6443 -f1:3,2:4,8:6,20:10 -k passwd 227 | udp2raw -s -l0.0.0.0:4096 -r 127.0.0.1:6500 -k passwd --cipher-mode xor --auth-mode simple --raw-mode faketcp -a 228 | udp2raw -s -l0.0.0.0:4097 -r 127.0.0.1:6501 -k passwd --cipher-mode xor --auth-mode simple --raw-mode faketcp -a 229 | ``` 230 | 231 | **Client 端** 232 | 233 | ``` sh 234 | docker run -dt \ 235 | --cap-add=NET_ADMIN \ 236 | --restart=always \ 237 | --name ssclient \ 238 | -p 6500:6500 \ 239 | -p 6500:6500/udp \ 240 | -p 1080:1080 \ 241 | -p 1080:1080/udp \ 242 | sola97/shadowsocks \ 243 | -t "-c -l0.0.0.0:3333 -r$SS_SERVER_IP:4096 -k passwd --cipher-mode xor --auth-mode simple --raw-mode faketcp -a" \ 244 | -T "-c -l0.0.0.0:3334 -r$SS_SERVER_IP:4097 -k passwd --cipher-mode xor --auth-mode simple --raw-mode faketcp -a" \ 245 | -k "kcpclient" \ 246 | -K "-l :6500 -r 127.0.0.1:3333 --mode fast2 --mtu 1300" \ 247 | -u "-c -l[::]:6500 -r127.0.0.1:3334 -f1:3,2:4,8:6,20:10 -k passwd" \ 248 | -s "ss-local" \ 249 | -S "-s 127.0.0.1 -p 6500 -b 0.0.0.0 -l 1080 -u -m rc4-md5 -k passwd --fast-open" 250 | ``` 251 | 252 | **以上命令相当于执行了** 253 | 254 | ``` sh 255 | udp2raw -c -l0.0.0.0:3333 -r$SS_SERVER_IP:4096 -k passwd --cipher-mode xor --auth-mode simple --raw-mode faketcp -a 256 | udp2raw -c -l0.0.0.0:3334 -r$SS_SERVER_IP:4097 -k passwd --cipher-mode xor --auth-mode simple --raw-mode faketcp -a 257 | kcpclient -l :6500 -r 127.0.0.1:3333 --mode fast2 --mtu 1300 258 | speederv2 -c -l[::]:6500 -r127.0.0.1:3334 -f1:3,2:4,8:6,20:10 -k passwd 259 | ss-local -s 127.0.0.1 -p 6500 -b 0.0.0.0 -l 1080 -u -m rc4-md5 -k passwd --fast-open 260 | ``` 261 | 262 | **注意:启用udp2raw或BBR的时候要指定**`docker --cap-add=NET_ADMIN` 263 | 264 | 265 | ### 环境变量支持 266 | 267 | 268 | |环境变量|作用|取值| 269 | |-------|---|---| 270 | |SS_MODULE|shadowsocks 启动命令| `ss-local`、`ss-manager`、`ss-nat`、`ss-redir`、`ss-server`、`ss-tunnel`| 271 | |SS_CONFIG|shadowsocks-libev 参数字符串|所有字符串内内容应当为 shadowsocks-libev 支持的选项参数| 272 | |KCP_MODULE|kcptun 启动命令| `kcpserver`、`kcpclient`| 273 | |KCP_CONFIG|kcptun 参数字符串|所有字符串内内容应当为 kcptun 支持的选项参数| 274 | |UDPSPEEDER_CONFIG|udpspeederv2 参数字符串|所有字符串内内容应当为 udpspeederv2 支持的选项参数,为空时不启动 275 | |UDP2RAW_CONFIG_ONE|第一个 udp2raw 进程参数字符串|所有字符串内内容应当为 udp2raw 支持的选项参数,为空时不启动 276 | |UDP2RAW_CONFIG_TWO|第二个 udp2raw 进程参数字符串|所有字符串内内容应当为 udp2raw 支持的选项参数,为空时不启动 277 | |BBR_MODULE|启用的bbr模块|`rinetd-bbr`、`rinetd-bbr-powered`、`rinetd-pcc`, 为空时不启动 278 | |BBR_CONFIG|`/etc/rinetd.conf`文件内容|所有字符串内内容应当为rinted支持的格式 279 | |TINY_MAPPER_CONFIG_ONE|第一个tinyPortMapper进程参数字符串|所有字符串内内容应当为 tinyPortMapper支持的选项参数, 为空时不启动 280 | |TINY_MAPPER_CONFIG_TWO|第二个tinyPortMapper进程参数字符串|所有字符串内内容应当为 tinyPortMapper支持的选项参数, 为空时不启动 281 | 282 | **使用时可指定环境变量,如下** 283 | 284 | ``` sh 285 | docker run -dt --name ss -p 6443:6443 -p 6500:6500/udp -e SS_CONFIG="-s 0.0.0.0 -p 6443 -m rc4-md5 -k passwd" -e KCP_MODULE="kcpserver" -e KCP_CONFIG="-t 127.0.0.1:6443 -l :6500 --mode fast2 --mtu 1300" sola97/shadowsocks 286 | ``` 287 | 288 | 289 | 290 | **更新日志** 291 | - 2021-07-18 292 | 293 | 更新generate.py,自动在docker-compose文件夹下生成yml文件 294 | 295 | - 2020-09-17 296 | 297 | 更新generate.py,设置服务端为--network=host,用于支持Full cone NAT 298 | 299 | - 2020-08-05 300 | 301 | 取消SS为必须项,更新generate.py,添加udp2raw设置raw-mode 302 | 303 | - 2020-07-21 基于mritd/shadowsocks:3.3.4-20200701 304 | 305 | 添加TinyPortMapper 306 | 307 | - 2020-05-16 基于mritd/shadowsocks:3.3.4-20200409 308 | 309 | 更新 generate.py,添加UDPSpeeder的FEC参数选项 310 | 311 | - 2020-01-06 基于mritd/shadowsocks:3.3.3-20191229 312 | 313 | 添加v2ray(ws+tls)的配置说明 314 | 315 | - 2020-01-01 添加基于LKL的BBR 316 | 317 | 添加BBR,更新 generate.py 318 | 319 | - 2019-12-31 基于mritd/shadowsocks:3.3.3-20191127 320 | 321 | 更新 generate.py,添加用于计算丢包率的脚本 322 | -------------------------------------------------------------------------------- /generate.py: -------------------------------------------------------------------------------- 1 | import os 2 | import re 3 | import json 4 | import string 5 | import random 6 | from urllib import request, parse 7 | import base64 8 | import math 9 | 10 | # 密码和加密方式 11 | PASSWD = "" # 为空时自动生成 12 | SS_ENCRYPT = "rc4-md5" # 加密方式,并不是所有都和udpspeeder等兼容,会导致udp不通,需自行测试 13 | GROUP_NAME = "" # SSR客户端分组名称 14 | 15 | # v2ray-plugin 16 | V2RAY_CERT_FILE = "" 17 | V2RAY_KEY_FILE = "" 18 | 19 | # 其他参数 20 | SS_PARAM = "--fast-open" 21 | KCP_SERVER_PARAM = "" 22 | KCP_CLIENT_PARAM = "" 23 | UDPSPEEDER_FEC = "" 24 | UDPSPEEDER_PARAM = "" 25 | UDP2RAW_PARAM = "--cipher-mode xor --auth-mode simple --raw-mode {mode} --fix-gro -a" 26 | UDP2RAW_MODE = "" 27 | UDP2RAW_PORT_PROTOCOL = "" # 用于docker端口 tcp为"",udp为"/udp" 28 | BBR_MODULE = "" 29 | BBR_DESCRIPTION = "不启用" 30 | 31 | # 服务端默认参数 32 | server_ss_port = 6443 # 原生ss端口 33 | server_name = "ssserver" 34 | server_kcptun_port = 6500 35 | server_udpspeeder_port = 6501 36 | server_udp2raw_port = 4096 37 | server_network_mode = "host" # 用于支持Full cone NAT 38 | # 客户端默认参数 39 | client_name = "ssclient" 40 | client_ss_port = server_kcptun_port # windows,安卓等SS客户端可以连这个端口使用 41 | relay_host = "127.0.0.1" # 运行docker客户端的IP或域名, 生成ss链接用于局域网/国内中转 42 | client_socks5_port = 1080 43 | client_network_mode = "bridge" 44 | # 全局变量 45 | 46 | server_ip = None 47 | server_host = None 48 | is_domain = False 49 | ip_data = dict() 50 | 51 | # Linux下控制台输出颜色 52 | if os.name == 'nt': 53 | CBLUE = CRED = CEND = CYELLOW = CGREEN = "" 54 | else: 55 | CBLUE = '\033[94m' 56 | CRED = '\033[95m' 57 | CYELLOW = '\033[93m' 58 | CGREEN = '\033[92m' 59 | CEND = '\033[0m' 60 | 61 | 62 | def get_network_mode(): 63 | return { 64 | 0: {"mode": "host", "desc": "支持 Full cone NAT"}, 65 | 1: {"mode": "bridge", "desc": "桥接"} 66 | } 67 | 68 | 69 | def get_udp2raw_mode(): 70 | return { 71 | 0: {"mode": "faketcp", "protocol": "", "desc": "绕过Qos等"}, 72 | 1: {"mode": "udp", "protocol": "/udp", "desc": "心跳保活、断线重连等"} 73 | } 74 | 75 | 76 | def get_udp_fec_param(): 77 | return { 78 | 0: {"FEC": "输入丢包率进行计算", "desc": ""}, 79 | 1: {"FEC": "-f1:1,2:2,5:3,10:4,17:5,25:6", "desc": "丢包率7%的时候,降到0.48%"}, 80 | 2: {"FEC": "-f1:3,2:4,8:6,20:10", "desc": "丢包率15%的时候,降到0.49%"}, 81 | 3: {"FEC": "-f1:3,3:4,4:5,6:6,8:7,10:8,12:9,14:10,17:11,19:12,20:13", 82 | "desc": "丢包率20%的时候,降到0.27%"}, 83 | 4: {"FEC": "-f1:3,2:4,3:5,4:6,5:7,7:8,8:9,10:10,12:11,13:12,15:13,17:14,19:15,20:16", 84 | "desc": "丢包率25%的时候,降到0.31%"}, 85 | 5: {"FEC": "-f1:4,2:5,3:6,4:7,5:8,6:9,7:10,8:11,10:12,11:13,13:14,14:15,15:16,17:17,18:18,20:19", 86 | "desc": "丢包率30%的时候,降到0.49%"}, 87 | } 88 | 89 | 90 | def get_tcp_param(): 91 | return { 92 | 0: {"KCP_SERVER_PARAM": "--mode fast2 --mtu 1300", 93 | "KCP_CLIENT_PARAM": "--mode fast2 --mtu 1300", 94 | "desc": "低丢包率下使用"}, 95 | 1: {"KCP_SERVER_PARAM": "--mode fast --datashard 15 --parityshard 8 --mtu 1300", 96 | "KCP_CLIENT_PARAM": "--mode fast --datashard 15 --parityshard 8 --mtu 1300", 97 | "desc": "丢包率15%的时候,降到0.42%"}, 98 | 2: {"KCP_SERVER_PARAM": "--mode fast --datashard 15 --parityshard 15 --mtu 1300", 99 | "KCP_CLIENT_PARAM": "--mode fast --datashard 15 --parityshard 15 --mtu 1300", 100 | "desc": "丢包率30%的时候,降到0.63%"} 101 | } 102 | 103 | 104 | def get_bbr_module(select): 105 | return { 106 | 0: ["", "不启用"], 107 | 1: ["rinetd-bbr", "bbr原版"], 108 | 2: ["rinetd-bbr-powered", "bbr魔改版"], 109 | 3: ["rinetd-pcc", "pcc"] 110 | }[select] 111 | 112 | 113 | def get_random_password(num): 114 | str = string.ascii_letters + string.digits 115 | key = random.sample(str, num) 116 | keys = "".join(key) 117 | return keys 118 | 119 | 120 | def getURI(server_ip, ss_port, description="", group=GROUP_NAME, plugin="", plugin_opts=""): 121 | country = ip_data.get("country") 122 | city = ip_data.get("city", "") if ip_data.get("city") != ip_data.get("country") else "" 123 | remarks = " ".join([country, city, description]) 124 | ss_tag = "#" + parse.quote(remarks) 125 | if plugin and plugin_opts: 126 | password = base64.urlsafe_b64encode(str.encode(f"{SS_ENCRYPT}:{PASSWD}", 'utf8')).decode("utf-8") 127 | plugin_data = parse.quote(f";{plugin_opts}") 128 | ss_data = f"{password}@{server_host}:{ss_port}/?plugin={plugin}{plugin_data}{ss_tag}" 129 | print(" " * 4 + CYELLOW + f"ss://{ss_data}") 130 | return 131 | 132 | remarks_b64_encode = base64.urlsafe_b64encode(str.encode(remarks, 'utf8')).decode("utf-8") 133 | 134 | ss_data = f"{SS_ENCRYPT}:{PASSWD}@{server_ip}:{ss_port}" 135 | ss_uri = base64.b64encode(ss_data.encode('utf8')).decode("utf-8") + ss_tag 136 | print(" " * 4 + CYELLOW + f"ss://{ss_uri}" + CEND) 137 | 138 | password_encode = base64.urlsafe_b64encode(str.encode(PASSWD, 'utf8')).decode("utf-8") 139 | group_encode = base64.urlsafe_b64encode(str.encode(group, 'utf8')).decode("utf-8") 140 | ssr_data = f"{server_ip}:{ss_port}:origin:{SS_ENCRYPT}:plain:{password_encode}/?obfsparam=&remarks={remarks_b64_encode}&group={group_encode}" 141 | ssr_uri = base64.urlsafe_b64encode(ssr_data.encode('utf8')).decode("utf-8").strip("=") 142 | print(" " * 4 + CYELLOW + f"ssr://{ssr_uri}".strip("=") + CEND) 143 | 144 | 145 | def set_server_network_mode(): 146 | global server_network_mode 147 | while True: 148 | print(f"{CGREEN}请选择服务端的网络模式{CEND}") 149 | for index, v in get_network_mode().items(): 150 | if index == 0: 151 | print(f"{CGREEN}[{index}]." + v["mode"] + f" {v['desc']} {CEND}{CYELLOW}[默认]{CEND}") 152 | else: 153 | print(f"{CGREEN}[{index}]." + v["mode"] + f" {v['desc']}") 154 | 155 | input_select = input("请输入选项:") 156 | if input_select == "": 157 | server_network_mode = get_network_mode()[0]['mode'] 158 | print(f"当前网络模式为--network={CYELLOW}{server_network_mode}{CEND}") 159 | break 160 | elif re.match("^\d+$", input_select) and get_network_mode().get(int(input_select), None): 161 | index = int(input_select) 162 | server_network_mode = get_network_mode()[index]['mode'] 163 | print(f"当前网络模式为--network={CYELLOW}{server_network_mode}{CEND}") 164 | break 165 | else: 166 | print(CRED + "输入错误,请重新输入" + CEND) 167 | 168 | 169 | def set_kcptun_param(): 170 | global KCP_SERVER_PARAM, KCP_CLIENT_PARAM 171 | if KCP_SERVER_PARAM and KCP_SERVER_PARAM: 172 | return 173 | while True: 174 | print(f"{CGREEN}请选择kcptun的参数{CEND}") 175 | for index, v in get_tcp_param().items(): 176 | if index == 0: 177 | print(f"{CGREEN}[{index}]." + v["KCP_SERVER_PARAM"] + f" {v['desc']} {CEND}{CYELLOW}[默认]{CEND}") 178 | else: 179 | print(f"{CGREEN}[{index}]." + v["KCP_SERVER_PARAM"] + f" {v['desc']}") 180 | 181 | input_select = input("请输入选项:") 182 | if input_select == "": 183 | KCP_SERVER_PARAM = get_tcp_param()[0]['KCP_SERVER_PARAM'] 184 | KCP_CLIENT_PARAM = get_tcp_param()[0]['KCP_CLIENT_PARAM'] 185 | print(f"当前kcptun参数:{CYELLOW}{KCP_SERVER_PARAM}{CEND}") 186 | break 187 | elif re.match("^\d+$", input_select) and get_tcp_param().get(int(input_select), None): 188 | index = int(input_select) 189 | KCP_SERVER_PARAM = get_tcp_param()[index]['KCP_SERVER_PARAM'] 190 | KCP_CLIENT_PARAM = get_tcp_param()[index]['KCP_CLIENT_PARAM'] 191 | print(f"当前kcptun参数:{CYELLOW}{KCP_SERVER_PARAM}{CEND}") 192 | break 193 | else: 194 | print(CRED + "输入错误,请重新输入" + CEND) 195 | 196 | 197 | def set_udpspeeder_fec_param(): 198 | global UDPSPEEDER_FEC 199 | if UDPSPEEDER_FEC: 200 | return 201 | while True: 202 | print(f"{CGREEN}请选择udpspeeder的FEC参数{CEND}") 203 | for index, v in get_udp_fec_param().items(): 204 | if index == 0: 205 | print(f"{CGREEN}[{index}]." + v["FEC"] + f" {v['desc']} {CEND}{CYELLOW}[默认]{CEND}") 206 | else: 207 | print(f"{CGREEN}[{index}]." + ",".join(v["FEC"].split(",")[:7]) + f" {v['desc']}") 208 | input_select = input("请输入选项:") 209 | if input_select == "" or input_select == "0": 210 | while True: 211 | origin_loss = input(f"{CGREEN}请输入丢包率:{CEND}") 212 | if re.match("^\d+$", origin_loss): 213 | origin_loss = int(origin_loss) 214 | break 215 | else: 216 | print(f"{CRED}输入有误,请重新输入{CEND}") 217 | UDPSPEEDER_FEC = calc_fec_param(0.5, origin_loss) 218 | print(f"当前FEC参数:{CYELLOW}{UDPSPEEDER_FEC}{CEND}") 219 | break 220 | elif re.match("^\d+$", input_select) and get_udp_fec_param().get(int(input_select), None): 221 | index = int(input_select) 222 | UDPSPEEDER_FEC = get_udp_fec_param()[index]['FEC'] 223 | print(f"当前FEC参数:{CYELLOW}{UDPSPEEDER_FEC}{CEND}") 224 | break 225 | else: 226 | print(CRED + "输入错误,请重新输入" + CEND) 227 | 228 | 229 | def set_udp2raw_mode_param(): 230 | global UDP2RAW_MODE, UDP2RAW_PORT_PROTOCOL 231 | while True: 232 | print(f"{CGREEN}请选择UDP2raw的 --raw-mode{CEND}") 233 | for index, v in get_udp2raw_mode().items(): 234 | if index == 0: 235 | print(f"{CGREEN}[{index}]." + v["mode"] + f" {v['desc']} {CEND}{CYELLOW}[默认]{CEND}") 236 | else: 237 | print(f"{CGREEN}[{index}]." + ",".join(v["mode"].split(",")[:7]) + f" {v['desc']}") 238 | input_select = input("请输入选项:") 239 | if input_select == "" or input_select == "0": 240 | UDP2RAW_MODE = get_udp2raw_mode().get(0)['mode'] 241 | UDP2RAW_PORT_PROTOCOL = get_udp2raw_mode().get(0)['protocol'] 242 | print(f"当前UDP2raw参数:{CYELLOW}{UDP2RAW_PARAM.format(mode=UDP2RAW_MODE)}{CEND}") 243 | break 244 | elif re.match("^\d+$", input_select) and get_udp2raw_mode().get(int(input_select), None): 245 | UDP2RAW_MODE = get_udp2raw_mode().get(int(input_select))['mode'] 246 | UDP2RAW_PORT_PROTOCOL = get_udp2raw_mode().get(int(input_select))['protocol'] 247 | print(f"当前UDP2raw参数:{CYELLOW}{UDP2RAW_PARAM.format(mode=UDP2RAW_MODE)}{CEND}") 248 | break 249 | else: 250 | print(CRED + "输入错误,请重新输入" + CEND) 251 | 252 | 253 | def ss_bbr(server_num=0, client_offset=0, suffix=""): 254 | server_cmd = f'docker rm -f {server_name}_{server_num};\\\n\ 255 | docker run -dt \\\n\ 256 | --cap-add=NET_ADMIN \\\n\ 257 | --network={server_network_mode} \\\n\ 258 | --restart=always \\\n\ 259 | --name {server_name}_{server_num} \\\n\ 260 | -p {server_ss_port + server_num}:{server_ss_port + server_num} \\\n\ 261 | -p {server_ss_port + server_num}:{server_ss_port + server_num}/udp \\\n\ 262 | sola97/shadowsocks \\\n\ 263 | -s "ss-server" \\\n\ 264 | -S "-s 0.0.0.0 -p {server_ss_port + server_num} -m {SS_ENCRYPT} -k {PASSWD} -u {SS_PARAM}\" \\\n\ 265 | -b "{BBR_MODULE}" ' 266 | 267 | client_cmd = f'docker rm -f {client_name}{suffix};\\\n\ 268 | docker run -dt \\\n\ 269 | --network={client_network_mode} \\\n\ 270 | --restart=always \\\n\ 271 | --name {client_name}{suffix} \\\n\ 272 | -p {client_socks5_port + client_offset}:{client_socks5_port + client_offset} \\\n\ 273 | -p {client_socks5_port + client_offset}:{client_socks5_port + client_offset}/udp \\\n\ 274 | sola97/shadowsocks \\\n\ 275 | -s "ss-local" \\\n\ 276 | -S "-s {server_host} -p {server_ss_port + server_num} -b 0.0.0.0 -l {client_socks5_port + client_offset} -u -m {SS_ENCRYPT} -k {PASSWD} {SS_PARAM}"' 277 | 278 | print(f"{CRED}↓SS + {BBR_DESCRIPTION}↓{CEND}") 279 | print(f"服务端:\n {CBLUE}{server_cmd}{CEND}") 280 | print(f"客户端:\n {CBLUE}{client_cmd}{CEND}") 281 | print(f"{CRED}↑SS + {BBR_DESCRIPTION}↑{CEND}") 282 | print(f"服务端SS端口:{server_ss_port + server_num}") 283 | print(f"客户端SOCKS5端口:{client_socks5_port + client_offset}") 284 | print("密码为:" + PASSWD) 285 | print(f"导出链接:") 286 | getURI(server_host, server_ss_port + server_num, f"{BBR_DESCRIPTION} 直连") 287 | write_compose_file(server_cmd, subfolder="ss-bbr") 288 | write_compose_file(client_cmd, subfolder="ss-bbr") 289 | 290 | 291 | def ss_v2ray_ws_tls_bbr(server_num=0, client_offset=0, suffix=""): 292 | server_ss_port = globals().get("server_ss_port") 293 | server_suffix = server_num 294 | global V2RAY_CERT_FILE, V2RAY_KEY_FILE 295 | if not is_domain: 296 | print(f"{CRED}启用 v2ray(ws+tls) 需要服务器地址为域名{CEND}") 297 | return 298 | 299 | if not V2RAY_CERT_FILE: 300 | while True: 301 | V2RAY_CERT_FILE = input(f"{CGREEN}请输入要mount的证书fullchain.cer文件的路径:{CEND}") 302 | confirm = input( 303 | f"{CGREEN}输入的路径为:{CEND}{CYELLOW}" + V2RAY_CERT_FILE + f" {CEND}{CGREEN}确认{CEND}{CYELLOW}Y{CEND}{CGREEN}/n{CEND}") 304 | if confirm == "" or confirm.lower().startswith("y"): 305 | break 306 | 307 | if not V2RAY_KEY_FILE: 308 | while True: 309 | V2RAY_KEY_FILE = input(f"{CGREEN}请输入要mount的证书{server_host}.key文件的路径:{CEND}") 310 | confirm = input( 311 | f"{CGREEN}输入的路径为:{CEND}{CYELLOW}" + V2RAY_KEY_FILE + f" {CEND}{CGREEN}确认{CEND}{CYELLOW}Y{CEND}{CGREEN}/n{CEND}") 312 | if confirm == "" or confirm.lower().startswith("y"): 313 | break 314 | while True: 315 | confirm = input(f"{CGREEN}是否设定服务器端口为443?{CEND}{CYELLOW}Y{CEND}{CGREEN}/n{CEND}") 316 | if confirm == "" or confirm.lower().startswith("y"): 317 | server_suffix = "https" 318 | server_ss_port = 443 319 | server_num = 0 320 | break 321 | elif confirm.lower().startswith("n"): 322 | break 323 | cert_file_path = "/etc/v2ray-plugin/fullchain.cer" 324 | key_file_path = f"/etc/v2ray-plugin/private.key" 325 | server_cmd = f'docker rm -f {server_name}_{server_suffix};\\\n\ 326 | docker run -dt \\\n\ 327 | --cap-add=NET_ADMIN \\\n\ 328 | --restart=always \\\n\ 329 | --network={server_network_mode} \\\n\ 330 | --name {server_name}_{server_suffix} \\\n\ 331 | -p {server_ss_port + server_num}:{server_ss_port + server_num} \\\n\ 332 | -p {server_ss_port + server_num}:{server_ss_port + server_num}/udp \\\n\ 333 | -v {V2RAY_CERT_FILE}:{cert_file_path} \\\n \ 334 | -v {V2RAY_KEY_FILE}:{key_file_path} \\\n \ 335 | sola97/shadowsocks \\\n\ 336 | -s "ss-server" \\\n\ 337 | -S "-s 0.0.0.0 -p {server_ss_port + server_num} -m {SS_ENCRYPT} -k {PASSWD} -u {SS_PARAM} --plugin v2ray-plugin --plugin-opts=server;tls;host={server_host};cert={cert_file_path};key={key_file_path}\" \\\n\ 338 | -b "{BBR_MODULE}"' 339 | 340 | client_cmd = f'docker rm -f {client_name}{suffix};\\\n\ 341 | docker run -dt \\\n\ 342 | --restart=always \\\n\ 343 | --network={client_network_mode} \\\n\ 344 | --name {client_name}{suffix} \\\n\ 345 | -p {client_socks5_port + client_offset}:{client_socks5_port + client_offset} \\\n\ 346 | -p {client_socks5_port + client_offset}:{client_socks5_port + client_offset}/udp \\\n\ 347 | sola97/shadowsocks \\\n\ 348 | -m "-l0.0.0.0:{client_socks5_port + client_offset} -r{server_ip}:{server_ss_port + server_num} -u" \\\n\ 349 | -s "ss-local" \\\n\ 350 | -S "-s {server_host} -p {server_ss_port + server_num} -b 0.0.0.0 -l {client_socks5_port + client_offset} -u -m {SS_ENCRYPT} -k {PASSWD} {SS_PARAM} --plugin v2ray-plugin --plugin-opts=tls;host={server_host}"' 351 | 352 | print(f"{CRED}↓SS + v2ray-plugin(ws+tls) + bbr↓{CEND}") 353 | print(f"服务端:\n {CBLUE}{server_cmd}{CEND}") 354 | print(f"客户端:\n {CBLUE}{client_cmd}{CEND}") 355 | print(f"{CRED}↑SS + v2ray-plugin(ws+tls) + bbr↑{CEND}") 356 | print(f"服务端SS端口:{server_ss_port + server_num}") 357 | print(f"客户端SOCKS5端口:{client_socks5_port + client_offset}") 358 | print("密码为:" + PASSWD) 359 | print(f"导出链接:") 360 | getURI(server_host, server_ss_port + server_num, f"{BBR_DESCRIPTION} + v2ray(ws+tls)", "", "v2ray-plugin", 361 | f"tls;host={server_host}") 362 | write_compose_file(server_cmd, subfolder="ss-v2ray") 363 | write_compose_file(client_cmd, subfolder="ss-v2ray") 364 | 365 | 366 | def ss_kcptun_udpspeeder(server_num=0, client_offset=0, suffix=""): 367 | set_kcptun_param() 368 | set_udpspeeder_fec_param() 369 | server_cmd = f'docker rm -f {server_name}_{server_num};\\\n\ 370 | docker run -dt \\\n\ 371 | --cap-add=NET_ADMIN \\\n\ 372 | --network={server_network_mode} \\\n\ 373 | --restart=always \\\n\ 374 | --name {server_name}_{server_num} \\\n\ 375 | -p {server_ss_port + server_num}:{server_ss_port + server_num} \\\n\ 376 | -p {server_ss_port + server_num}:{server_ss_port + server_num}/udp \\\n\ 377 | -p {server_kcptun_port + server_num * 2}:{server_kcptun_port + server_num * 2}/udp \\\n\ 378 | -p {server_udpspeeder_port + server_num * 2}:{server_udpspeeder_port + server_num * 2}/udp \\\n\ 379 | sola97/shadowsocks \\\n\ 380 | -s "ss-server" \\\n\ 381 | -S "-s 0.0.0.0 -p {server_ss_port + server_num} -m {SS_ENCRYPT} -k {PASSWD} -u {SS_PARAM}\" \\\n\ 382 | -k "kcpserver" \\\n\ 383 | -K "-l 0.0.0.0:{server_kcptun_port + server_num * 2} -t 127.0.0.1:{server_ss_port + server_num} {KCP_SERVER_PARAM} " \\\n\ 384 | -u "-s -l0.0.0.0:{server_udpspeeder_port + server_num * 2} -r 127.0.0.1:{server_ss_port + server_num} {UDPSPEEDER_FEC} {UDPSPEEDER_PARAM} -k {PASSWD}" \\\n\ 385 | -b "{BBR_MODULE}" ' 386 | 387 | client_cmd = f'docker rm -f {client_name}{suffix};\\\n\ 388 | docker run -dt \\\n\ 389 | --network={client_network_mode} \\\n\ 390 | --restart=always \\\n\ 391 | --name {client_name}{suffix} \\\n\ 392 | -p {client_ss_port + client_offset}:{client_ss_port + client_offset} \\\n\ 393 | -p {client_ss_port + client_offset}:{client_ss_port + client_offset}/udp \\\n\ 394 | -p {client_socks5_port + client_offset}:{client_socks5_port + client_offset} \\\n\ 395 | -p {client_socks5_port + client_offset}:{client_socks5_port + client_offset}/udp \\\n\ 396 | sola97/shadowsocks \\\n\ 397 | -s "ss-local" \\\n\ 398 | -S "-s 127.0.0.1 -p {client_ss_port + client_offset} -b 0.0.0.0 -l {client_socks5_port + client_offset} -u -m {SS_ENCRYPT} -k {PASSWD} {SS_PARAM}" \\\n\ 399 | -k "kcpclient" \\\n\ 400 | -K "-l :{client_ss_port + client_offset} -r {server_ip}:{server_kcptun_port + server_num * 2} {KCP_CLIENT_PARAM}" \\\n\ 401 | -u "-c -l0.0.0.0:{client_ss_port + client_offset} -r{server_ip}:{server_udpspeeder_port + server_num * 2} {UDPSPEEDER_FEC} {UDPSPEEDER_PARAM} -k {PASSWD}"' 402 | print(f"{CRED}↓SS + Kcptun + UDPspeeder↓{CEND}") 403 | print(f"服务端:\n {CBLUE}{server_cmd}{CEND}") 404 | print(f"客户端:\n {CBLUE}{client_cmd}{CEND}") 405 | print(f"{CRED}↑SS + Kcptun + UDPspeeder↑{CEND}") 406 | print(f"服务端原生SS端口:{server_ss_port + server_num}") 407 | print(f"客户端本地映射SS端口:{client_ss_port + client_offset}\n" 408 | f"SOCKS5端口:{client_socks5_port + client_offset}") 409 | print("密码为:" + PASSWD) 410 | print(f"{BBR_DESCRIPTION + '加速' if BBR_MODULE else ''}直连服务端SS:") 411 | getURI(server_host, server_ss_port + server_num, f"{BBR_DESCRIPTION} 直连") 412 | print(f"通过{CRED}{relay_host}{CEND}的 Kcptun + UDPspeeder 的监听端口连接SS:") 413 | getURI(relay_host, client_ss_port + client_offset, '') 414 | write_compose_file(server_cmd, subfolder="ss-kcp-udp") 415 | write_compose_file(client_cmd, subfolder="ss-kcp-udp") 416 | 417 | 418 | def ss_kcptun_udpspeeder_dual_udp2raw(server_num=0, client_offset=0, suffix=""): 419 | set_kcptun_param() 420 | set_udpspeeder_fec_param() 421 | set_udp2raw_mode_param() 422 | server_cmd = f'docker rm -f {server_name}_{server_num};\\\n\ 423 | docker run -dt \\\n\ 424 | --cap-add=NET_ADMIN \\\n\ 425 | --network={server_network_mode} \\\n\ 426 | --restart=always \\\n\ 427 | --name {server_name}_{server_num} \\\n\ 428 | -p {server_ss_port + server_num}:{server_ss_port + server_num} \\\n\ 429 | -p {server_ss_port + server_num}:{server_ss_port + server_num}/udp \\\n\ 430 | -p {server_udp2raw_port + server_num * 2}:{server_udp2raw_port + server_num * 2}{UDP2RAW_PORT_PROTOCOL} \\\n\ 431 | -p {server_udp2raw_port + 1 + server_num * 2}:{server_udp2raw_port + 1 + server_num * 2}{UDP2RAW_PORT_PROTOCOL} \\\n\ 432 | sola97/shadowsocks \\\n\ 433 | -s "ss-server" \\\n\ 434 | -S "-s 0.0.0.0 -p {server_ss_port + server_num} -m {SS_ENCRYPT} -k {PASSWD} -u --fast-open" \\\n\ 435 | -k "kcpserver" \\\n\ 436 | -K "-l 0.0.0.0:6500 -t 127.0.0.1:{server_ss_port + server_num} {KCP_SERVER_PARAM} " \\\n\ 437 | -u "-s -l0.0.0.0:6501 -r 127.0.0.1:{server_ss_port + server_num} {UDPSPEEDER_FEC} {UDPSPEEDER_PARAM} -k {PASSWD}" \\\n\ 438 | -t "-s -l0.0.0.0:{server_udp2raw_port + server_num * 2} -r 127.0.0.1:6500 -k {PASSWD} {UDP2RAW_PARAM.format(mode=UDP2RAW_MODE)}" \\\n\ 439 | -T "-s -l0.0.0.0:{server_udp2raw_port + 1 + server_num * 2} -r 127.0.0.1:6501 -k {PASSWD} {UDP2RAW_PARAM.format(mode=UDP2RAW_MODE)}"\\\n\ 440 | -b "{BBR_MODULE}" ' 441 | 442 | client_cmd = f'docker rm -f {client_name}{suffix};\\\n\ 443 | docker run -dt \\\n\ 444 | --cap-add=NET_ADMIN \\\n\ 445 | --network={client_network_mode} \\\n\ 446 | --restart=always \\\n\ 447 | --name {client_name}{suffix} \\\n\ 448 | -p {client_ss_port + client_offset}:{client_ss_port + client_offset} \\\n\ 449 | -p {client_ss_port + client_offset}:{client_ss_port + client_offset}/udp \\\n\ 450 | -p {client_socks5_port + client_offset}:{client_socks5_port + client_offset} \\\n\ 451 | -p {client_socks5_port + client_offset}:{client_socks5_port + client_offset}/udp \\\n\ 452 | sola97/shadowsocks \\\n\ 453 | -t "-c -l0.0.0.0:3333 -r{server_ip}:{server_udp2raw_port + server_num * 2} -k {PASSWD} {UDP2RAW_PARAM.format(mode=UDP2RAW_MODE)}\" \\\n\ 454 | -T "-c -l0.0.0.0:3334 -r{server_ip}:{server_udp2raw_port + 1 + server_num * 2} -k {PASSWD} {UDP2RAW_PARAM.format(mode=UDP2RAW_MODE)}\" \\\n\ 455 | -k "kcpclient" \\\n\ 456 | -K "-l :{client_ss_port + client_offset} -r 127.0.0.1:3333 {KCP_CLIENT_PARAM}" \\\n\ 457 | -u "-c -l0.0.0.0:{client_ss_port + client_offset} -r127.0.0.1:3334 {UDPSPEEDER_FEC} {UDPSPEEDER_PARAM} -k {PASSWD}" \\\n\ 458 | -s "ss-local" \\\n\ 459 | -S "-s 127.0.0.1 -p {client_ss_port + client_offset} -b 0.0.0.0 -l {client_socks5_port + client_offset} -u -m {SS_ENCRYPT} -k {PASSWD} {SS_PARAM}"' 460 | print(f"{CRED}↓SS + Kcptun + UDPspeeder + 双UDP2raw↓{CEND}") 461 | print(f"服务端:\n {CBLUE}{server_cmd}{CEND}") 462 | print(f"客户端:\n {CBLUE}{client_cmd}{CEND}") 463 | print(f"{CRED}↑SS + Kcptun + UDPspeeder + 双UDP2raw↑{CEND}") 464 | print(f"服务端原生SS端口:{server_ss_port + server_num}") 465 | print(f"客户端本地映射SS端口:{client_ss_port + client_offset}\n" 466 | f"SOCKS5端口:{client_socks5_port + client_offset}") 467 | print("密码为:" + PASSWD) 468 | print(f"{BBR_DESCRIPTION + '加速' if BBR_MODULE else ''}直连服务端SS:") 469 | getURI(server_host, server_ss_port + server_num, f"{BBR_DESCRIPTION} 直连") 470 | print(f"通过{CRED}{relay_host}{CEND}的 Kcptun + UDPspeeder 的监听端口连接SS:") 471 | getURI(relay_host, client_ss_port + client_offset, '双udp2raw') 472 | write_compose_file(server_cmd, subfolder="ss-kcp-udp-dual2raw") 473 | write_compose_file(client_cmd, subfolder="ss-kcp-udp-dual2raw") 474 | 475 | 476 | def ss_kcptun_udpspeeder_udp2raw(server_num=0, client_offset=0, suffix=""): 477 | set_kcptun_param() 478 | set_udpspeeder_fec_param() 479 | set_udp2raw_mode_param() 480 | server_cmd = f'docker rm -f {server_name}_{server_num};\\\n\ 481 | docker run -dt \\\n\ 482 | --cap-add=NET_ADMIN \\\n\ 483 | --network={server_network_mode} \\\n\ 484 | --restart=always \\\n\ 485 | --name {server_name}_{server_num} \\\n\ 486 | -p {server_ss_port + server_num}:{server_ss_port + server_num} \\\n\ 487 | -p {server_ss_port + server_num}:{server_ss_port + server_num}/udp \\\n\ 488 | -p {server_kcptun_port + server_num * 2}:{server_kcptun_port + server_num * 2}/udp \\\n\ 489 | -p {server_udp2raw_port + 1 + server_num * 2}:{server_udp2raw_port + 1 + server_num * 2}{UDP2RAW_PORT_PROTOCOL} \\\n\ 490 | sola97/shadowsocks \\\n\ 491 | -s "ss-server" \\\n\ 492 | -S "-s 0.0.0.0 -p {server_ss_port + server_num} -m {SS_ENCRYPT} -k {PASSWD} -u {SS_PARAM}\" \\\n\ 493 | -k "kcpserver" \\\n\ 494 | -K "-l 0.0.0.0:{server_kcptun_port + server_num * 2} -t 127.0.0.1:{server_ss_port + server_num} {KCP_SERVER_PARAM} " \\\n\ 495 | -u "-s -l0.0.0.0:{server_kcptun_port + 1 + server_num * 2} -r 127.0.0.1:{server_ss_port + server_num} {UDPSPEEDER_FEC} {UDPSPEEDER_PARAM} -k {PASSWD}" \\\n\ 496 | -t "-s -l0.0.0.0:{server_udp2raw_port + 1 + server_num * 2} -r 127.0.0.1:{server_kcptun_port + 1 + server_num * 2} -k {PASSWD} {UDP2RAW_PARAM.format(mode=UDP2RAW_MODE)}" \\\n\ 497 | -b "{BBR_MODULE}" ' 498 | 499 | client_cmd = f'docker rm -f {client_name}{suffix};\\\n\ 500 | docker run -dt \\\n\ 501 | --cap-add=NET_ADMIN \\\n\ 502 | --network={client_network_mode} \\\n\ 503 | --restart=always \\\n\ 504 | --name {client_name}{suffix} \\\n\ 505 | -p {client_ss_port + client_offset}:{client_ss_port + client_offset} \\\n\ 506 | -p {client_ss_port + client_offset}:{client_ss_port + client_offset}/udp \\\n\ 507 | -p {client_socks5_port + client_offset}:{client_socks5_port + client_offset} \\\n\ 508 | -p {client_socks5_port + client_offset}:{client_socks5_port + client_offset}/udp \\\n\ 509 | sola97/shadowsocks \\\n\ 510 | -t "-c -l0.0.0.0:3334 -r{server_ip}:{server_udp2raw_port + 1 + server_num * 2} -k {PASSWD} {UDP2RAW_PARAM.format(mode=UDP2RAW_MODE)}" \\\n\ 511 | -k "kcpclient" \\\n\ 512 | -K "-l :{client_ss_port + client_offset} -r {server_ip}:{server_kcptun_port + server_num * 2} {KCP_CLIENT_PARAM}" \\\n\ 513 | -u "-c -l0.0.0.0:{client_ss_port + client_offset} -r127.0.0.1:3334 {UDPSPEEDER_FEC} {UDPSPEEDER_PARAM} -k {PASSWD}" \\\n\ 514 | -s "ss-local" \\\n\ 515 | -S "-s 127.0.0.1 -p {client_ss_port + client_offset} -b 0.0.0.0 -l {client_socks5_port + client_offset} -u -m {SS_ENCRYPT} -k {PASSWD} {SS_PARAM}"' 516 | print(f"{CRED}↓SS + Kcptun + UDPspeeder+ 单UDP2raw↓{CEND}") 517 | print(f"服务端:\n {CBLUE}{server_cmd}{CEND}") 518 | print(f"客户端:\n {CBLUE}{client_cmd}{CEND}") 519 | print(f"{CRED}↑SS + Kcptun + UDPspeeder+ 单UDP2raw↑{CEND}") 520 | print(f"服务端原生SS端口:{server_ss_port + server_num}") 521 | print(f"客户端本地映射SS端口:{client_ss_port + client_offset}\n" 522 | f"SOCKS5端口:{client_socks5_port + client_offset}") 523 | print("密码为:" + PASSWD) 524 | print(f"{BBR_DESCRIPTION + '加速' if BBR_MODULE else ''}直连服务端SS:") 525 | getURI(server_host, server_ss_port + server_num, f"{BBR_DESCRIPTION} 直连") 526 | print(f"通过{CRED}{relay_host}{CEND}的 Kcptun + UDPspeeder 的监听端口连接SS:") 527 | getURI(relay_host, client_ss_port + client_offset, '单udp2raw') 528 | write_compose_file(server_cmd, subfolder="ss-kcp-udp-udp2raw") 529 | write_compose_file(client_cmd, subfolder="ss-kcp-udp-udp2raw") 530 | 531 | 532 | # 在丢包率为P的情况下,n个包中至少到达m个的概率 533 | def f0(n, m, p): 534 | sum = 0 535 | for k in range(m, n + 1): 536 | sum += C(k, n) * math.pow(1 - p, k) * math.pow(p, n - k) 537 | return sum 538 | 539 | 540 | def C(n, m): 541 | return math.factorial(m) / (math.factorial(n) * math.factorial(m - n)) 542 | 543 | 544 | def calc(x, y, p): 545 | return 1 - f0(x + y, x, p) 546 | 547 | 548 | def predict_loss(fec, packet_loss): 549 | x, y = fec.split(":") 550 | pred = calc(int(x), int(y), packet_loss / 100.0) * 100 551 | print(f"{x}:{y} 可以将 {packet_loss}% 的丢包率降为 " + "%.2f%%" % pred) 552 | 553 | 554 | def calc_fec_param(target_loss, origin_loss, num=20): 555 | str = "-f" 556 | origin_loss /= 100.0 557 | target_loss /= 100.0 558 | num += 1 559 | map = dict() 560 | for x in range(1, num): 561 | for y in range(1, num): 562 | if calc(x, y, origin_loss) < target_loss: 563 | map[y] = x 564 | break 565 | return str + ",".join(f"{map[k]}:{k}" for k in sorted(map.keys())) 566 | 567 | 568 | # 转换为docker-compose 569 | 570 | def search(command, arg): 571 | regex = "^[ ]*[-]+" + arg + '[\s="]+([^\n\\\\"]+)[ ]*' 572 | if re.findall(regex, command, flags=re.MULTILINE).__len__() > 0: 573 | value = '"' + re.search(re.compile(regex, re.MULTILINE), command, ).group(1).strip() + '"' 574 | return value 575 | return "" 576 | 577 | 578 | def search_ports(command): 579 | if search(command, "network") == '"host"': 580 | return "" 581 | else: 582 | ports = "\n ports:" 583 | for p in re.findall("^[ ]*-p (\S+)", command, flags=re.MULTILINE): 584 | ports += "\n - " + p 585 | return ports 586 | 587 | 588 | def search_env(command): 589 | env = "" 590 | map = { 591 | "SS_MODULE": "s", 592 | "SS_CONFIG": "S", 593 | "KCP_MODULE": "k", 594 | "KCP_CONFIG": "K", 595 | "UDPSPEEDER_CONFIG": "u", 596 | "UDP2RAW_CONFIG_ONE": "t", 597 | "UDP2RAW_CONFIG_TWO": "T", 598 | "BBR_MODULE": "b", 599 | "BBR_CONFIG": "B", 600 | "TINY_MAPPER_CONFIG_ONE": "m", 601 | "TINY_MAPPER_CONFIG_TWO": 'M', 602 | } 603 | for cmd_name, cmd_key in map.items(): 604 | cmd = search(command, cmd_key) 605 | if cmd: 606 | env += f"\n {cmd_name}: {cmd}" 607 | return env 608 | 609 | 610 | def get_docker_compose(command): 611 | docker_compose_template = f'''version: '3.7' 612 | services: 613 | shadowsocks: 614 | cap_add: 615 | - NET_ADMIN 616 | image: sola97/shadowsocks 617 | container_name: {search(command, "name")} 618 | restart: always 619 | network_mode: {search(command, "network")}{search_ports(command)} 620 | environment:{search_env(command)} 621 | logging: 622 | driver: "json-file" 623 | options: 624 | max-size: "10m" 625 | max-file: "3" 626 | ''' 627 | return docker_compose_template 628 | 629 | 630 | def write_compose_file(command, subfolder=""): 631 | path = "docker-compose/"+subfolder+"/" 632 | if not os.path.exists(path): 633 | os.makedirs(path) 634 | file_name = path + search(command, "name").strip('"') + ".yml" 635 | file_content = get_docker_compose(command) 636 | with open(file_name, mode='w', encoding='utf-8') as f: 637 | f.write(file_content) 638 | print(f"{CGREEN}已写入docker-compose文件:" + file_name) 639 | 640 | 641 | if __name__ == '__main__': 642 | if not PASSWD: 643 | PASSWD = get_random_password(8) 644 | while True: 645 | query = input(f"{CGREEN}请输入服务器IP或者域名(留空为获取本机IP):{CEND}") 646 | try: 647 | print("正在获取服务器IP的所在地...") 648 | with request.urlopen(f"http://ip-api.com/json/{query}?lang=zh-CN") as f: 649 | ip_data = json.loads(f.read().decode('utf-8')) 650 | if ip_data['status'] == 'success': 651 | client_name = "ss_" + ip_data['countryCode'] + ( 652 | f"_{ip_data['region']}" if ip_data['region'] else "") 653 | client_name = client_name.lower() 654 | server_ip = ip_data['query'] 655 | if query != server_ip and query != "": 656 | server_host = query 657 | is_domain = True 658 | else: 659 | server_host = server_ip 660 | print(f"{CYELLOW}服务器信息:" + " ".join( 661 | [ip_data.get("country", ""), ip_data.get("city", ""), server_ip]) + CEND) 662 | break 663 | else: 664 | print("获取失败,请检查输入是否有误") 665 | except Exception as e: 666 | print("获取失败,请重试", e) 667 | 668 | server_num = 0 669 | client_offset = 0 670 | 671 | sname_input = input(f"{CGREEN}请输入服务端容器名(默认为{CEND}{CYELLOW}{server_name}{CEND}{CGREEN},回车保持默认)\n:{CEND}") 672 | if sname_input: 673 | server_name = sname_input 674 | 675 | sn_input = input(f"{CGREEN}请输入sserver容器的序号(用于运行多个容器的情况,默认为0,回车保持默认)\n:{CEND}") 676 | if re.match("^\d+$", sn_input): 677 | server_num = int(sn_input) 678 | client_offset = int(sn_input) 679 | print(f"服务端docker容器名为:{CYELLOW}{server_name}_{server_num}{CEND}") 680 | 681 | cname_input = input(f"{CGREEN}请输入客户端容器名(默认为{CEND}{CYELLOW}{client_name}{CEND}{CGREEN},回车保持默认)\n:{CEND}") 682 | if cname_input: 683 | client_name = cname_input 684 | 685 | print(f"客户端docker容器名为:{CYELLOW}{client_name}{CEND}") 686 | cl_offset = input( 687 | f"{CGREEN}客户端将使用{CEND}{CYELLOW}{client_socks5_port + client_offset}{CEND}{CGREEN}端口,如需修改请输入新的偏移量,当前为{client_socks5_port}+{CEND}{CYELLOW}{server_num}\n:{CEND}") 688 | 689 | if re.match("^\d+$", cl_offset): 690 | client_offset = int(cl_offset) 691 | print(f"客户端SOCKS5端口为:{CYELLOW}{client_socks5_port + client_offset}{CEND}") 692 | 693 | set_server_network_mode() 694 | 695 | while True: 696 | print(f"{CGREEN}请选择启动的bbr模块,回车保持默认,当前为{CEND}{CYELLOW}{BBR_DESCRIPTION}{CEND}") 697 | for i in range(4): 698 | print(f"{CGREEN}[{i}]." + " ".join(get_bbr_module(i)) + CEND) 699 | 700 | input_select = input("请输入选项:") 701 | if input_select in ("0", "1", "2", "3"): 702 | BBR_MODULE, BBR_DESCRIPTION = get_bbr_module(int(input_select)) 703 | print("当前bbr模块:" + CYELLOW + " ".join([BBR_MODULE, BBR_DESCRIPTION]) + CEND) 704 | break 705 | elif input_select == "": 706 | print("当前bbr模块:" + CYELLOW + " ".join([BBR_MODULE, BBR_DESCRIPTION]) + CEND) 707 | break 708 | else: 709 | print(CRED + "输入错误,请重新输入" + CEND) 710 | 711 | while True: 712 | print(f"{CGREEN}请选择方案:") 713 | print("[0].退出") 714 | bbr = "+ " + BBR_DESCRIPTION if BBR_MODULE else "" 715 | print(f"[1].SS {bbr}") 716 | print(f"[2].SS {bbr}+ v2ray-plugin(ws+tls)") 717 | print(f"[3].SS {bbr}+ Kcptun + UDPspeeder + 单UDP2raw {CEND}{CYELLOW}[默认 游戏推荐]{CEND}{CGREEN}") 718 | print(f"[4].SS {bbr}+ Kcptun + UDPspeeder") 719 | print(f"[5].SS {bbr}+ Kcptun + UDPspeeder + 双UDP2raw") 720 | input_select = input("请输入选项:") 721 | if input_select == "": 722 | print("输入有误,请重新输入") 723 | if input_select == "1": 724 | ss_bbr(server_num, client_offset) 725 | if input_select == "2": 726 | ss_v2ray_ws_tls_bbr(server_num, client_offset, "_v2ray") 727 | if input_select == "3": 728 | ss_kcptun_udpspeeder_udp2raw(server_num, client_offset) 729 | if input_select == "4": 730 | ss_kcptun_udpspeeder(server_num, client_offset) 731 | if input_select == "5": 732 | ss_kcptun_udpspeeder_dual_udp2raw(server_num, client_offset) 733 | if input_select == "0": 734 | print("退出") 735 | break 736 | --------------------------------------------------------------------------------