10
20
2013
5

通过 OpenVPN 让 TCP 使用 UDP 洞

本文来自依云's Blog,转载请注明。

上篇成功让 mosh 走 UDP 洞,连接上了在 NAT 后边的主机。然而,很多有用的协议都是走 TCP 的,比如能传文件的 ssh、访问我的 MediaWiki 的 HTTP。TCP 洞难打,于是在想,OpenVPN 可以使用 UDP 协议,那么把双方用 OpenVPN 连起来,不是可以想用什么传输层的协议都可以了吗!于是,有了新的脚本

与 mosh 相比,打洞部分主要的不同有:

  1. OpenVPN 的可配置性强,不需要 hack 即可让它绑定到需要的端口。
  2. OpenVPN 本身使用证书认证,因此把证书部分保存在客户端,余下的部分(包含双方使用的 IP 地址和端口号)可以通过打好的洞明文发送,不用怕被攻击。所以跑我这个脚本的话,当前工作目录要可写,以便保存双方即将使用的配置文件。
  3. OpenVPN 客户端会自动忽略对方发过来它不认识的配置信息,不用想办法避免。
  4. OpenVPN 需要 root 权限,因此脚本调用了 sudo,需要及时输入密码

在实验过程中也遇到了一些坑:

  1. Python 里没办法将已连接的 UDP socket「断开连接」,即将一个已经connect的 UDP socket 恢复到初始时可接收任意地址数据的状态。原本以为connect(('0.0.0.0', 0))可以的,结果客户端这边始终收不到服务端发送的 OpenVPN 配置信息。Wireshark 抓包看到内核收到数据后发了 ICMP Port Unreachable 错误之后才明白过来。
  2. MTU 的问题。默认值会导致刚开始传输正常,但随后收不到数据的情况。添加mssfix 1400配置解决。(其实这个 OpenVPN man 手册里有写。)
  3. 超时的问题。先是没注意到 OpenVPN 服务端说没有配置keepalive的警告,结果连接空闲几分钟之后,「洞」就失效了。加上keepalive 10 60解决。

配置中没有加默认路由,所以连接上之后唯一的效果就是,两个主机分别多出了同一网段的两个 IP 地址,相互间可以进行 TCP 通信了~~

对了,客户端连接时需要一个包含 OpenVPN 证书信息的文件,其格式为:

<ca>
# ca.crt 文件内容
</ca>

<cert>
# crt 文件内容(只需要 BEGIN 和 END 标记的那部分)
</cert>

<key>
# key 文件内容
</key>

PS: 有这个想法后不久,发现 None 已经做过类似的事情了。不过脚本有点多,是使用第三方服务器而不是像我这样手工交换地址的。

Category: 网络 | Tags: python 网络 OpenVPN UDP | Read Count: 13065
None 说:
Oct 20, 2013 10:06:05 PM

我是想用这玩意,和同学玩 Minecraft 的..
想做成“傻瓜型”所以脚本有点多…

Avatar_small
依云 说:
Oct 20, 2013 10:53:51 PM

你也玩 Minecraft 呀=w=
我是觉得,为了实现自动交换网络地址,专门弄个消息存取服务太浪费了,而且还涉及到认证之类的问题。

None 说:
Oct 20, 2013 11:47:37 PM

自用所以认证什么的都偷懒省掉了..
不过最后还是用家里的路由器做中转了.. 宿舍路由器 PPTP 连回家,家里路由器做 DNAT 来我宿舍的本子…
这样同学那边比较方便.. 所以打洞也没继续完善..
(最近在玩 Terraria~

Sandtears 说:
Oct 21, 2013 08:10:33 AM

感觉既然已经有第三方服务器了... 直接把第三方服务器做成VPN服务器,要打洞的机器都连接到VPN不就好了么 0.0

Avatar_small
依云 说:
Oct 21, 2013 10:44:39 AM

1. 服务器在国外,转来转去延迟很高;
2. 服务器在国外,开 VPN 容易被墙。


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

部分静态文件存储由又拍云存储提供。 | Theme: Aeros 2.0 by TheBuckmaker.com