![通过中间/跳转服务器的 VPN](https://linux22.com/image/747102/%E9%80%9A%E8%BF%87%E4%B8%AD%E9%97%B4%2F%E8%B7%B3%E8%BD%AC%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%20VPN.png)
以下是我想做的事情的粗略情况:
客户端 -> |VPN| -> 服务器 A -> |VPN| -> 服务器 B -> 互联网。
服务器 A 和服务器 B 都位于公共互联网上,具有公共 IP,而且我对这两台服务器都有 root 访问权限。客户端位于防火墙后面,但可以访问服务器 A。客户端无法直接访问服务器 B。服务器 A 可以访问服务器 B。我希望数据包从服务器 B 流出到互联网。我需要加密从客户端到 A 以及从 A 到 B 的通信,因为 A 和 B 不在同一个 LAN 中,所以 A 和 B 之间的流量通过公共基础设施传输。
我已经能够在 A 上设置 IPSec VPN 服务器并能够连接到它。但我无法找到从 A 到 B 建立另一个 VPN 并将来自 A 的流量从客户端重新路由到 B 的正确方法。
尖端?
ps 我最初考虑使用 SSH 隧道连接 A 和 B,然后通过这样的隧道将来自客户端的相关数据包路由到 B。但正如人们在评论中指出的那样,这不是一个好主意。所以我愿意接受任何建议。谢谢!
编辑#1
服务器 A 上的 VPN 服务使用 strongswan 设置,它处理客户端和服务器 A 之间的任何连接。我通过以下方式完成ipsec.conf
:
# ipsec.conf - strongSwan IPsec configuration file
# basic configuration
config setup
charondebug="ike 2, knl 2, cfg 2, net 2, esp 2, dmn 2, mgr 2"
strictcrlpolicy=no
uniqueids=yes
cachecrls=no
conn ipsec-ikev2-vpn
auto=add
compress=no
type=tunnel # defines the type of connection, tunnel.
keyexchange=ikev2
fragmentation=yes
forceencaps=yes
dpdaction=clear
dpddelay=300s
rekey=no
left=%any
leftid=47.112.200.xxx # if using IP, define it without the @ sign
leftcert=vpn-server.cert.pem # reads the VPN server cert in /etc/ipsec.d/certs
leftsendcert=always
leftsubnet=0.0.0.0/0
right=%any
rightid=%any
rightauth=eap-mschapv2
rightsourceip=10.10.10.0/24 # IP address Pool to be assigned to the clients
rightdns=1.1.1.1,8.8.8.8 # DNS to be assigned to clients
rightsendcert=never
eap_identity=%identity # defines the identity the client uses to reply to an EAP Identity request.
使用ufw
(我所遵循的教程使用了 ufw,但我iptables
也可以使用基本规则)设置/etc/ufw/before.rules
;我省略了 ufw 自动生成的部分,并且我还手动允许端口 500/4500 上的 udp 和端口 22 上的 tcp:
#
# rules.before
#
# Rules that should be run before the ufw command line added rules. Custom
# rules should be added to one of these chains:
# ufw-before-input
# ufw-before-output
# ufw-before-forward
#
# Don't delete these required lines, otherwise there will be errors
*nat
-A POSTROUTING -s 10.10.10.0/24 -o eth0 -m policy --pol ipsec --dir out -j ACCEPT
-A POSTROUTING -s 10.10.10.0/24 -o eth0 -j MASQUERADE
COMMIT
*mangle
-A FORWARD --match policy --pol ipsec --dir in -s 10.10.10.0/24 -o eth0 -p tcp -m tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1361:1536 -j TCPMSS --set-mss 1360
COMMIT
*filter
:ufw-before-input - [0:0]
:ufw-before-output - [0:0]
:ufw-before-forward - [0:0]
:ufw-not-local - [0:0]
# End required lines
-A ufw-before-forward --match policy --pol ipsec --dir in --proto esp -s 10.10.10.0/24 -j ACCEPT
-A ufw-before-forward --match policy --pol ipsec --dir out --proto esp -d 10.10.10.0/24 -j ACCEPT
这就是我所取得的进展。由于端口 500 和 4500 被阻止/篡改,在 A 和 B 之间通过 strongswan IPSec 设置站点到站点 VPN 的单独尝试失败:客户端可以通过 500/4500 访问 A,A 无法通过 500/4500 访问 B,并且我已将 B 的所有端口暴露给开放互联网进行测试。
编辑2
目前,我设法在 A 和 B 之间建立的唯一隧道是 SSH socks(ssh -N -f -4 -D 1080 [server B ip]
来自服务器 A)。我正在考虑通过该 SSH 隧道将离开 A 的流量(其目的地不是我的客户端设备)重定向到 B。
类似于:-A OUTPUT -p tcp --dport 443 -j REDIRECT --to-ports 1080
在 ufw/iptables 中。(这实际上不起作用,服务器 A 的 ip 仍然显示在 ip 检查器中,被阻止的网站仍然无法访问)
答案1
在评论中扩展我的提示。
我知道如何在 OpenVPN 中建立隧道,因为我使用它来连接到 IPv6 网络,但对于 IPSec 来说,其理念应该是一样的。
我将从我熟悉的(IPv6)开始,并展示如何将其转换为 IPv4。
不过这里有一个友好的免责声明:
我还没有尝试过在 IPv4 上进行多主路由,所以您的情况可能会有所不同。
服务器 A-IPv6 版本
在我的服务器上,OpenVPN 隧道网络接口被称为tun0
。
在服务器 A编辑/etc/iproute2/rt_tables
,因此您有以下条目:
200 openvpn
这将创建一个专用的路由表,我们可以使用它来进行 VPN 路由。默认路由表称为main
。
该表openvpn
将处理所有向上游发送的数据包(您 -> 互联网),而路由表main
将处理所有向下游发送的流量(互联网 -> 您)。
ip -6 rule add priority 32000 iif tun0 to 2000::/3 table openvpn
ip -6 route add default via <ipv6 address> dev tun1 table openvpn
请注意,您必须为属于您的任何 IP 范围添加规则。
假设 IPv6 范围 2001:db8:cafe::/48 属于您,并且您具有以下设置:
- 客户端 VPN 链接位于 2001:db8:cafe:1::/64,客户端的 IP 地址为 2001:db8:cafe:1::100
- 客户端本地网络是 2001:db8:cafe:100::/64,其将给出规则:
ip -6 route add unreachable 2001:db8:cafe::/48 table main
ip -6 route add 2001:db8:cafe:100::/64 via 2001:db8:cafe:1::100 dev tun0
服务器 A-IPv4 版本
IPv4 版本为:
我们仍然需要一个专用的路由表,因为我们需要根据来源路由流量,因此/etc/iproute2/rt_tables
仍然需要以下条目:
200 openvpn
假设 IPv4 规则与 IPv6 非常类似,为操作系统提供以下命令用于 openvpn 路由表:
ip rule add priority 32000 iif tun0 to 0.0.0.0/0 table openvpn
ip route add default via <ipv4 address> dev tun1 table openvpn
现在我不确定是否有任何需要在此时捕获的 IPv4 范围(例如 RFC1918 地址),因为一般的想法基本上是转发接口上进入的所有内容tun0
并将其发送到tun1
上图中。
服务器 B-IPv6 版本
现在有两种将 IPv6 流量转发到 Internet 的方法:
如果您从连接到 的 ISP 处获得了可路由的 IPv6 池
Server B
,那么对您来说就太好了。默认路由表main
可能可以为您完成所有事情。如果您有来自 Hurricane Electric 的 IPv6 块,那么您基本上需要与上相同的设置,即
Server A
使用专用路由表作为上游,使用默认路由表作为下游。
服务器 B-IPv4 版本
这里最简单的解决方案可能是Server B
将其视为 NAT,因此您需要在将来自您网络的所有数据包发送到 Internet 之前对其进行伪装。
答案2
如果您在 Linux(StrongSwan)上使用 IPSec,则使用 执行策略路由ip xfrm policy
:带有 的策略dir out
用于决定将数据包转发到哪个隧道,而带有dir in
和 的策略dir fwd
用于决定是否允许或丢弃数据包。
假设serverA
有公有 IP192.0.2.1
和私有 IP 10.0.10.1
(你可以把它附加到环回设备上),serverB
有公有 IP198.51.100.1
和私有 IP 10.0.20.1
,而 VPN 客户端在网络中获得一个 IP 。你可以像这样在 serverA 上10.0.30.0/24
使用建立隧道:swanctl.conf
connections {
serverB {
version = 2
local_addrs=192.0.2.1
remote_addrs=198.51.100.1
local {
# serverA auth parameters
}
# serverB auth parameters
}
children {
tunnel {
local_ts = 10.0.10.0/24
remote_ts = 10.0.20.0/24
start_action = start
reqid = 10
priority = 1000
}
}
}
}
在服务器B上也有类似的配置,local*
并且remote*
反转。
请注意,reqid
和priority
参数是固定的,因此可以在策略中使用。在中无法做到这一点ipsec.conf
。
要配置策略路由,您需要在服务器 A 上执行以下操作:
- 允许从 IP 到任意 IP 的加密流量。如果您在 VPN 客户端的连接配置中
10.0.30.0/16
设置,则此操作会自动完成。local_ts = 0.0.0.0/0
允许加密流量
10.0.30.0/24
与 serverB 建立隧道:ip xfrm policy add src 0/0 dst 10.0.30/24 \ dir fwd priority 2000 \ tmpl src 198.51.100.1 dst 192.0.2.1 \ proto esp reqid 10 mode tunnel
这与IP 链
ACCEPT
中的规则类似FORWARD
。转发流量
10.0.30.0/24
到服务器B:ip xfrm policy add src 10.0.30/24 dst 0/0 \ dir out priority 2000 \ tmpl src 192.0.2.1 dst 198.51.100.1 \ proto esp reqid 10 mode tunnel
优先级高于 StrongSwan 自动安装的优先级,因此如果安装了这些策略,则允许转发。如果删除这些策略,StrongSwan 安装的策略将仅允许10.0.10.0/24
和之间的流量10.0.20.0/24
。在 serverB 上,您可以使用相同的策略,只需dir out
与交换即可dir fwd
。
附言:当然,您还需要一些 iptables 规则,以便服务器 A 和服务器 B 允许 ESP 和 IKE 流量:
iptables -I INPUT -p esp -j ACCEPT
iptables -I INPUT -p udp -m multiport --dports 500,4500 -m comment --comment "IKE" -j ACCEPT
并设置一些丢弃规则,以便隧道断开时数据包不会以未加密的形式退出:
iptables -A OUTPUT -o <external_interface> -s 10.0.0.0/16 -m policy --dir out --policy ipsec -j ACCEPT
iptables -A OUTPUT -o <external_interface> -s 10.0.0.0/16 -j DROP
编辑:由于您正在使用ipsec配置文件与上述等效的配置swanctl.conf
是:
conn servers {
left=192.0.2.1
right=198.51.100.1
# The appropriate authentication leftauth, leftid, ...
leftsubnet = 10.0.10.0/24
rightsubnet = 10.0.20.0/24
auto = start
reqid = 10
}
就其而言,swanctl.conf
它的优点是无需在两个主机上进行修改即可工作,但它不允许设置策略priority
,因此您需要检查 StrongSwan 选择设置更高的优先级。