由于Unbinilium的Twist脚本长时间不更新且已删库,想自己维护但确实不太会写shell脚本,只好把他脚本里的内容一步步写下来,当作日记,也方便自己日后使用。
前置准备
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| cd /tmp
sudo mkdir /etc/twist
sudo apt update sudo apt upgrade
sudo apt install -y wget gawk grep curl sed git gcc swig gettext autoconf automake make libtool perl cpio xmlto asciidoc cron net-tools dnsutils rng-tools libc-ares-dev libev-dev openssl libssl-dev zlib1g-dev libpcre3-dev libevent-dev build-essential python3-dev python3-pip python3-setuptools python3-qrcode nginx fail2ban
route | grep '^default' | grep -o '[^ ]*$'
ip -4 route list 0/0 | grep -Po '(?<=dev )(\S+)'
cat /sys/class/net/eth0/operstate
dig @resolver1.opendns.com -t A -4 myip.opendns.com +short
ip -6 addr show eth0
curl -s diagnostic.opendns.com/myip
cat /sys/class/net/eth0/mtu
|
开启bbr算法
如果内核大于等于4.8,可以直接开启bbr算法,否则可以升级内核后开启
1 2 3 4 5 6
| [ -e /proc/user_beancounters ] && echo "存在" || echo "不存在"
uname -r | grep -oE '[0-9]+\.[0-9]+'
|
内核版本大于等于4.8或者内核已经升级
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| cp /etc/sysctl.conf /etc/twist/sysctl.conf.old-$(date +%Y%m%d%H%M%S)
sudo sysctl net.ipv4.tcp_available_congestion_control
ls /lib/modules/$(uname -r)/kernel/net/ipv4/tcp_bbr.ko*
sudo modprobe tcp_bbr
sed -i '/net.ipv4.tcp_congestion_control/d' /etc/sysctl.conf echo "net.ipv4.tcp_congestion_control = bbr" >> /etc/sysctl.conf
|
更新内核(我没尝试过)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| KERNELURL="https://kernel.ubuntu.com/~kernel-ppa/mainline/" wget -qO- "$KERNELURL" | awk -F'\"v' '/v[4-9]./{print $2}' | cut -d/ -f1 | grep -v - | sort -V | tail -1
dpkg --print-architecture
KERNELVER="$(wget -qO- ${KERNELURL} | awk -F'\"v' '/v[4-9]./{print $2}' | cut -d/ -f1 | grep -v - | sort -V | tail -1)" for pkg in linux-headers linux-headers-all linux-modules linux-image-unsigned; do FILE=$(wget -qO- "${KERNELURL}v${KERNELVER}/" | grep "$pkg" | grep "generic" | grep "amd64.deb" | awk -F'\">' '{print $2}' | cut -d'<' -f1 | head -1) [ -n "$FILE" ] && wget -c "${KERNELURL}v${KERNELVER}/${FILE}" done sudo dpkg -i *.deb sudo update-grub sudo reboot
|
安装shadowsocks-rust
shadowsocks-rust跟shadowsocks-libev不同,不支持xchacha20-ietf-poly1305算法
1 2 3 4 5 6 7 8 9 10
|
curl -LO https://github.com/shadowsocks/shadowsocks-rust/releases/download/v1.24.0/shadowsocks-v1.24.0.x86_64-unknown-linux-gnu.tar.xz
sha256sum shadowsocks-v1.24.0.x86_64-unknown-linux-gnu.tar.xz
tar Jxf shadowsocks-v1.24.0.x86_64-unknown-linux-gnu.tar.xz -C /usr/local/bin
|
创建systemd服务
1 2 3 4 5 6 7 8 9 10 11 12 13
| [Unit] Description=Shadowsocks-Rust Service After=network.target
[Service] Type=simple ExecStart=/usr/local/bin/ssserver -c /etc/shadowsocks-rust/config.json Restart=on-failure LimitNOFILE=512000
[Install] WantedBy=multi-user.target
|
安装simple-obfs:simple-obfs已经不更新了,各大发行版也移除了,但目前还是需要用到
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| git clone https://github.com/shadowsocks/simple-obfs.git
cd simple-obfs
git submodule update --init --recursive
./autogen.sh ./configure --prefix=/usr/local/simple-obfs && make
sudo make install
|
配置shadowsocks-rust
确定监听地址
DNS
密码生成
1 2 3 4 5
| PASSWORD="$(< /dev/urandom tr -dc 'A-HJ-NPR-Za-km-z2-9-._+?%^&*()' | head -c 8)"
PASSWORD="$(ssservice genkey -m "aes-256-gcm")"
|
生成json文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| mkdir -p /etc/shadowsocks-rust
cat > /etc/shadowsocks-rust/config.json <<-EOF { "server":"0.0.0.0", "server_port":443, "password":"${PASSWORD}", "method":"aes-256-gcm", "timeout":1800, "udp_timeout":1800, "plugin":"/usr/local/simple-obfs/bin/obfs-server", "plugin_opts":"obfs=tls;obfs-host=microsoft.com;obfs-uri=/", "fast_open":true, "reuse_port":true, "nofile":512000, "nameserver":"8.8.8.8,8.8.4.4", "dscp":"EF", "mode":"tcp_and_udp", "mtu":1500, "mptcp":false, "ipv6_first":false, "use_syslog":true, "no_delay":true, } EOF
|
配置内核参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
|
cat >> /etc/sysctl.conf <<-EOF
# Twist fs.file-max = 512000 net.core.rmem_max = 67108864 net.core.wmem_max = 67108864 net.core.netdev_max_backlog = 256000 net.core.somaxconn = 4096 net.ipv4.udp_mem = 25600 51200 102400 net.ipv4.tcp_mem = 25600 51200 102400 net.ipv4.tcp_rmem = 4096 87380 67108864 net.ipv4.tcp_wmem = 4096 65536 67108864 net.ipv4.ip_local_port_range = 49152 65535 net.ipv4.tcp_max_syn_backlog = 8192 net.ipv4.tcp_max_tw_buckets = 4096 net.core.default_qdisc = fq net.ipv4.ip_forward = 1 net.ipv4.tcp_window_scaling = 1 net.ipv4.tcp_syncookies = 1 net.ipv4.tcp_timestamps = 1 net.ipv4.tcp_fack = 1 net.ipv4.tcp_sack = 1 net.ipv4.tcp_dsack = 1 net.ipv4.tcp_tw_reuse = 1 net.ipv4.tcp_fwmark_accept = 1 net.ipv4.tcp_stdurg = 1 net.ipv4.tcp_synack_retries = 30 net.ipv4.tcp_syn_retries = 30 net.ipv4.tcp_rfc1337 = 1 net.ipv4.tcp_fin_timeout = 60 net.ipv4.tcp_keepalive_time = 1800 net.ipv4.tcp_mtu_probing = 2 net.ipv4.tcp_fastopen = 3 net.ipv4.tcp_low_latency = 1 net.ipv4.udp_l3mdev_accept = 1 net.ipv4.fib_multipath_hash_policy = 1 net.ipv4.fib_multipath_use_neigh = 1 net.ipv4.cipso_rbm_optfmt = 1 net.ipv4.fwmark_reflect = 1 net.ipv4.conf.all.accept_source_route = 1 net.ipv4.conf.all.accept_redirects = 1 net.ipv4.conf.all.send_redirects = 1 net.ipv4.conf.all.rp_filter = 1 net.ipv4.conf.all.arp_accept = 1 net.ipv4.conf.all.arp_announce = 1 net.ipv4.conf.all.proxy_arp = 1 net.ipv4.conf.all.proxy_arp_pvlan = 1 net.ipv4.conf.all.mc_forwarding = 1 net.ipv6.conf.all.forwarding = 1 net.ipv6.conf.all.accept_source_route = 1 net.ipv6.conf.all.accept_redirects = 1 net.ipv6.conf.all.autoconf = 1 net.ipv6.conf.all.accept_ra = 2 net.ipv6.conf.all.seg6_enabled = 1
EOF
|
配置用户或进程的资源限制
1 2 3 4 5 6 7
| cp /etc/security/limits.conf /etc/security/limits.conf.old-$(date +%Y%m%d%H%M%S)
echo "* soft nofile 512000" >> /etc/security/limits.conf echo "* hard nofile 512000" >> /etc/security/limits.conf echo "" >> /etc/security/limits.conf
|
DNS 配置
1 2 3 4 5 6 7 8 9
| echo "nameserver 8.8.8.8" > /etc/resolv.conf
echo "nameserver 8.8.8.4" >> /etc/resolv.conf
echo "" >> /etc/resolv.conf
|
配置防火墙
ufw
twist用的是iptables,比较专业,但我用ufw比较多,下面是ufw的同等配置
1 2 3 4 5 6 7
| sudo ufw allow 22/tcp
sudo ufw allow 80/tcp sudo ufw allow 80/udp sudo ufw allow 443/tcp sudo ufw allow 443/udp
|
内核参数配置
1 2 3 4
|
net/ipv4/ip_forward=1 net/ipv6/conf/all/forwarding=1
|
细粒度的iptables修改
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
|
*nat :POSTROUTING ACCEPT [0:0] -A POSTROUTING -o ${ETH} -j MASQUERADE COMMIT
-A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
|
启动ufw并设置开机启动
1 2 3 4 5 6
| sudo ufw enable
sudo systemctl enable --now ufw
sudo ufw status verbose
|
iptables
下面是iptables的配置,有点老了,最新的是使用nftables,目前还是兼容的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| iptables-save > /etc/twist/iptables.rules iptables-save > /etc/twist/iptables.rules.old-$(date +%Y%m%d%H%M%S)
iptables -I INPUT -m conntrack --ctstate INVALID -j DROP
iptables -I INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -I INPUT -p tcp -m multiport --dports $PORT -j ACCEPT
iptables -I INPUT -p udp -m multiport --dports $PORT -j ACCEPT
iptables -I INPUT -m state --state NEW -m tcp -p tcp --dport $PORT -j ACCEPT
iptables -I INPUT -m state --state NEW -m udp -p udp --dport $PORT -j ACCEPT
iptables -I FORWARD -m conntrack --ctstate INVALID -j DROP
iptables -I FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
iptables -t nat -A POSTROUTING -o $ETH -j MASQUERADE
iptables-save > /etc/iptables.rules
cp /etc/ip6tables.rules /etc/twist/ip6tables.rules.old-$(date +%Y%m%d%H%M%S)
cp -f /etc/iptables.rules /etc/ip6tables.rules
mkdir -p /etc/network/if-pre-up.d
cp /etc/network/if-pre-up.d/iptablesload /etc/twist/iptablesload.old-$(date +%Y%m%d%H%M%S)
cat > /etc/network/if-pre-up.d/iptablesload <<-EOF #!/bin/sh
iptables-restore < /etc/iptables.rules exit 0
EOF
cp /etc/network/if-pre-up.d/ip6tablesload /etc/twist/ip6tablesload.old-$(date +%Y%m%d%H%M%S)
cat > /etc/network/if-pre-up.d/ip6tablesload <<-EOF #!/bin/sh
ip6tables-restore < /etc/ip6tables.rules exit 0
EOF
|
开机启动
原版
可以忽略,现在用systemd,没怎么用rc.local
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| cp /etc/rc.local /etc/twist/rc.local.old-$(date +%Y%m%d%H%M%S)
cat >> /etc/rc.local <<-EOF
# 但有些发行版或特殊场景(比如 rc.local 早于 sysctl 服务执行),可能会导致参数未及时生效,所以脚本里加 sysctl -q -p 是保险做法,确保参数一定被加载 sysctl -q -p
# 只有在你直接用 iptables 命令自定义规则时,才需要 iptables-save/iptables-restore 来持久化和恢复 iptables-restore < /etc/iptables.rules ip6tables-restore < /etc/ip6tables.rules
# 启动服务 systemctl restart fail2ban cron nginx shadowsocks-rust
exit 0
EOF
|
systemd
1 2 3 4
| sudo systemctl enable --now shadowsocks-rust sudo systemctl enable --now nginx sudo systemctl enable --now fail2ban sudo systemctl enable --now cron
|
打印输出
以下仅供参考,相关变量请改成实际的变量值。如果是http混淆,echo部分也需要做响应修改
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| METHOD=aes-256-gcm PASSWORD=abcdefg PUBLICIP=1.2.3.4 PORT=443 OBFSHOST=microsoft.com OBFSURI=/ OBFS=tls IPV6ENABLE=false PUBLICIPv6=
BASE64=$(echo -n "${METHOD}:${PASSWORD}" | base64 -w 0)
echo "ss://${BASE64}@${PUBLICIP}:${PORT}?plugin=obfs-local;obfs-host=${OBFSHOST};obfs-uri=${OBFSURI};obfs=${OBFS}#Twist" | qr
echo -e "# [\033[32;1mss://\033[0m\033[34;1m$(echo "${BASE64}@${PUBLICIP}:${PORT}?plugin=obfs-local;obfs-host=${OBFSHOST};obfs-uri=${OBFSURI};obfs=${OBFS}#Twist")\033[0m]"
echo -e "# [\033[32;1mServer IP:\033[0m \033[34;1m${PUBLICIP}\033[0m\c" [ ! "$IPV6ENABLE" = "false" ] && echo -e "(\033[34;1m${PUBLICIPv6}\033[0m)\c" echo -e " \033[32;1mPassWord:\033[0m \033[34;1m${PASSWORD}\033[0m \033[32;1mEncryption:\033[0m \033[34;1m${METHOD}\033[0m \033[32;1mOBFS:\033[0m \033[34;1m${OBFS}\033[0m \033[32;1mOBFS-HOST:\033[0m \033[34;1m${OBFSHOST}\033[0m \033[32;1mOBFS-URI:\033[0m \033[34;1m${OBFSURI}\033[0m]"
|
配置Nginx
伪装为微软的服务器
1 2 3 4 5 6 7 8
| # /etc/nginx/sites-enabled/default server { listen 80; server_name _; location / { return 301 http://microsoft.com$request_uri; } }
|
重启nginx
1 2
| nginx -t sudo systemctl restart nginx
|
配置fail2ban
fail2ban自带了很多规则,自己可以根据nginx的日志添加一些,放在/etc/fail2ban/filter.d/下面不过默认的也够了
添加过滤器
1 2 3 4
| # 仅用作参考,默认的够用了 # /etc/fail2ban/filter.d/nginx-badurl.conf [Definition] failregex = <HOST> -.*"(GET|POST|HEAD) (/admin.*)
|
添加jail
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| # /etc/fail2ban/jail.d/nginx-all.local [nginx-bad-request] enabled = true filter = nginx-bad-request port = http,https logpath = /var/log/nginx/access.log backend = auto maxretry = 1 bantime = 86400 findtime = 600
[nginx-botsearch] enabled = true filter = nginx-botsearch port = http,https logpath = /var/log/nginx/access.log backend = auto maxretry = 1 bantime = 86400 findtime = 600
[nginx-http-auth] enabled = true filter = nginx-http-auth port = http,https logpath = /var/log/nginx/error.log backend = auto maxretry = 1 bantime = 86400 findtime = 600
[nginx-limit-req] enabled = true filter = nginx-limit-req port = http,https logpath = /var/log/nginx/error.log backend = auto maxretry = 1 bantime = 86400 findtime = 600
|
重启验证
1 2 3 4
| sudo systemctl restart fail2ban
fail2ban-client status fail2ban-client status nginx-bad-request
|
重启下服务器,完成
注意:国内电信/联通网络的DPI检测很严格,混淆经常失效,目前还在调查原因