mirror of
https://github.com/juewuy/ShellCrash.git
synced 2026-03-11 07:51:45 +00:00
~修复部分调用工具或者界面报错的bug ~修复bot_tg胡乱推送消息以及可能多进程同时存在的bug ~修复nftables启动报错 ~修复Tailscale无法正确启用域名嗅探以及dns劫持失效的bug
220 lines
12 KiB
Bash
220 lines
12 KiB
Bash
#!/bin/sh
|
|
# Copyright (C) Juewuy
|
|
|
|
RESERVED_IP=$(echo $reserve_ipv4 | sed 's/ /, /g')
|
|
RESERVED_IP6=$(echo "$reserve_ipv6 $host_ipv6" | sed 's/ /, /g')
|
|
|
|
add_ip6_route(){
|
|
#过滤保留地址及本机地址
|
|
nft add rule inet shellcrash $1 ip6 daddr {$RESERVED_IP6} return
|
|
#仅代理本机局域网网段流量
|
|
nft add rule inet shellcrash $1 ip6 saddr != {$HOST_IP6} return
|
|
#绕过CN_IPV6
|
|
[ "$dns_mod" != "fake-ip" -a "$cn_ip_route" = "已开启" -a -f "$BINDIR"/cn_ipv6.txt ] && {
|
|
CN_IP6=$(awk '{printf "%s, ",$1}' "$BINDIR"/cn_ipv6.txt)
|
|
[ -n "$CN_IP6" ] && {
|
|
nft add set inet shellcrash cn_ip6 { type ipv6_addr \; flags interval \; }
|
|
nft add element inet shellcrash cn_ip6 { $CN_IP6 }
|
|
nft add rule inet shellcrash $1 ip6 daddr @cn_ip6 return
|
|
}
|
|
}
|
|
}
|
|
start_nft_route() { #nftables-route通用工具
|
|
#$1:name $2:hook(prerouting/output) $3:type(nat/mangle/filter) $4:priority(-100/-150)
|
|
[ "$common_ports" = "已开启" ] && PORTS=$(echo $multiport | sed 's/,/, /g')
|
|
[ "$1" = 'prerouting' ] && HOST_IP=$(echo $host_ipv4 | sed 's/ /, /g')
|
|
[ "$1" = 'output' ] && HOST_IP="127.0.0.0/8, $(echo $local_ipv4 | sed 's/ /, /g')"
|
|
[ "$1" = 'prerouting_vm' ] && HOST_IP="$(echo $vm_ipv4 | sed 's/ /, /g')"
|
|
#添加新链
|
|
nft add chain inet shellcrash $1 { type $3 hook $2 priority $4 \; }
|
|
[ "$1" = 'prerouting_vm' ] && nft add rule inet shellcrash $1 ip saddr != {$HOST_IP} return #仅代理虚拟机流量
|
|
#过滤dns
|
|
nft add rule inet shellcrash $1 tcp dport 53 return
|
|
nft add rule inet shellcrash $1 udp dport 53 return
|
|
#防回环
|
|
nft add rule inet shellcrash $1 meta mark $routing_mark return
|
|
nft add rule inet shellcrash $1 meta skgid 7890 return
|
|
[ "$firewall_area" = 5 ] && nft add rule inet shellcrash $1 ip saddr $bypass_host return
|
|
[ -z "$ports" ] && nft add rule inet shellcrash $1 tcp dport {"$mix_port, $redir_port, $tproxy_port"} return
|
|
#过滤常用端口
|
|
[ -n "$PORTS" ] && {
|
|
nft add rule inet shellcrash $1 ip daddr != {28.0.0.0/8} tcp dport != {$PORTS} return
|
|
nft add rule inet shellcrash $1 ip daddr != {28.0.0.0/8} udp dport != {$PORTS} return
|
|
nft add rule inet shellcrash $1 ip6 daddr != {fc00::/16} tcp dport != {$PORTS} return
|
|
nft add rule inet shellcrash $1 ip6 daddr != {fc00::/16} udp dport != {$PORTS} return
|
|
}
|
|
#nft add rule inet shellcrash $1 ip saddr 28.0.0.0/8 return
|
|
nft add rule inet shellcrash $1 ip daddr {$RESERVED_IP} return #过滤保留地址
|
|
#过滤局域网设备
|
|
[ "$1" = 'prerouting' ] && {
|
|
[ "$macfilter_type" != "白名单" ] && {
|
|
[ -s "$CRASHDIR"/configs/mac ] && {
|
|
MAC=$(awk '{printf "%s, ",$1}' "$CRASHDIR"/configs/mac)
|
|
nft add rule inet shellcrash $1 ether saddr {$MAC} return
|
|
}
|
|
[ -s "$CRASHDIR"/configs/ip_filter ] && {
|
|
FL_IP=$(awk '{printf "%s, ",$1}' "$CRASHDIR"/configs/ip_filter)
|
|
nft add rule inet shellcrash $1 ip saddr {$FL_IP} return
|
|
}
|
|
nft add rule inet shellcrash $1 ip saddr != {$HOST_IP} return #仅代理本机局域网网段流量
|
|
}
|
|
[ "$macfilter_type" = "白名单" ] && {
|
|
[ -s "$CRASHDIR"/configs/mac ] && MAC=$(awk '{printf "%s, ",$1}' "$CRASHDIR"/configs/mac)
|
|
[ -s "$CRASHDIR"/configs/ip_filter ] && FL_IP=$(awk '{printf "%s, ",$1}' "$CRASHDIR"/configs/ip_filter)
|
|
if [ -n "$MAC" ] && [ -n "$FL_IP" ]; then
|
|
nft add rule inet shellcrash $1 ether saddr != {$MAC} ip saddr != {$FL_IP} return
|
|
elif [ -n "$MAC" ]; then
|
|
nft add rule inet shellcrash $1 ether saddr != {$MAC} return
|
|
elif [ -n "$FL_IP" ]; then
|
|
nft add rule inet shellcrash $1 ip saddr != {$FL_IP} return
|
|
else
|
|
nft add rule inet shellcrash $1 ip saddr != {$HOST_IP} return #仅代理本机局域网网段流量
|
|
fi
|
|
}
|
|
}
|
|
#绕过CN-IP
|
|
[ "$dns_mod" != "fake-ip" -a "$cn_ip_route" = "已开启" -a -f "$BINDIR"/cn_ip.txt ] && {
|
|
CN_IP=$(awk '{printf "%s, ",$1}' "$BINDIR"/cn_ip.txt)
|
|
[ -n "$CN_IP" ] && {
|
|
nft add set inet shellcrash cn_ip { type ipv4_addr \; flags interval \; }
|
|
nft add element inet shellcrash cn_ip { $CN_IP }
|
|
nft add rule inet shellcrash $1 ip daddr @cn_ip return
|
|
}
|
|
}
|
|
#局域网ipv6支持
|
|
if [ "$ipv6_redir" = "已开启" -a "$1" = 'prerouting' -a "$firewall_area" != 5 ]; then
|
|
HOST_IP6=$(echo $host_ipv6 | sed 's/ /, /g')
|
|
add_ip6_route "$1"
|
|
elif [ "$ipv6_redir" = "已开启" -a "$1" = 'output' -a \( "$firewall_area" = 2 -o "$firewall_area" = 3 \) ]; then
|
|
HOST_IP6="::1, $(echo $host_ipv6 | sed 's/ /, /g')"
|
|
add_ip6_route "$1"
|
|
else
|
|
nft add rule inet shellcrash $1 meta nfproto ipv6 return
|
|
fi
|
|
#添加通用路由
|
|
nft add rule inet shellcrash "$1" "$JUMP"
|
|
#处理特殊路由
|
|
[ "$redir_mod" = "混合模式" ] && {
|
|
nft add rule inet shellcrash $1 meta l4proto tcp mark set $((fwmark + 1))
|
|
nft add chain inet shellcrash "$1"_mixtcp { type nat hook $2 priority -100 \; }
|
|
nft add rule inet shellcrash "$1"_mixtcp mark $((fwmark + 1)) meta l4proto tcp redirect to $redir_port
|
|
}
|
|
#nft add rule inet shellcrash local_tproxy log prefix \"pre\" level debug
|
|
}
|
|
start_nft_dns() { #nftables-dns
|
|
[ "$1" = 'prerouting' ] && {
|
|
HOST_IP=$(echo $host_ipv4 | sed 's/ /, /g')
|
|
HOST_IP6=$(echo $host_ipv6 | sed 's/ /, /g')
|
|
}
|
|
[ "$1" = 'output' ] && HOST_IP="127.0.0.0/8, $(echo $local_ipv4 | sed 's/ /, /g')"
|
|
[ "$1" = 'prerouting_vm' ] && HOST_IP="$(echo $vm_ipv4 | sed 's/ /, /g')"
|
|
nft add chain inet shellcrash "$1"_dns { type nat hook $2 priority -100 \; }
|
|
#过滤非dns请求
|
|
nft add rule inet shellcrash "$1"_dns udp dport != 53 return
|
|
nft add rule inet shellcrash "$1"_dns tcp dport != 53 return
|
|
#防回环
|
|
nft add rule inet shellcrash "$1"_dns meta mark $routing_mark return
|
|
nft add rule inet shellcrash "$1"_dns meta skgid { 453, 7890 } return
|
|
[ "$firewall_area" = 5 ] && nft add rule inet shellcrash "$1"_dns ip saddr $bypass_host return
|
|
nft add rule inet shellcrash "$1"_dns ip saddr != {$HOST_IP} return #屏蔽外部请求
|
|
[ "$1" = 'prerouting' ] && nft add rule inet shellcrash "$1"_dns ip6 saddr != {$HOST_IP6} return #屏蔽外部请求
|
|
#过滤局域网设备
|
|
[ "$1" = 'prerouting' ] && [ -s "$CRASHDIR"/configs/mac ] && {
|
|
MAC=$(awk '{printf "%s, ",$1}' "$CRASHDIR"/configs/mac)
|
|
if [ "$macfilter_type" = "黑名单" ]; then
|
|
nft add rule inet shellcrash "$1"_dns ether saddr {$MAC} return
|
|
else
|
|
nft add rule inet shellcrash "$1"_dns ether saddr != {$MAC} return
|
|
fi
|
|
}
|
|
nft add rule inet shellcrash "$1"_dns udp dport 53 redirect to ${dns_port}
|
|
nft add rule inet shellcrash "$1"_dns tcp dport 53 redirect to ${dns_port}
|
|
}
|
|
start_nft_wan() { #nftables公网防火墙
|
|
HOST_IP=$(echo $host_ipv4 | sed 's/ /, /g')
|
|
HOST_IP6=$(echo $host_ipv6 | sed 's/ /, /g')
|
|
nft add chain inet shellcrash input { type filter hook input priority -100 \; }
|
|
nft add rule inet shellcrash input iif lo accept #本机请求全放行
|
|
#端口放行
|
|
[ -f "$CRASHDIR"/configs/gateway.cfg ] && . "$CRASHDIR"/configs/gateway.cfg
|
|
accept_ports=$(echo "$fw_wan_ports,$vms_port,$sss_port" | sed "s/,,/,/g ;s/^,// ;s/,$// ;s/,/, /")
|
|
[ -n "$accept_ports" ] && {
|
|
fw_wan_nfports="{ $(echo "$accept_ports" | sed 's/,/, /g') }"
|
|
nft add rule inet shellcrash input tcp dport $fw_wan_nfports accept
|
|
nft add rule inet shellcrash input udp dport $fw_wan_nfports accept
|
|
}
|
|
#端口拦截
|
|
reject_ports="{ $mix_port, $db_port, $dns_port }"
|
|
nft add rule inet shellcrash input ip saddr {$HOST_IP} accept
|
|
nft add rule inet shellcrash input ip6 saddr {$HOST_IP6} accept
|
|
nft add rule inet shellcrash input tcp dport $reject_ports reject
|
|
nft add rule inet shellcrash input udp dport $reject_ports reject
|
|
}
|
|
start_nftables() { #nftables配置总入口
|
|
#初始化nftables
|
|
nft add table inet shellcrash 2>/dev/null
|
|
nft flush table inet shellcrash 2>/dev/null
|
|
#公网访问防火墙
|
|
[ "$fw_wan" != OFF ] && [ "$systype" != 'container' ] && start_nft_wan
|
|
#启动DNS劫持
|
|
[ "$dns_no" != "已禁用" -a "$dns_redir" != "已开启" -a "$firewall_area" -le 3 ] && {
|
|
[ "$lan_proxy" = true ] && start_nft_dns prerouting prerouting #局域网dns转发
|
|
[ "$local_proxy" = true ] && start_nft_dns output output #本机dns转发
|
|
}
|
|
#分模式设置流量劫持
|
|
[ "$redir_mod" = "Redir模式" ] && {
|
|
JUMP="meta l4proto tcp redirect to $redir_port" #跳转劫持的具体命令
|
|
[ "$lan_proxy" = true ] && start_nft_route prerouting prerouting nat -100
|
|
[ "$local_proxy" = true ] && start_nft_route output output nat -100
|
|
}
|
|
[ "$redir_mod" = "Tproxy模式" ] && (modprobe nft_tproxy >/dev/null 2>&1 || lsmod 2>/dev/null | grep -q nft_tproxy) && {
|
|
JUMP="meta l4proto {tcp, udp} mark set $fwmark tproxy to :$tproxy_port" #跳转劫持的具体命令
|
|
[ "$lan_proxy" = true ] && start_nft_route prerouting prerouting filter -150
|
|
[ "$local_proxy" = true ] && {
|
|
JUMP="meta l4proto {tcp, udp} mark set $fwmark" #跳转劫持的具体命令
|
|
start_nft_route output output route -150
|
|
nft add chain inet shellcrash mark_out { type filter hook prerouting priority -100 \; }
|
|
nft add rule inet shellcrash mark_out meta mark $fwmark meta l4proto {tcp, udp} tproxy to :$tproxy_port
|
|
}
|
|
}
|
|
[ "$tun_statu" = true ] && {
|
|
[ "$redir_mod" = "Tun模式" ] && JUMP="meta l4proto {tcp, udp} mark set $fwmark" #跳转劫持的具体命令
|
|
[ "$redir_mod" = "混合模式" ] && JUMP="meta l4proto udp mark set $fwmark" #跳转劫持的具体命令
|
|
[ "$lan_proxy" = true ] && {
|
|
start_nft_route prerouting prerouting filter -150
|
|
#放行流量
|
|
nft list table inet fw4 >/dev/null 2>&1 || nft add table inet fw4
|
|
nft list chain inet fw4 forward >/dev/null 2>&1 || nft add chain inet fw4 forward { type filter hook forward priority filter \; } 2>/dev/null
|
|
nft list chain inet fw4 input >/dev/null 2>&1 || nft add chain inet fw4 input { type filter hook input priority filter \; } 2>/dev/null
|
|
nft list chain inet fw4 forward | grep -q 'oifname "utun" accept' || nft insert rule inet fw4 forward oifname "utun" accept
|
|
nft list chain inet fw4 input | grep -q 'iifname "utun" accept' || nft insert rule inet fw4 input iifname "utun" accept
|
|
}
|
|
[ "$local_proxy" = true ] && start_nft_route output output route -150
|
|
}
|
|
[ "$firewall_area" = 5 ] && {
|
|
[ "$redir_mod" = "T&U旁路转发" ] && JUMP="meta l4proto {tcp, udp} mark set $fwmark" #跳转劫持的具体命令
|
|
[ "$redir_mod" = "TCP旁路转发" ] && JUMP="meta l4proto tcp mark set $fwmark" #跳转劫持的具体命令
|
|
[ "$lan_proxy" = true ] && start_nft_route prerouting prerouting filter -150
|
|
[ "$local_proxy" = true ] && start_nft_route output output route -150
|
|
}
|
|
[ "$vm_redir" = "已开启" ] && [ -n "$$vm_ipv4" ] && {
|
|
start_nft_dns prerouting_vm prerouting
|
|
JUMP="meta l4proto tcp redirect to $redir_port" #跳转劫持的具体命令
|
|
start_nft_route prerouting_vm prerouting nat -100
|
|
}
|
|
#屏蔽QUIC
|
|
[ "$quic_rj" = '已启用' -a "$lan_proxy" = true ] && {
|
|
[ "$redir_mod" = "Tproxy模式" ] && {
|
|
nft add chain inet shellcrash quic_rj { type filter hook input priority 0 \; }
|
|
[ -n "$CN_IP" ] && nft add rule inet shellcrash quic_rj ip daddr @cn_ip return
|
|
[ -n "$CN_IP6" ] && nft add rule inet shellcrash quic_rj ip6 daddr @cn_ip6 return
|
|
nft add rule inet shellcrash quic_rj udp dport {443, 8443} reject comment 'ShellCrash-QUIC-REJECT'
|
|
}
|
|
[ "$redir_mod" = "Tun模式" -o "$redir_mod" = "混合模式" ] && {
|
|
nft insert rule inet fw4 forward oifname "utun" udp dport {443, 8443} reject comment 'ShellCrash-QUIC-REJECT'
|
|
[ -n "$CN_IP" ] && nft insert rule inet fw4 forward oifname "utun" ip daddr { $CN_IP } return
|
|
[ -n "$CN_IP6" ] && nft insert rule inet fw4 forward oifname "utun" ip6 daddr { $CN_IP6 } return
|
|
}
|
|
}
|
|
}
|