OpenSSH建立二层和三层加密隧道
OpenSSH 可以使用tun/tap设备来创建一个加密隧道,SSH隧道类似mode TCP模式下的OpenVPN,对于有需求快速设置一个基于IP的VPN来说非常方便。使用SSH隧道的优点:
- 不需要安装和配置额外的软件
- 使用SSH认证并自带加密,不需要使其它VPN软件一样配置共享密钥或者证书
- 兼容性强,可以建立二层隧道或三层隧道,所有3/4层协议如:ICMP、TCP/UDP 等都可支持
- 配置过程简单
当然也有缺点:
- 基于TCP协议,其传输效率较低
- 隧道依赖于单个TCP连接,容易中断或假死
- 需要ROOT权限
这里还要说明一下二层和三层的区别:
- layer 2 : 交换单元是帧,只识别MAC地址,只有交换功能,相关协议:Ethernet、VLAN、STP、PPP、FDDI、ARP(OSI模型)、MPLS(介于2层3层之间)等,在Linux中是虚拟点对点设备,显示为tap
- layer 3 : 交换单元是包,能识别MAC地址和IP,有交换和路由功能,相关协议:IP、ICMP、IGMP、IPsec等,在Linux中是虚拟以太网设备,显示tun
在Linux中tun/tap都可以设置IP,只是模拟的工作层有区别,tun是模拟三层网络设备,收发的是IP包,无法处理以太网数据帧。tap模拟的是二层设备,收发的是以为网数据帧,更接近物理网卡,可以和物理网卡通过网桥绑定。我们日常用的wmware虚拟机中的nat网络,对应的就是tun,桥接网络对应的就是tap。
一、ssh server端配置
首先要使用ssh的二层和三层隧道,尽量保证系统差别不要太大,我这里两边都是oracle linux 8,SSH版本更新到最新。server端需要允许root登录和隧道,编辑/etc/ssh/sshd_config:
PermitRootLogin yes
PermitTunnel yes
#建议添加
TCPKeepAlive yes
PermitTunnel yes代表允许point-to-point (layer 3)和ethernet (layer 2)
二、三层隧道配置
2.1 建立三层隧道
在client端执行:
ssh -w any:any root@[server_ip]
如果客户端和服务器端没有其它的tun设备,就会在客户端和服务器端各生成一个名为tun0设备,指定any可以自动分配可用的设备。查看设备:
[root@centos8 ~]# ip addr
3: tun0: <POINTOPOINT,MULTICAST,NOARP> mtu 1500 qdisc noop state DOWN group default qlen 500
link/none
可以看到有个tun0 <POINTOPOINT,MULTICAST,NOARP>,这个设备是未激活的状态,如果用ifconfig命令查看,需要加上-a参数才能看到。
为安全起见,建议使用以下命令:
ssh -NTCf -w 5:5 root@[server_ip]
- “-N”:不执行远程命令
- “-T”:不分配终端
- “-C”:压缩传输的流量
- “-f”:在客户端后台运行
执行完该命令client和server各自会创建一个tun5的点对点设备,下一步就是需要激活设备并分配IP。
2.2 分配IP并激活隧道
分配IP不要与服务器和客户端网段有冲突,这里假设:
客户端IP:10.0.0.2 tun5
服务器IP:10.0.0.1 tun5
服务器激活点对点设备并分配IP和路由:
ip link set tun5 up
ip addr add 10.0.0.1/32 peer 10.0.0.2 dev tun5
客户端同理:
ip link set tun5 up
ip addr add 10.0.0.2/32 peer 10.0.0.1 dev tun5
这时隧道已经建立成功,此时用查看一下状态:
[root@centos8 ~]# ip addr
14: tun5: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 500
link/none
inet 10.0.0.1 peer 10.0.0.2/32 scope global tun5
可以看到比之前多了“UP,LOWER_UP”,说明已经激活。正常情况下客户端和服务器已经可以相互ping。
客户端用一条命令也能搞定:
ssh \
-o PermitLocalCommand=yes \
-o LocalCommand="ip link set tun5 up && ip addr add 10.0.0.2/32 peer 10.0.0.1 dev tun5 " \
-o TCPKeepAlive=yes \
-w 5:5 root@[server_ip] \
'ip link set tun5 up && ip addr add 10.0.0.1/32 peer 10.0.0.2 dev tun5'
2.3 添加其它网段的路由
如果服务器端有其它内网段,需要继续添加客户端路由才能ping通,例如,客户端想与服务器端网段10.0.12.0/24互通,需在客户端执行:
ip route add 10.0.12.0/24 dev tun5
按需添加即可,更改路由是高风险操作,需要格外小心,同时也要确保ssh连接不要中断。
三、二层隧道配置
由于linux中允许为tap设备设置ip,所以二层隧道和三层隧道也可以完全一样的进行配置。区别是tap设备可以和物理网卡进行绑定,也就是桥接,同时由于工作在二层,允许Arp通过,能支持STP生成树、PPP等协议。
3.1 建立二层隧道
在客户端执行:
ssh -o Tunnel=ethernet -w 6:6 root@[server_ip]
这里参数 -o 需要在 -w 前面,查看一下客户端和服务器的网卡:
[root@centos8 ~]# ip addr
20: tap6: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
在ip命令中 tap6: <BROADCAST,MULTICAST>,和物理网卡显示的一样,说明模拟的是物理网卡。
3.2 创建并配置网桥
二层可以进行网卡桥接,桥接可以多块网卡,也可以一块网卡,这里测试为了省事只用一块网卡,创建网桥有三种工具:
- 使用bridge-utils中的brctl命令
- 使用oracle linux 8 系列自带的nmcli
- 使用ip命令
建议用ip命令建立:
ip link add br0 type bridge
将tap6加入网桥:
ip link set tap6 master br0
配置服务器端网桥IP信息并启动网桥:
ip address add 10.0.0.1/32 dev br0
ip link set tap6 up
ip link set br0 up
客户端流程一样,只是客户端的ip是10.0.0.2
在客户端测试ARP包能不能通过:
[root@oracle8 ~]# arping -I br0 10.0.0.1
ARPING 10.0.0.1 from 10.0.0.2 br0
Unicast reply from 10.0.0.1 [3A:E7:2F:3F:42:24] 193.222ms
Unicast reply from 10.0.0.1 [3A:E7:2F:3F:42:24] 191.903ms
如果是三层隧道,就无法使用arping。
看似很多内容,其实使用很简单,OpenSSH套件功能真强大。
参考文章
https://help.ubuntu.com/community/SSH_VPN
https://www.cyberciti.biz/faq/centos-8-add-network-bridge-br0-with-nmcli-command/
https://gobomb.github.io/post/build-l2-l3-vpn-by-openssh/