端口敲门(Port Knocking)脚本
什么是端口敲门?
端口敲门是一种网络安全技术,通过按特定顺序”敲击”一系列端口,才能打开目标端口的访问权限。这就像是一种密码锁,只有知道正确的”敲门”顺序,才能获得访问权限。
使用方法
脚本接受两个主要参数:
-allow:要保护的端口(想要最终访问的端口)
-knowk:敲门端口序列(按顺序敲击的端口)
使用示例
1
| bash knockers.sh -allow 22 -knowk 88,99,33,44
|
这个命令表示:
- 保护SSH端口(22)
- 需要按顺序敲击 88→99→33→44 这四个端口才能获得SSH访问权限
脚本源码
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 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
| #!/usr/bin/env bash
_allow=false _knowk=false _allow_values="" _knowk_values=""
while [[ $# -gt 0 ]]; do key="$1" case $key in -allow) _allow=true shift _allow_values="$1" shift ;; -knowk) _knowk=true shift _knowk_values="$1" shift ;; *) echo "Unknown option: $1" shift ;; esac done __main() { mapfile -d , -t _allow_ports < <(echo -n "$_allow_values" | tr -d '\n') mapfile -d , -t _knowk_ports < <(echo -n "$_knowk_values" | tr -d '\n')
echo "allow_ports: ${_allow_ports[*]}" echo "knowk_ports: ${_knowk_ports[*]}"
{
nft delete table inet portknock nft add table inet portknock nft add chain inet portknock input '{ type filter hook input priority -10 ; policy accept ; }'
nft add set inet portknock guarded_ports '{ type inet_service; }' nft add element inet portknock guarded_ports \{ "${_allow_values}" \}
nft add set inet portknock clients_ipv4 '{ type ipv4_addr; flags timeout; }'
nft add set inet portknock clients_ipv6 '{ type ipv6_addr; flags timeout; }'
nft add set inet portknock candidates_ipv4 '{ type ipv4_addr . inet_service; flags timeout; }'
nft add set inet portknock candidates_ipv6 '{ type ipv6_addr . inet_service; flags timeout; }'
nft add chain inet portknock input '{ type filter hook input priority -10; policy accept; }'
nft add rule inet portknock input iifname "lo" return } if [ "${#_knowk_ports[@]}" -eq 1 ]; then nft add rule inet portknock input tcp dport "${_knowk_ports[0]}" add @clients_ipv4 '{ ip saddr timeout 10s }' log prefix '"Successful portknock: "' nft add rule inet portknock input tcp dport "${_knowk_ports[0]}" add @clients_ipv6 '{ ip6 saddr timeout 10s }' log prefix '"Successful portknock: "' else for item in $(seq 0 $((${#_knowk_ports[@]} - 1))); do case "${item}" in 0) nft add rule inet portknock input tcp dport "${_knowk_ports[$item]}" add @candidates_ipv4 \{ ip saddr . "${_knowk_ports[item + 1]}" timeout 10s \} nft add rule inet portknock input tcp dport "${_knowk_ports[$item]}" add @candidates_ipv6 \{ ip6 saddr . "${_knowk_ports[item + 1]}" timeout 10s \} ;; "$((${#_knowk_ports[@]} - 1))") nft add rule inet portknock input tcp dport "${_knowk_ports[$item]}" ip saddr . tcp dport @candidates_ipv4 add @clients_ipv4 '{ ip saddr timeout 10s }' log prefix '"Successful portknock: "' nft add rule inet portknock input tcp dport "${_knowk_ports[$item]}" ip6 saddr . tcp dport @candidates_ipv6 add @clients_ipv6 '{ ip6 saddr timeout 10s }' log prefix '"Successful portknock: "' ;; *) nft add rule inet portknock input tcp dport "${_knowk_ports[$item]}" ip saddr . tcp dport @candidates_ipv4 add @candidates_ipv4 \{ ip saddr . "${_knowk_ports[item + 1]}" timeout 10s \} nft add rule inet portknock input tcp dport "${_knowk_ports[$item]}" ip6 saddr . tcp dport @candidates_ipv6 add @candidates_ipv6 \{ ip6 saddr . "${_knowk_ports[item + 1]}" timeout 10s \} ;; esac done fi
{ nft add rule inet portknock input tcp dport @guarded_ports ip saddr @clients_ipv4 counter accept nft add rule inet portknock input tcp dport @guarded_ports ip6 saddr @clients_ipv6 counter accept nft add rule inet portknock input tcp dport @guarded_ports ct state established,related counter accept nft add rule inet portknock input tcp dport @guarded_ports counter reject with tcp reset } } __main
__help() { bash /apps/data/workspace/default/shell/knockers/knockers.sh -allow 22 -knowk 88,99,33,44 }
|
工作原理简介
- 脚本创建一个nftables防火墙表和规则集
- 设置受保护的端口(如SSH 22端口)
- 定义”敲门”顺序(如 88→99→33→44)
- 当客户端按正确顺序敲击这些端口时,其IP地址会被临时加入白名单(10秒有效期)
- 白名单内的IP可以访问受保护的端口,其他IP则被拒绝
实际应用场景
此脚本适合用于保护服务器的敏感端口(如SSH)不被随意扫描和暴力破解。即使攻击者知道你的SSH端口,没有正确的”敲门”序列也无法连接。
优点
- 同时支持IPv4和IPv6
- 可设置单个或多个敲门端口
- 白名单有超时机制,增强安全性
- 成功敲门会记录日志