China IP

China IP

China IP 是指分配给中国的所有 IP 段(通常指 IPV4)。由于中国网络的特殊性,很多应用场景都需要中国 IP 段。

获取中国 IP 段列表

有以下几种方法

从 ipdeny 获取

分配给中国的所有 IPV4 段最新数据可以从 ipdeny 获取:

cn-aggregated.zone (聚合版数据,数量更少,匹配快。推荐)
cn.zone

获取的文件内容格式:

1.0.1.0/24
1.0.2.0/23
1.0.8.0/21
...

这个方式的问题是获取的只是“归属地”为中国的IP,而不是真正地理位置是中国的IP。用来判断是否走代理会有误差。

从 APNIC 获取

APNIC (亚太互联网络信息中心) 公开提供所有亚洲国家的 IPV4 分配信息,可以从以下地址获取:

http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest

获取的文件格式如下,文件里有每行有几个字段,以 "|" 作为分隔符。文件格式说明

# comments
apnic|JP|asn|3391|1|20020801|allocated
apnic|AU|asn|3395|1|20020801|allocated
apnic|CN|asn|3460|1|20020801|allocated
...

需要解析处理该文件才能得到中国 IP 信息。chnroutes 项目提供一个 python 脚本能够自动从 APNIC 获取该文件、解析,然后直接写入系统路由表。

订阅第三方维护的中国IP源

Github 上有很多中国IP源,数据来源不一。

  • chn-iplist : 数据来源于 APNIC Delegated List

策略路由

通过 Linux 策略路由实现直连中国 IP,通常用于全局 VPN / 代理环境。具体也有两种方法。

  1. 使用 ipset + iptables
  2. 使用 ip route

ipset + iptables 策略路由直连中国 IP

将所有中国 IP 段 存入一个 ipset,并对 dst IP 属于这个 ipset 里的所有流量写入 mark bit 0 = 1,然后做策略路由,使这些流量走系统默认路由(主路由表)

设备启动脚本:

#!/bin/sh

cd /root

# wget -P . http://www.ipdeny.com/ipblocks/data/countries/cn.zone
ipset create cn hash:net
for i in $(cat ./cn.zone ); do ipset -A cn $i; done

iptables -t mangle -I PREROUTING -m set --match-set cn dst -j MARK --set-mark 0x1/0x1
iptables -t mangle -I OUTPUT -m set --match-set cn dst -j MARK --set-mark 0x1/0x1
ip rule add fwmark 0x1/0x1 lookup main prio 1

与使用 "ip route 添加路由表"方式 相比,这种方法优点:

  • 只需要在设备启动时执行一次脚本即可。而 ip route 方式需要在每次宽带拨号连接 (PPPoE)后都执行一次脚本(因为每次宽带重新连接后默认网关都会改变)。

缺点:

  • ipset (好像)无法批量添加,执行一次添加全部中国 IP 段(几千条记录)操作需要近1分钟时间。而 ip route batch 批量添加路由仅需1秒。

ip route 添加中国 IP 直连路由表

可以参考 chnroutes 提供的 python 脚本。建议将所有中国 IP 单独放在一个路由表里,然后用 ip rule 添加使用这个独立路由表规则(将其优先级设置为高于其他自定义的 VPN 路由表),例如:

设备启动脚本:

ip rule add lookup 4 prio 4

宽带 PPPoE 拨号成功脚本:(因为每次宽带重新连接后默认网关会发生变化,所以必须重新添加中国 IP 路由表)

#!/bin/sh

# 获取设备当前默认网关
GW=$(ip route show 0/0 | head -n1 | grep 'via' | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+')

ip -batch - <<EOF
route add 1.0.1.0/24 via $GW table 4
route add 1.0.2.0/23 via $GW table 4
# more ...
EOF

iptables 中国IP跳过透明代理

如果在 iptables -t nat 的 PREROUTING / OUTPUT 链上用 redsocks / clash / ss-redir 等做了透明代理,可以设置跳过中国 IP:

iptables -t mangle -I PREROUTING -m set --match-set cn dst -j ACCEPT
iptables -t nat -I prerouting_wan_rule -m set --match-set cn dst -j ACCEPT
iptables -t nat -I prerouting_lan_rule -m set --match-set cn dst -j ACCEPT

说明:

  • 加在 -t mangle -I PREROUTING 的规则是为了跳过某些代理工具的 TPROXY udp 透明代理。
  • prerouting_wan_rule 和 prerouting_lan_rule 是 OpenWrt firewall创建和维护的子链。(子链里必须用 ACCEPT 不能用 RETURN, 因为 RETURN 仅仅停止遍历子链,还会继续遍历父链)

应用场景

配合全局 VPN 使用

设备启动脚本

假设 VPN 启动时把默认路由加到 table 10 的路由表里

# 通用 VPN iptables 规则
iptables -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN  -j TCPMSS --clamp-mss-to-pmtu
iptables -t nat -A POSTROUTING -o tun+ -s 192.168.0.0/16 -j MASQUERADE
iptables -t nat -A POSTROUTING -o tun+ -s 10.0.0.0/8 -j MASQUERADE

# 以下需要 iptables-mod-conntrack-extra 和 kmod-ipt-conntrack-extra
# 使对数据包打的mark对于同一连接的其他数据包(回程或相关的)也生效
iptables -I PREROUTING -t mangle  -j CONNMARK --restore-mark
iptables -I POSTROUTING -t mangle -j CONNMARK --save-mark

ip rule add to 192.168.0.0/16 lookup main prio 1
ip rule add to 127.0.0.1/8 lookup main prio 1
ip rule add to 10.0.0.1/8 lookup main prio 1
# VPN server IP
ip rule add to 1.2.3.4/32 lookup main prio 1
ip rule add lookup 10 prio 10
# now sart vpn
# /root/startvpn.sh

VPN 启动成功脚本

ip route add default via 192.168.10.1 table 10
# ip route add default dev tun0 table 10

Tips

  • 不要忘了设置 "net.ipv4.ip_forward=1" 内核参数。(路由器之类的设备应该默认开启了这个参数)

Last update: 2020-08-03 04:15:51 UTC