KoolShare

 找回密码
 立即注册
搜索
查看: 5244|回复: 16

ThisWay#1: 内网穿透 + 端口转发的另一种操作

[复制链接]

31

主题

1079

帖子

1万

积分

大魔导师

Rank: 9Rank: 9Rank: 9

精华
1
门户文章
3
魔力币
3148
魔法值
45
注册时间
2015-11-8

R7000DDOS纪念勋章

发表于 2018-4-7 16:28:18 | 显示全部楼层 |阅读模式
本帖最后由 updateing 于 2018-4-7 16:28 编辑

好久没有发主题帖了,最近研究了点新东西,来水一帖

自从自己拉了条宽带结果发现 v6 爆炸、v4 内网以后,就一直在研究如何优雅地实现内网穿透。目前常见的内网穿透大多是用 frp、ngrok,但个人觉得数据转发这种没有用户态程序交互需求的事情,应该在内核中直接完成,没必要到用户态绕一圈。并且 TCP 直接穿透时服务器程序无法得知原始访问者的 IP,这使得统计数据和访问控制都难以处理,被人黑了都没日志能看论坛上还经常能看到这俩程序掉线的帖子,就觉得更加不优雅了……

那么,怎样才能实现一个优雅一些的内网穿透呢?

原理分析

从原理上来看,内网穿透就是路由器主动连接到服务器。就这么一句话,方法很多,甚至 ssh 反向隧道都能算得上。

而端口转发在 Linux 上最常见的实现方式则是 iptables DNAT,把发到自己的数据包修改目标地址后转发到自己管理的子网内。带上内网穿透以后,就有了 服务器 → 路由器、路由器 → LAN 客户端 两次转发,需要两次 DNAT。

其中,从路由器转发到 LAN 主机的 DNAT 就是在路由器界面上配置的端口转发,新的问题是从服务器到路由器的 DNAT 应当如何实现。如果能让路由器与服务器处于同一个子网,就可以用路由器到 LAN 的同样方式来配置服务器到路由器。

那么,综合以上两点需求:

1. 路由器发起连接,与服务器建立一条隧道
2. 路由器与服务器处于同一子网

就可以很容易地发现这就是虚拟 V 专用 P 网 N 工具的特征。这样一来,思路就很清楚了:

让路由器通过虚拟 V 专用 P 网 N 连上服务器,并将 V*N 接口划为 WAN 口,然后在服务器上使用一条 DNAT 规则将需要转发的端口转发到路由上,即可实现内网穿透。而路由器能够收到穿透过来的数据包以后,再要转发到 LAN 设备上,直接在 web 界面上按正常方式配置就可以了,非常简单。

实践历程

由于你懂的原因,虚拟专用网这里的配置就不说了。请大家考虑环境因素,合理选择方案,甚至可以多个方案综合使用。

在虚拟专用网配置好以后,假设

服务器公网 IP 是 45.54.1.1,
服务器虚拟专用网 IP 是 10.10.10.1,
路由器虚拟专用网 IP 是 10.10.10.2,
路由器 LAN 是 192.168.1.1/24,
需要映射的 LAN 主机是 192.168.1.99
需要映射的端口是 5000~6000

网络结构大概是这个样子:

屏幕截图(34).png

下面开始配置:

1. 配置路由器到 LAN 主机的转发

web 界面直接配置即可

屏幕截图(32).png

顺便放一张虚拟专用网接口的配置:

屏幕截图(31).png

重点是把它放在 WAN 的防火墙区域内,这样就可以用常规方式设置端口转发。

2. 配置服务器到路由器的转发

需要手动设置 DNAT 了,把路由器上的 iptables 复制过来即可:

  1. (Private Server) # iptables -t nat -A PREROUTING -p tcp -d 45.54.1.1 --dport 5000:6000 -j DNAT --to-destination 10.10.10.2
复制代码


到这里为止,一行命令就配通了从外到内的数据通路,LAN 主机已经能抓到访问 45.54.1.1:5000 时发进来的数据包了。

