VPN翻墙与P2P下载

#假装懂技术
#GFW促进学习

在路由器上部署了VPN Client和chnroutes后,连接到国外VPS的VPN Server后,整个区域网内所有设备能够透明翻墙,但是一些P2P软体会遇到问题。

P2P软体需要监听固定埠,并且需要外网的机器能够主动连接到运行P2P软体内网机器。方法是用路由器的“埠映射”功能,将公网IP的某些埠映射到内网某个机器上。这是通过iptables的DNAT实现的:

假设在路由器管理界面中将10400-10499埠映射到192.168.0.4,路由器会添加下面的iptables规则(由于WAN IP通常不是固定的,路由器会在ppp拨号或DHCP获得公网IP后动态添加这些规则):

iptables -t NAT -A PREROUTING -d  -p tcp --dport 10400:10499 -j DNAT --to 192.168.0.4
iptables -t NAT -A PREROUTING -d  -p udp --dport 10400:10499 -j DNAT --to 192.168.0.4

但是部署OpenVPN和chnroutes后,国外的IP就不能主动和内网机器建立连接了(即使已经按照上面方法在路由器上开启了埠映射),因为这时国外IP看到的是VPS的IP,不是路由器的公网IP。

要使路由器部署VPN时仍然支持内网P2P下载和其它需要外网埠的应用,需要在VPS和路由器上同时增加新的iptables DNAT规则。

首先,需要知道路由器所使用的OpenVPN客户端证书的(X509) common name,这个common name是在生成证书时指定的,OpenVPN easy-rsa创建证书时默认使用文件名作为common name。可以在证书crt文件中查看其common name

[email protected]:/etc/openvpn/easy-rsa/keys# cat client-common.crt
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 10 (0xa)
    Signature Algorithm: sha1WithRSAEncryption
        Issuer: C=US, ST=CA, L=SanFrancisco, O=SAGAN, OU=SAGAN, CN=SAGAN/name=SAGAN/[email protected]
        Validity
            Not Before: Jan 11 02:36:33 2013 GMT
            Not After : Jan  9 02:36:33 2023 GMT
        Subject: C=US, ST=CA, L=SanFrancisco, O=SAGAN, OU=SAGAN, CN=client-common/name=SAGAN/[email protected]
.....

证书的Subject行里的CN栏位就是common name,如上面例子证书的common name就是”client-common”

路由器的VPN Client必须具有固定IP(不能是Server通过DHCP分配的动态IP)。OpenVPN伺服器可以通过下面方式实现给某个客户端分配固定IP

假设VPS的openvpn伺服器端配置文件位于/etc/openvpn,在这个目录下创建一个”clients”目录.

编辑OpenVPN伺服器端配置文件server.conf,加入下面内容

client-config-dir clients

在刚刚创建的/etc/openvpn/clients目录下新建一个”client-common”文件(无扩展名),文件名就是路由器使用的证书的common name。这个文件用于给路由器的VPN Client分配固定IP,内容只有一行:

#假设你的OpenVPN虚拟网段是192.168.200.0/24
ifconfig-push 192.168.200.2 255.255.255.0

这样做以后,路由器的OpenVPN Client连接后会自动获取到192.168.200.2这个固定IP。

PS. 另一种让路由器的OpenVPN客户端获取固定IP的方法是OpenVPN的static key模式。

配置好OpenVPN后只需要在VPS和路由器上分别添加iptables DNAT规则即可。规则如下。

# 下面代码中
# A.B.C.D是VPS的公网IP
# 192.168.200.0/24是OpenVPN的网段
# 192.168.200.2是路由器OpenVPN Client获得的IP
# 192.168.0.0/24是路由器所在的本地内网网段
# 192.168.0.1是路由器内网IP

# VPS上的iptables规则
iptables -t nat -A PREROUTING -p tcp -d A.B.C.D --dport 10000:20000 -j DNAT --to 192.168.200.2
iptables -t nat -A PREROUTING -p udp -d A.B.C.D --dport 10000:20000 -j DNAT --to 192.168.200.2

# 路由器上的iptables规则
iptables -t nat -A PREROUTING -p tcp -d 192.168.200.2 --dport 10400:10499 -j DNAT --to 192.168.0.4
iptables -t nat -A PREROUTING -p udp -d 192.168.200.2 --dport 10400:10499 -j DNAT --to 192.168.0.4

上面的iptables规则把VPS的10000-20000埠全部转发给路由器,然后路由器再做一次DNAT,把这些埠任意分配给内网机器。如上面的示例把10400-10499映射到192.168.0.4,可以再把10500-10599映射给192.168.0.5,依此类推。

数据流向: 192.168.0.4:10401与某个Internet IP W.X.Y.Z:abc通信:

W.X.Y.Z:abc 向 A.B.C.D:10401发起连接 ->
  src W.X.Y.Z:abc dst A.B.C.D:10401

VPS DNAT ->
  src W.X.Y.Z:abc dst 192.168.200.2:10401

Router DNAT ->
  src W.X.Y.Z:abc dst 192.168.0.4:14001

192.168.0.4:10401 received


反方向:


192.168.0.4:10401 回应 W.X.Y.Z:abc
  src 192.168.0.4:10401 dst W.X.Y.Z;abc

Router Un DNAT
  src 192.168.200.2:10401 dst W.X.Y.Z:abc

VPS Un DNAT
  src A.B.C.D:10401 dst W.X.Y.Z:abc

W.X.Y.Z:abc reveived

Un DNAT(DNAT的Reverse)是自动的

注意,使用这种方法下载国外的P2P资源(如share)有版权风险,可能导致VPS被封 = =

PS. 还有一种路由器部署VPN时内网机器下载国外P2P资源的方法,就是在路由器上做策略路由(policy routing),用iptables给P2P数据包打标记(MARK),然后ip rule创建规则对这些数据包走默认网关。但是因为GFW现在连P2P连接也会reset(比如用emule搜索某个敏感关键字文件时),不推荐此方法。