Linux(Ubuntu)OpenVPN 客户端 - 不通过 SSH 隧道

Linux(Ubuntu)OpenVPN 客户端 - 不通过 SSH 隧道

我想在我的云 VM(EC2 实例)上以客户端模式运行 OpenVPN,这样离开 VM 的流量通常会通过 VPN。但我仍然希望现有 IP 地址可用于 SSH 连接(这样它就不会中断我当前连接到机器的 SSH 连接)。

以下是.ovpn我正在使用的当前设置文件:

client
dev tun
proto udp
remote xxx.yyy.com 1198
resolv-retry infinite
nobind
persist-key
persist-tun
cipher aes-128-cbc
auth sha1
tls-client
remote-cert-tls server
auth-user-pass
comp-lzo
verb 1
reneg-sec 0
crl-verify crl.rsa.2048.pem
ca ca.rsa.2048.crt
disable-occ

编辑:这个问题可能与防止在服务器机器上登录 VPN 后丢失 SSH 连接...但是那里也没有可以接受的答案。

答案1

您可以使用高级路由将主接口上传入的数据包通过同一接口进行路由。这样,来自服务器的任何流量都将通过 VPN 路由,但服务器的主接口仍可用于连接。这里的想法是,如果数据包通过主接口,它将使用名为“vpn”的不同路由表,因此它不会受到 VPN 客户端的路由设置的影响。

为了实现此目的,请执行以下操作:

编辑/etc/iproute2/rt_tables文件。它应该包含如下内容:

#
# reserved values
#
255     local
254     main
253     default
0       unspec
#
# local 
#

将此行添加到文件末尾:

1        vpn

/etc/network/interfaces文件中,在主界面的设置下(或 中的相应文件/etc/network/interfaces.d/),添加以下行:

up ip route add 0.0.0.0/0 via def.ault.gw table vpn
up ip rule add from the.primary.ip.addr table vpn
down ip route del 0.0.0.0/0 table vpn
down ip rule del from the.primary.ip.addr

将其替换the.primary.ip.addr为您的主接口的 IP 地址(即您希望服务器通过该 IP 访问的 IP)和def.ault.gw默认网关地址。

答案2

我建议使用“--up”和“--down”选项来运行 shell 脚本,根据需要操纵虚拟机上的防火墙和路由表。这将允许您通过 VPN 隧道传输流量(如果 openvpn 尚未这样做)并为 ssh 流量设置例外。请记住,iptables 规则是以自上而下的方式应用的,因此请确保在隧道规则之前应用例外规则。还有其他问题可以用作如何管理路由表和防火墙规则的示例。

iptables-目标是将数据包路由到特定接口?

答案3

我认为您面临的问题是默认路由在 VPN 上,并且有些路由会过滤掉来自没有源路由的接口的数据包。这称为反渗透过滤器

您有两种解决方案,可以让 sshd 的默认路由与其他进程不同。您可以使用网络命名空间,也可以使用 cgroups。我不太了解这些,但您可以在以下答案中了解更多信息:
https://superuser.com/questions/271915/route-the-traffic-over-specific-interface-for-a-process-in-linux

答案4

您可以按照建议通过高级路由来完成此操作,但并不是那么简单。

实现目标的最简单解决方案是将包路由到不同的 (家庭) IP 地址。将 ssh 访问限制到几个安全的 IP 地址始终是一个好主意。例如,您可以执行以下操作:

ip route add 1.1.1.1 via 9.9.9.9

这里 1.1.1.1 是你的家庭 IP 地址,9.9.9.9 是某个默认网关已经可以到达在路由表中。现在,从您的机器到外部 IP 的所有包都将以相同的方式返回。您可以像往常一样通过 VPN 路由其他所有内容。您甚至可以在 openvpn 配置文件中添加此路由。一切都很棒。

但是,如果您的家庭 IP 不断变化(即动态地址),或者您必须从随机地址(多个用户、旅行)访问您的机器,那么情况就不那么好了。在这种情况下,您必须走一条艰难的道路。

请注意,如果你什么都不做,ssh 包将到达你的外部接口(和 ip),但如果你通过 VPN 路由它们,它们将无法找到返回的路径(实际上它们可以取决于您的 VPN 设置,但源 IP 会有所不同,并且包将被丢弃)。您的目标是重定向一些部分出站数据包被发送到外部接口,部分发送到 VPN。这就是问题所在。

创建备用路由表:

echo "100 secure" >> /etc/iproute2/rt_tables

填充并控制路由:

# route ssh over external iface eth0 to router 9.9.9.9 
ip route add default via 9.9.9.9 dev eth0 table secure

# send all packages with fwmark 1 to the secondary routing table
ip rule add fwmark 0x1 table secure

# Mark outgoing ssh packages with the mark 1
iptables -t mangle -A OUTPUT -p tcp --sport 22 -j MARK --set-mark 1

在这里,我们将标记所有传出的 ssh 包,然后通过替代路由重定向所有标记的包。当然,现在你惯于能够通过 vpn 进行 ssh,因为所有答案都会重定向到另一个接口。关键是,您可以创建任意复杂的 iptables 规则,并使用 set-mark 以不同的方式路由它们。

幸运的是,我们有一个叫做 CONNMARK 的东西,它(利用内核的连接跟踪功能)可以来回标记整个连接(您将需要 xt_connmark 模块)。

# mark incoming ssh *connection* with 1. Here eth0 is your external interface
iptables -A INPUT -m state --state NEW -i eth0 -p tcp --dport 22 -t mangle -j CONNMARK --set-mark 1

# restore connection mark (e.g. mark the packages) 
iptables -A OUTPUT -t mangle -j CONNMARK --restore-mark 

# send all packages with fwmark 1 to the secondary routing table as before..
ip rule add fwmark 0x1 table secure

请在理解概念后根据您当前的设置使用上述内容,不要只是复制粘贴。


编辑:从客户的角度来看

如果您使用 VPN相同的当您建立 ssh 连接的机器上时,会出现另一个问题。

默认情况下,VPN 对等体被设为默认网关。它很容易破坏你现有的连接,因为你的 ssh 包将通过 VPN 通道路由(服务器将从 tun 或 tap 接口获取它们,然后不是来自物理 eth 接口)。简单的解决方案是不在客户侧配置(或者不推送)。仅推送首选子网的路由。警告:如果您使用 VPN 来隐藏您的(家庭)公共地址,这可能不是您想要的!

相关内容