3. 配置回程路由

但 LAN 内的主机在发出回应后,路由器按默认路由表转发,会从路由器的 WAN 口出去,而不是从虚拟专用网走。这就导致服务器收不到回应,连接无法建立。

为了配通回去的路,需要让虚拟专用网进来的连接保持从虚拟专用网出去。这可以利用 Linux 的连接追踪和策略路由配合实现。

幸运的是,连接追踪和策略路由都很好做:

  1. (Router) # iptables -t mangle -A PREROUTING -i tun0 -j CONNMARK --set-mark 0x1234 # 给 虚拟专用网 进来的连接都打上标记
  2. (Router) # iptables -t mangle -A PREROUTING -m connmark --mark 0x1234 -j CONNMARK --restore-mark # 把连接的标记打到数据包上
  3. (Router) # ip rule add fwmark 0x1234 lookup 1234 # 把具有“虚拟专用网连接”这个标记的数据包导向 ID 为 1234 的这张路由表
复制代码


然后设置此类穿透连接的路由:

  1. (Router) # ip rule add table 1234 default via 10.10.10.1 dev tun0
  2. (Router) # ip rule add table 1234 192.168.1.0/24 dev br-lan
复制代码

一点小提示:

1. 是不是觉得后面一行 192.168.1.0/24 的路由多余了?

要注意上面 iptables 是在 PREROUTING 打标记的,并且虚拟专用网传入的数据包也会被标记。这时候还没有进行路由判决。等到了判决的时候,这个传入的数据包已经有 mark 了,也已经 DNAT 了,就会变成 “一个目标 192.168.1.99 的数据包要查询 1234 这张表”。如果没有这条路由,这个包就找不到下一跳的路由,发不出去了。

2. 为什么打标记要分两条 iptables 规则?

conntrack 是针对连接打标,ip rule 期待的是对数据包打标。这俩显然不是打在同一个对象上。那么就得想办法把连接的标记打到数据包上,这样才能根据连接来选路。

4. 配置本机路由

如上配置后,LAN 设备的端口转发就已经可用了。但是如果心血来潮转发一个路由器上的服务,会发现仍然连不通。这是为什么呢?

