从逻辑上讲,VPN 应该比 SSH 隧道传输速度更快,因为:
- 它在 UDP 上运行,而不是 TCP(因此没有 TCP over TCP)
- 它有压缩
但是,今天我测试了两种方法的 Redis 复制。
我在爱尔兰 AWS VM 上运行了测试,连接到美国东部 AWS VM。
由于我的测试用例是 Redis 复制,所以我测试的内容正是如此 - 我运行了一个空白的 Redis 服务器,在它完成加载后,我执行了slaveof
另一个服务器,并测量了 Connecting to MASTER
和之间的时间MASTER <-> SLAVE sync: Finished with success
。在这期间,我使用了
while 1; do redis-cli -p 7777 info | grep master_sync_left_bytes;sleep 1; done
粗略估计一下速度。SSH
遥遥领先:~11MB/s,而 OpenVPN 的速度约为 2MB/s。
这是否意味着我研究的所有东西都是错误的,还是我的设置配置严重错误?
更新
我用相同的数据集做了几次测试,并得到了以下结果:
- OpenVPN
- TCP:
压缩:15 分钟
无压缩:21 分钟 - UDP:
压缩:5 分钟
无压缩:6 分钟
- TCP:
- SSH
默认设置:1分50秒
无压缩:1分30秒
压缩:2分30秒
更新2
以下是 iperf 的结果,包含双向测试(SSH 除外,因为没有可用的返回路径)
| method | result (Mb/s)|
|------------------+--------------|
| ssh | 91.1 / N.A |
| vpn blowfish udp | 43 / 11 |
| vpn blowfish tcp | 13 / 12 |
| vpn AES udp | 36 / 4 |
| vpn AES tcp | 12 / 5 |
技术规格
我运行的是 CentOS 6.3(服务器)、CentOS 6.5(客户端)。OpenVPN
版本是 2.3.2(与 Ubuntu 14.10 相同,因此没有发霉的版本)
我的 SSH 隧道如下所示:
ssh -f XXXX@XXXX -i XXXX -L 12345:127.0.0.1:12345 -N
我的配置文件如下:
服务器
port 1194
proto udp
dev tun0
topology subnet
log /var/log/openvpn.log
ca XXXX
cert XXXX
key XXXX
dh XXXX
crl-verify XXXX
cipher AES-256-CBC
server XXXX 255.255.255.0
ifconfig-pool-persist /etc/openvpn/ipp.txt
keepalive 10 120
comp-lzo
status /var/log/openvpn-status.log
verb 3
tun-mtu 1500
fragment 1300
persist-key
persist-tun
客户
client
remote XXXX 1194
proto udp
dev tun
log /var/log/openvpn.log
comp-lzo
cipher AES-256-CBC
ns-cert-type server
# the full paths to your server keys and certs
ca XXXX
cert XXXX
key XXXX
tun-mtu 1500 # Device MTU
fragment 1300 # Internal fragmentation
persist-key
persist-tun
nobind
答案1
谢谢卡斯帕德的评论,我了解到 SSH 不会受到 TCP-over-TCP 的影响,因为它只移动数据包。我写了一个博客文章关于它,但最有趣的是输出netstat
,证明 SSH 确实没有保留第 3,4 层数据:
隧道建立之后,连接之前
backslasher@client$ netstat -nap | grep -P '(ssh|redis)'
...
tcp 0 0 127.0.0.1:20000 0.0.0.0:* LISTEN 20879/ssh
tcp 0 0 10.105.16.225:53142 <SERVER IP>:22 ESTABLISHED 20879/ssh
...
backslasher@server$ netstat -nap | grep -P '(ssh|redis)'
...
tcp 0 0 0.0.0.0:6379 0.0.0.0:* LISTEN 54328/redis-server
tcp 0 0 <SERVER IP>:22 <CLIENT IP>:53142 ESTABLISHED 53692/sshd
...
建立隧道并连接后
backslasher@client$ netstat -nap | grep -P '(ssh|redis)'
...
tcp 0 0 127.0.0.1:20000 0.0.0.0:* LISTEN 20879/ssh
tcp 0 0 127.0.0.1:20000 127.0.0.1:53142 ESTABLISHED 20879/ssh
tcp 0 0 127.0.0.1:53142 127.0.0.1:20000 ESTABLISHED 21692/redis-cli
...
backslasher@server$ netstat -nap | grep -P '(ssh|redis)'
...
tcp 0 0 0.0.0.0:6379 0.0.0.0:* LISTEN 54328/redis-server
tcp 0 0 127.0.0.1:6379 127.0.0.1:42680 ESTABLISHED 54328/redis-server
tcp 0 0 127.0.0.1:42680 127.0.0.1:6379 ESTABLISHED 54333/sshd
tcp 0 0 <SERVER IP>:22 <CLIENT IP>:53142 ESTABLISHED 52889/sshd
...
因此我将使用 SSH 隧道,因为看起来我的 OpenVPN 没有配置错误或其他问题,只是它不是适合这项工作的工具。
答案2
这取决于您要实现的目标以及您的优先事项。VPN 将您连接到网络,而 SSH 则连接到机器。VPN 具有封装功能,因此更安全一些,而 SSH 则不具备这种功能。
此外,VPN 允许所有流量轻松通过,而使用 SSH 则必须强制应用程序通过。
你会使用 AD 吗?因为 VPN 可以让你更轻松地做到这一点。
我更喜欢使用 SSH 来满足快速需求,而对于需要节省额外时间的关键应用程序,我更喜欢使用 VPN。
根据具体情况,我曾在 VPN 中使用 SSH,以防 VPN 被攻破。这样,探测者就必须通过 SSH 隧道。
答案3
SSH 端口转发不是隧道,因为不会发生协议栈包装。OpenVPN 会进行包装,因此 SSH 端口转发不会受到 TCP-over-TCP 问题的影响。
例如在 OpenVPN 中,协议栈将类似于:
Redis
TCP
IP
OpenVPN (tun mode)
UDP
IP
Ethernet
IP(网络层协议)在这里出现了两次,这就是我们称之为隧道。