384 lines
11 KiB
Markdown
384 lines
11 KiB
Markdown
#### Debian12 封禁中国大陆 IP 访问 40000‑50000 端口
|
||
说明:封禁大陆 IP 段,有两种主流方案:**iptables + ipset(性能好,推荐)**、直接 iptables 批量添加规则(IP 段多,规则膨胀,不推荐)。端口范围:TCP+UDP 40000‑50000。
|
||
|
||
#### 方案一:ipset + iptables(推荐,Debian12)
|
||
1. 安装依赖
|
||
~~~
|
||
apt update
|
||
apt install ipset curl nftables -y
|
||
~~~
|
||
2. 创建 ipset 集合存储中国大陆 IP 段, 创建集合,hash:net 存放网段
|
||
~~~
|
||
ipset create cn_ip hash:net family inet hashsize 1024 maxelem 65536
|
||
~~~
|
||
3. 获取中国大陆 IP 网段并导入 ipset
|
||
~~~
|
||
# 清空旧集合
|
||
ipset flush cn_ip
|
||
# 下载cn网段列表写入ipset
|
||
curl -s https://ftp.apnic.net/stats/apnic/delegated-apnic-latest | awk -F'|' '$2=="CN"&&$3=="ipv4"{printf("add cn_ip %s/%d\n",$4,32-log($5)/log(2))}' | ipset restore
|
||
~~~
|
||
⚠️网络不好时 curl 会失败,可以把文件下载到本地再导入。
|
||
4. iptables 规则:拒绝 cn_ip 集合访问本机 40000‑50000 TCP/UDP
|
||
~~~
|
||
# TCP
|
||
iptables -A INPUT -m set --match-set cn_ip src -p tcp --dport 40000:50000 -j DROP
|
||
# UDP
|
||
iptables -A INPUT -m set --match-set cn_ip src -p udp --dport 40000:50000 -j DROP
|
||
~~~
|
||
5. 持久化 iptables & ipset(Debian12 保存重启不丢失)
|
||
安装`iptables‑persistent`
|
||
~~~
|
||
apt install iptables-persistent -y
|
||
~~~
|
||
> 安装弹窗时选择保存当前 ipv4 规则。
|
||
ipset 默认不会被 persistent 保存,需要写**定时脚本开机重载 CN IP 列表**。
|
||
新建脚本 `/etc/network/if‑pre‑up.d/load‑cn‑ipset`
|
||
~~~
|
||
#!/bin/sh
|
||
ipset create cn_ip hash:net family inet hashsize 1024 maxelem 65536 2>/dev/null
|
||
ipset flush cn_ip
|
||
curl -s https://ftp.apnic.net/stats/apnic/delegated-apnic-latest | awk -F'|' '$2=="CN"&&$3=="ipv4"{printf("add cn_ip %s/%d\n",$4,32-log($5)/log(2))}' | ipset restore
|
||
~~~
|
||
赋予执行权限
|
||
~~~
|
||
chmod +x /etc/network/if-pre-up.d/load-cn-ipset
|
||
~~~
|
||
注意:服务器断网开机时 curl 下载网段会失败,可把网段文件本地缓存,避免依赖网络。
|
||
查看当前规则
|
||
~~~
|
||
iptables -L INPUT -n --line-numbers
|
||
ipset list cn_ip
|
||
~~~
|
||
#### 方案二:nftables(Debian12 默认防火墙,替代 iptables)
|
||
Debian12 默认使用 nftables,如果你在用 nftables,示例配置 `/etc/nftables.conf`
|
||
~~~
|
||
table ip filter {
|
||
set cn_ip {
|
||
type ipv4_addr;
|
||
flags interval;
|
||
auto-merge;
|
||
}
|
||
|
||
chain input {
|
||
type filter hook input priority 0; policy accept;
|
||
ip saddr @cn_ip tcp dport 40000-50000 drop
|
||
ip saddr @cn_ip udp dport 40000-50000 drop
|
||
}
|
||
}
|
||
~~~
|
||
同样需要脚本定期把 APNIC 的 CN 网段填充到`cn_ip`集合。
|
||
|
||
#### ⚠️重要风险提醒
|
||
|
||
1. **如果你自己是国内 IP 远程管理这台机器**:千万不要执行完直接断开 SSH!你的 SSH 端口如果落在 40000‑50000 之外不受影响;如果 SSH 端口在 40000‑50000,执行完直接失联。
|
||
2. APNIC 网段会变动,需要定期更新 ipset 集合,否则部分新分配大陆 IP 无法拦截。
|
||
3. 只拦截**入站**(别人访问本机 40000‑50000);本机向外访问大陆 IP 不受影响。
|
||
4. 云服务器:部分云厂商还有**安全组**,iptables/nftables 生效前提是云安全组没有提前放行。
|
||
|
||
#### ⚠️测试规则是否生效
|
||
|
||
从国内机器:`telnet 服务器IP 40000`,应当连接超时。
|
||
|
||
清理回滚(紧急撤销)
|
||
iptables 版本:
|
||
~~~
|
||
# 查看行号删除对应规则
|
||
iptables -L INPUT -n --line-numbers
|
||
iptables -D INPUT 【行号】
|
||
ipset destroy cn_ip
|
||
~~~
|
||
注意:你现在混用了两套方案:**ipset(iptables)** 和 **nftables**,二者不要混用。截图里你删掉了 `/etc/nftables.conf`,用 nano 编辑它。
|
||
Debian12 默认防火墙是 nftables,下面完整操作流程:
|
||
### 1、先写完 /etc/nftables.conf
|
||
### 检查配置语法(非常关键,防止启动失败锁机)
|
||
~~~
|
||
nft -f /etc/nftables.conf --check
|
||
~~~
|
||
2、启动 & 设置开机自启 nftables
|
||
~~~
|
||
# 启动nftables服务
|
||
systemctl start nftables
|
||
|
||
# 设置开机自动加载配置文件
|
||
systemctl enable nftables
|
||
~~~
|
||
查看运行状态
|
||
~~~
|
||
systemctl status nftables
|
||
~~~
|
||
显示 `active (exited)` 属于正常,nftables 是一次性加载配置的服务。
|
||
|
||
### 查看当前生效规则
|
||
|
||
```
|
||
nft list ruleset
|
||
```
|
||
|
||
3、填充中国大陆 IP 网段到 nftables 的`cn_ip`集合
|
||
> nftables **不能直接用 ipset 命令**,ipset 是 iptables 的组件。需要脚本把 APNIC 网段导入 nftables set。
|
||
|
||
新建脚本 `/usr/local/bin/update-cn-set.sh`
|
||
```
|
||
cat > /usr/local/bin/update-cn-set.sh <<'EOF'
|
||
#!/bin/bash
|
||
TMP=$(mktemp)
|
||
curl -s https://ftp.apnic.net/stats/apnic/delegated-apnic-latest > "$TMP"
|
||
|
||
# 清空集合
|
||
nft flush set ip filter cn_ip
|
||
|
||
# 生成 nftables 合法 add element 语法
|
||
awk -F'|' '$2=="CN"&&$3=="ipv4"{
|
||
len=32 - log($5)/log(2);
|
||
printf "add element ip filter cn_ip { %s/%d }\n", $4, len
|
||
}' "$TMP" | nft -f -
|
||
|
||
rm -f "$TMP"
|
||
EOF
|
||
chmod +x /usr/local/bin/update-cn-set.sh
|
||
```
|
||
|
||
```
|
||
cat > /usr/local/bin/update-cn-set.sh <<'EOF'
|
||
#!/bin/bash
|
||
TMP=$(mktemp)
|
||
curl -s https://raw.githubusercontent.com/misakaio/chnroutes2/master/chnroutes.txt > "$TMP"
|
||
|
||
nft flush set ip filter cn_ip
|
||
|
||
while read -r net; do
|
||
[[ -z "$net" || "$net" =~ ^# ]] && continue
|
||
nft add element ip filter cn_ip { "$net" }
|
||
done < "$TMP"
|
||
|
||
rm -f "$TMP"
|
||
EOF
|
||
chmod +x /usr/local/bin/update-cn-set.sh
|
||
```
|
||
赋予执行权限:
|
||
|
||
```
|
||
chmod +x /usr/local/bin/update-cn-set.sh
|
||
```
|
||
|
||
**手动执行一次,加载 CN 网段:**
|
||
|
||
```
|
||
/usr/local/bin/update-cn-set.sh
|
||
```
|
||
|
||
验证集合是否有网段:
|
||
|
||
```
|
||
nft list set ip filter cn_ip
|
||
```
|
||
|
||
### 设置开机自动加载网段
|
||
|
||
编辑 `/etc/network/if-pre-up.d/update-cn-set`
|
||
|
||
```
|
||
#!/bin/sh
|
||
/usr/local/bin/update-cn-set.sh
|
||
```
|
||
|
||
```
|
||
chmod +x /etc/network/if-pre-up.d/update-cn-set
|
||
```
|
||
|
||
>
|
||
> 开机网络就绪后,自动拉取 CN 网段填充 nftables 集合。
|
||
|
||
## ⚠️重要提醒
|
||
|
||
1. 你之前执行过`ipset create cn_ip`,**nftables 的 set 和 ipset 完全独立**,之前 ipset 命令创建的集合对 nftables 无效,可以删掉:
|
||
|
||
```
|
||
ipset destroy cn_ip
|
||
```
|
||
|
||
2. 不要同时跑 iptables/ipset 和 nftables 两套防火墙。
|
||
3. **云服务器安全组!** 云服务商控制台安全组优先级高于主机 nftables,安全组如果放行 40000‑50000,主机防火墙拦截会失效。
|
||
4. 测试:国内机器访问 40000 端口,应当`connection refused / timeout`。
|
||
|
||
## 如果你想回退,清空所有 nftables 规则
|
||
|
||
```
|
||
nft flush ruleset
|
||
systemctl stop nftables
|
||
systemctl disable nftables
|
||
```
|
||
|
||
## 排查点
|
||
|
||
- `nft -f /etc/nftables.conf --check` 一定要跑,配置写错直接开机会断连。
|
||
- 如果执行`update‑cn‑set.sh`无 IP 写入集合:服务器无法访问 apnic 网站,可以把 delegated‑apnic‑latest 文件下载到本地,修改脚本读取本地文件。
|
||
|
||
### 补充:完整可用 `/etc/nftables.conf` 参考
|
||
|
||
```
|
||
#!/usr/sbin/nft -f
|
||
|
||
flush ruleset
|
||
|
||
table ip filter {
|
||
set cn_ip {
|
||
type ipv4_addr
|
||
flags interval
|
||
auto-merge
|
||
}
|
||
|
||
chain input {
|
||
type filter hook input priority 0; policy accept;
|
||
ip saddr @cn_ip tcp dport 40000-50000 drop
|
||
ip saddr @cn_ip udp dport 40000-50000 drop
|
||
}
|
||
}
|
||
```
|
||
|
||
保存后再执行语法校验。
|
||
|
||
## 如果依然有问题:手动测试单条命令
|
||
|
||
```
|
||
nft add element ip filter cn_ip {1.0.1.0/24}
|
||
```
|
||
|
||
这条命令不报错,说明 nftables 配置文件的`table ip filter`和`set cn_ip`已经正确加载。
|
||
|
||
>
|
||
> 确认 nftables 已经启动:
|
||
|
||
```
|
||
systemctl start nftables
|
||
nft list ruleset
|
||
```
|
||
|
||
## 额外注意
|
||
|
||
1. `nftables.conf`必须完整,table ip filter 以及 set cn_ip 必须存在,否则 add element 会找不到集合。
|
||
2. 如果你服务器访问 apnic 很慢 / 超时,可以把 `delegated‑apnic‑latest` 下载本地,修改脚本读取本地文件。
|
||
3. 不要残留旧 ipset,执行:`ipset destroy cn_ip`
|
||
|
||
### 完整 nftables.conf 再次贴一遍对照
|
||
|
||
```
|
||
#!/usr/sbin/nft -f
|
||
flush ruleset
|
||
|
||
table ip filter {
|
||
set cn_ip {
|
||
type ipv4_addr
|
||
flags interval
|
||
auto-merge
|
||
}
|
||
|
||
chain input {
|
||
type filter hook input priority 0; policy accept;
|
||
ip saddr @cn_ip tcp dport 40000-50000 drop
|
||
ip saddr @cn_ip udp dport 40000-50000 drop
|
||
}
|
||
}
|
||
```
|
||
|
||
修改配置后校验语法:
|
||
|
||
```
|
||
nft -f /etc/nftables.conf --check
|
||
systemctl restart nftables
|
||
```
|
||
|
||
执行完后,`nft list ruleset` 可以看到完整规则。
|
||
|
||
## 配置开机自动填充网段
|
||
|
||
Debian12 `if‑pre‑up.d` 在部分云 vps 网络时序会有问题(网络还没通就运行脚本),改用 **systemd service** 更稳定。
|
||
|
||
创建 systemd 服务文件:
|
||
|
||
```
|
||
cat > /etc/systemd/system/update-cn-ipset.service <<'EOF'
|
||
[Unit]
|
||
Description=Restart nftables && Load CN CIDR into nftables set
|
||
After=network-online.target
|
||
Wants=network-online.target
|
||
|
||
[Service]
|
||
Type=oneshot
|
||
ExecStart=/usr/bin/systemctl restart nftables
|
||
ExecStart=/usr/local/bin/update-cn-set.sh
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
EOF
|
||
```
|
||
|
||
启用开机自启:
|
||
|
||
```
|
||
systemctl daemon-reload
|
||
systemctl enable update-cn-ipset.service
|
||
```
|
||
|
||
>
|
||
> 测试运行这个 systemd 单元:
|
||
|
||
```
|
||
systemctl start update-cn-ipset.service
|
||
systemctl status update-cn-ipset.service
|
||
```
|
||
|
||
## 4、测试效果
|
||
|
||
1. 规则逻辑:**来自中国大陆 IP 访问本机 40000‑50000 端口 (TCP/UDP) 直接丢弃;其他 IP 不受影响;本机对外访问不受限制**。
|
||
2. SSH 端口只要不在 40000‑50000 区间不会被封。
|
||
3. 云服务器:**控制台安全组不能放行 40000‑50000,否则主机防火墙规则被绕过**。
|
||
|
||
## 5、排错
|
||
|
||
- 如果运行脚本卡住:github raw 访问失败。解决方案:预先下载`chnroutes.txt`上传服务器本地,修改脚本把 curl 那一行替换为 `cp /tmp/chnroutes.txt "$TMP"`。
|
||
- 查看 nftables 完整规则依旧是你截图那样,集合内有大量网段 = 整套功能已经就绪。
|
||
|
||
## 快速回退命令
|
||
|
||
```
|
||
#清空所有nftables规则
|
||
nft flush ruleset
|
||
systemctl stop nftables
|
||
systemctl disable nftables
|
||
systemctl disable update-cn-ipset.service
|
||
```
|
||
|
||
---
|
||
|
||
执行完脚本后把 `nft list set ip filter cn_ip` 的结果看一眼,确认有网段就全部完成。
|
||
|
||
### 补充 crontab 定期刷新网段(可选)
|
||
|
||
每周凌晨 2 点更新 CN 网段:
|
||
|
||
```
|
||
crontab -e
|
||
#写入
|
||
0 2 * * 0 /usr/local/bin/update-cn-set.sh
|
||
```
|
||
|
||
>
|
||
> 提醒:raw.githubusercontent 访问不稳定,生产环境建议本地缓存一份`chnroutes.txt`做降级备用。
|
||
|
||
现在执行完后,`nft list set ip filter cn_ip`确认集合内有大量 CN 网段,整套规则就完整可用。
|
||
|
||
~~~
|
||
ipset destroy cn_ip
|
||
nft flush ruleset
|
||
/usr/local/bin/update-cn-set.sh
|
||
nft -f /etc/nftables.conf --check
|
||
systemctl start nftables
|
||
systemctl stop nftables
|
||
systemctl status nftables
|
||
systemctl enable nftables
|
||
systemctl disable nftables
|
||
systemctl restart nftables
|
||
nft list set ip filter cn_ip
|
||
nft list ruleset |