我们可以来看看数据包流经 iptables 各链的顺序(图源维基:https://upload.wikimedia.org/wik ... ter-packet-flow.svg 原图为矢量,可点击查看并随意放大):

屏幕截图(33).png

注意一点,本地发包的起始点不是左边的 start,而是中间顶上的 local process. 本地收包和其他所有情况都是左边 start. 仔细想想也是这样,不然本地收包都经过了 local process 了还能接着往下走?并且本地发包是从 L7 往下走的,也不是像 start 一样从 L2 往上走。

那么情况就很清楚了:接收流程正常打了标记,但路由本地的服务回应时由于没有走 PREROUTING 链,导致连接标记没能打到数据包上,所以还是走了默认路由,而非虚拟专用网的专用路由表。

要解决这个问题,可以在 mangle OUTPUT 链上也加入 --restore-mark 规则。不过,对于这种本机服务源进源出的问题,可以直接使用 ip rule 的参数来实现了,即 ip rule from 10.10.10.2 lookup 1234。后者也是多 WAN 口时源进源出常见的实现方法。

总结起来,需要的命令如下:

  1. # 设置服务器到路由的转发
  2. (Private Server) # iptables -t nat -A PREROUTING -p tcp -d 45.54.1.1 --dport 5000:6000 -j DNAT --to-destination 10.10.10.2

  3. # 设置路由到 LAN 主机的转发
  4. (Router) # (把虚拟专用网接口加到 WAN Zone 里,然后直接在 web 上像常规一样设置转发)

  5. # 设置 LAN 主机的回程路由
  6. (Router) # iptables -t mangle -A PREROUTING -i tun0 -j CONNMARK --set-mark 0x1234
  7. (Router) # iptables -t mangle -A PREROUTING -m connmark --mark 0x1234 -j CONNMARK --restore-mark
  8. (Router) # ip rule add fwmark 0x1234 lookup 1234

  9. # 设置路由器自身的回程路由
  10. (Router) # ip rule from 10.10.10.2 lookup 1234

  11. # 回程路由表
  12. (Router) # ip rule add table 1234 default via 10.10.10.1 dev tun0
  13. (Router) # ip rule add table 1234 192.168.1.0/24 dev br-lan
复制代码


最后举个例子,手机连到家里的 NAS 上:

TIM图片20180407161856.png

可以看到 SSH_CLIENT 就是手机 4G 的 IP 地址,而非现有穿透程序一样的路由器 LAN IP. 如果要部署 fail2ban 之类的机制,这是非常有用的。

并且,整套方案的稳定性由虚拟专用网和 Linux 内核来担保。虚拟专用网有着近似于“基础设施”级别的需求,自然有足够稳定的实现可以选择;Linux 内核的稳定性大家用了这么久也很清楚了。如非出现不可抗力的网络问题,这套方案掉线的可能性极低。

这次的分享就到这里,感谢大家观看~

评分

5

查看全部评分

24

主题

749

帖子

1236

积分

大魔法师

Rank: 5Rank: 5

精华
0
门户文章
0
魔力币
920
魔法值
0
注册时间
2016-7-18
发表于 2018-4-7 16:41:42 | 显示全部楼层
你这个虚拟专用网还是不够优雅啊,内核态的WireGuard,了解一下。

31

主题

1079

帖子

1万

积分

大魔导师

Rank: 9Rank: 9Rank: 9

精华
1
门户文章
3
魔力币
3148
魔法值
45
注册时间
2015-11-8

R7000DDOS纪念勋章

 楼主| 发表于 2018-4-7 16:45:01 | 显示全部楼层
zyyhcufe 发表于 2018-4-7 16:41
你这个虚拟专用网还是不够优雅啊,内核态的WireGuard,了解一下。

那张防火墙区域图上的接口名是 wg_ext [doge]

3

主题

673

帖子

934

积分

高级魔法师

Rank: 4

精华
0
门户文章
0
魔力币
764
魔法值
0
注册时间
2017-2-8
QQ
发表于 2018-4-7 17:23:50 | 显示全部楼层

大神。。先膜拜一把。。

TMD完全看不懂啊

24

主题

749

帖子

1236

积分

大魔法师

Rank: 5Rank: 5

精华
0
门户文章
0
魔力币
920
魔法值
0
注册时间
2016-7-18
发表于 2018-4-7 18:35:30 | 显示全部楼层
updateing 发表于 2018-4-7 16:45
那张防火墙区域图上的接口名是 wg_ext [doge]

我就看见了dev tun0……想必是要和以前的规则兼容所以就沿用了设备名吧。

14

主题

144

帖子

739

积分

版主

Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20

精华
0
门户文章
0
魔力币
662
魔法值
0
注册时间
2017-2-23
发表于 2018-4-7 22:09:46 | 显示全部楼层
虽然看不懂但得赞一个
生命诚可贵,
爱情价更高。
若为自由故,
二者皆可抛……

24

主题

749

帖子

1236

积分

大魔法师

Rank: 5Rank: 5

精华
0
门户文章
0
魔力币
920
魔法值
0
注册时间
2016-7-18
发表于 2018-4-8 14:27:11 | 显示全部楼层
参照楼主的方案已配置成功。
一点补充建议,connmark模块需要安装iptables-mod-conntrack-extra包,ip rule和自定义route table可以写在/etc/config/network里,iptables规则可以写在/etc/firewall.user里。

9

主题

668

帖子

1249

积分

大魔法师

Rank: 5Rank: 5

精华
0
门户文章
0
魔力币
993
魔法值
0
注册时间
2017-2-1
发表于 2018-4-8 15:26:41 | 显示全部楼层
看得猫抓心,谢谢了,学习了

55

主题

364

帖子

644

积分

高级魔法师

Rank: 4

精华
0
门户文章
0
魔力币
443
魔法值
0
注册时间
2016-3-4
发表于 2018-4-8 16:35:21 来自手机 | 显示全部楼层
数通大神R&S游刃有余,刚在V P S上建好frps,客户端连接服务器端口,被服务器积极拒绝,不知道搬*瓦工如何开端口,还有内网的华为路由估计也要放行,出差回来接续折腾

31

主题

1079

帖子

1万

积分

大魔导师

Rank: 9Rank: 9Rank: 9

精华
1
门户文章
3
魔力币
3148
魔法值
45
注册时间
2015-11-8

R7000DDOS纪念勋章

 楼主| 发表于 2018-4-8 22:19:55 | 显示全部楼层
zyyhcufe 发表于 2018-4-8 14:27
参照楼主的方案已配置成功。
一点补充建议,connmark模块需要安装iptables-mod-conntrack-extra包,ip rule ...

感谢支持!

不过我没能在 /etc/config/network 找到这么精细的配置……

24

主题

749

帖子

1236

积分

大魔法师

Rank: 5Rank: 5

精华
0
门户文章
0
魔力币
920
魔法值
0
注册时间
2016-7-18
发表于 2018-4-9 20:06:51 | 显示全部楼层
updateing 发表于 2018-4-8 22:19
感谢支持!

不过我没能在 /etc/config/network 找到这么精细的配置……

不是有config rule、config route吗。

31

主题

1079

帖子

1万

积分

大魔导师

Rank: 9Rank: 9Rank: 9

精华
1
门户文章
3
魔力币
3148
魔法值
45
注册时间
2015-11-8

R7000DDOS纪念勋章

 楼主| 发表于 2018-4-9 21:21:05 | 显示全部楼层
zyyhcufe 发表于 2018-4-9 20:06
不是有config rule、config route吗。

没有试过定义精细到 fwmark 匹配的条目,我全都写到 firewall.user 去了。回头研究一下,谢啦~

8

主题

365

帖子

737

积分

高级魔法师

Rank: 4

精华
0
门户文章
0
魔力币
620
魔法值
0
注册时间
2017-3-4
发表于 2018-4-10 11:00:52 | 显示全部楼层
zyyhcufe 发表于 2018-4-7 16:41
你这个虚拟专用网还是不够优雅啊,内核态的WireGuard,了解一下。

赞,WireGuard非常好啊,期待支持更多系统

1

主题

17

帖子

72

积分

初级魔法师

Rank: 2

精华
0
门户文章
0
魔力币
69
魔法值
0
注册时间
2015-12-10
发表于 2018-4-12 13:06:45 | 显示全部楼层
阿里云云主机拼团活动,99元一年,明天结束,刚好能用上活动地址

3

主题

28

帖子

204

积分

中级魔法师

Rank: 3Rank: 3

精华
0
门户文章
0
魔力币
195
魔法值
0
注册时间
2016-12-6
发表于 2018-4-16 12:13:17 | 显示全部楼层
小白问一下这种方式是不是所有连接都走v*p*s流量呀?

66

主题

1057

帖子

3578

积分

中级魔导师

Rank: 7Rank: 7Rank: 7

精华
0
门户文章
0
魔力币
2934
魔法值
0
注册时间
2016-1-14

AC88UDDOS纪念勋章

发表于 2018-5-6 21:20:36 | 显示全部楼层
求梅林详细攻略。。。

31

主题

1079

帖子

1万

积分

大魔导师

Rank: 9Rank: 9Rank: 9

精华
1
门户文章
3
魔力币
3148
魔法值
45
注册时间
2015-11-8

R7000DDOS纪念勋章

 楼主| 发表于 2018-5-6 22:43:09 | 显示全部楼层
zhurifx 发表于 2018-5-6 21:20
求梅林详细攻略。。。

iptables 是 Linux 通用的……

联系我们|手机版|KoolShare ( 沪ICP备13045430号962110 沪公网备31010402005377

GMT+8, 2020-3-28 16:40 , Processed in 0.112708 second(s), 9 queries , Gzip On, Redis On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表