srv_pub srv_target
+-----------------+ +---------------------+
Internet | VPS | VPN 10.8.0.0/24 | HOME SERVER |
-----------> eth0: public_ip <------------------> eth0: non_public_ip |
| tun0: 10.8.0.1 | | tun0: 10.8.0.2 |
+-----------------+ +---------------------+
Domains: pub.example.com srv.example.com (desired)
目前情况:目标服务器(srv_target
)没有公网 IP,srv_pub
使用 OpenVPN 连接到其他具有公网 IP 的服务器()。我需要使用域名设置对 srv_target 的访问。
具体来说,这意味着:
- 如果我在互联网上的某个其他主机上输入 - 我将转到
ssh [email protected]
srv_target
curl http://srv.example.com
将被发送到srv_target
ping srv.example.com
外面会 pingsrv_target
srv_pub
通过域和公共 IP 保持可通过 http、ssh 和 icmp 访问。
怎么做 ?
我是否需要设置srv_pub
指向的A
记录的 DNS 服务器?srv.example.com
10.8.0.2
我是否需要使用类似软件创建额外的隧道穿梭巴士?
答案1
你需要做两件事 -
将 DNS 设置为指向您的 srv-public 的公共 IP 地址(没有必要将其设置为私有 IP - 它无法到达那里!)
在 srv-public 上设置 NAT 和端口转发,以便将流量转发到 srv-target。您尚未告知您的 cos/distro,但在 Linux 上可以使用以下方法完成此操作
#开启IP转发 echo 1 />proc/sys/net/ipv4/ip_forward
将流量从外部 IP 重定向到内部 IP。
iptables -A PREROUTING -t nat -p tcp -d pub.ip.add.res --dport 22 -j DNAT --to-destination 10.8.0.1
笔记:
- 需要对所有相关端口重复上述命令。
- 您需要确保来自私有 IP 的默认路由流量通过 VPN 并被拦截。(即,在设置 VPN 并推送默认路由并正常工作之前,不要尝试上述操作)
- 如果 ssh 重定向到 vpn,请考虑管理 pyblic 服务器的困难。您可能希望在备用端口上设置 ssh(除非您对 vpn 有信心或有远程控制台)。
如果这仅适用于 ssh 和 http(s),那么我们还有另一种可能性 - 为 http(s) 设置反向代理 - 这可以通过 Apache 使用 ProxyPass 指令来完成,或者类似地使用 nginx - 无需诉诸 iptables 规则并通过 vpn 路由所有流量 - 并且允许您在家中和 vpn 上设置 Web 服务器。
类似地,您可以配置 SSH,使其充当跳转箱/堡垒 - 有多种方法可以执行此操作,具体取决于您尝试的操作,但 ProxyCommand 或 ProxyJump 指令可能会有用。
答案2
没关系在哪里您设置 DNS 服务器(或使用现有的)。DNS 不中继数据,它只提供地址,但实际连接是使用客户端自己的功能建立的。
因此,如果您创建A
指向网络内部 IP 地址的记录,则只有已连接到网络的客户端(例如通过 VPN 接入的设备)才能访问该记录。外部客户端将能够解析该地址,但无法访问它。
这意味着 DNS 记录必须指向民众地址——如果您的 VPS 只有一个公共 IPv4 地址,那么该地址必须放入您的 DNS 记录中,并且您的主服务器需要以某种方式“共享”相同的地址。
通常这意味着保留 VPS 上的地址,但使用 iptables 或 nftablesDNAT
规则将特定端口“端口转发”到您的家庭服务器。(这实际上与您在家中的端口转发相同。)
因为您只有一个地址,所以像 SSH 之类的东西将需要在非标准端口上运行 - 例如端口 22 仍然用于 SSH 到 VPS 本身,而端口 5022 被转发到您的家庭服务器,并且您无法在这里 ping 任何东西,它总是会转到一台机器。
(另外请记住,主服务器需要回应通过 tun0,而不是通过 eth0,因此您可能需要“策略路由”。在网站上搜索ip rule
,它已被多次描述。)
只有 HTTP 和 HTTPS 的情况比较好——所有的 HTTP 请求都指明了域名,所以如果两台机器需要同时提供 HTTP 服务,你可以使用反向代理让 VPS 内部路由所有对 的请求http://srv.example.com
,http://10.8.0.2
而无需 DNAT 端口转发的麻烦。
如果 VPS 有二IP 地址 – 那么一个可以继续分配给 VPS 本身,而另一个则通过 VPN 路由并分配给您的服务器(...或所有 DNAT 到服务器的内容)。使用 IPv6 很容易,但如果您需要接受 IPv4 客户端,那么从 VPS 提供商处获取第二个 IP 地址将需要额外付费。
在这种情况下,像 sshuttle 这样的附加隧道不会有帮助。它们实际上并没有做任何现有 VPN 隧道无法做到的事情。
答案3
虽然您问到的所有问题都可以完全解决,但这不是很好的解决方案。转发 ping 的想法尤其糟糕。还有其他方法,通常是首选。无论哪种方式,您都不需要任何额外的隧道。
让具有 10.8.0.x 地址的虚拟 NIC 在两台服务器上都命名tun0
。顺便说一句,这取决于 OpenVPN 模式,在更广泛使用的客户端-服务器设置中,您的服务器将有一个地址10.8.0.6
。我强烈建议为此 VPN 使用模式,因为它更高效。(只有当您确切知道需要时才tun
使用模式。)tap
为了便于解释,我们假设srv_pub是的192.0.2.1
,您需要为这两个名称设置公共 DNS:
pub.example.com. A 192.0.2.1
srv.example.com. CNAME pub.example.com.
我建议当您的公共 IP 发生变化时,CNAME 仅更改一条记录。
剩下的就看你选择的配置方式了。(可能还有其他方式,我只想到这两种。)
更好的方法
更好的方法更易于控制,也更容易配置和支持。
- 设置反向 HTTP(s) 代理在srv_pub。您可以使用 Apache、Nginx、Caddy 来实现这一点;有很多手册介绍如何做到这一点,包括 ServerFault 上的手册。您将创建
srv.example.com
虚拟主机并将其代理到10.8.0.2
。 - 请注意该服务器将终止 HTTP(s),您可以在那里安装公共 HTTP(s) 证书;如果使用 Let's Encrypt,您还可以在srv_pub并将控制这两个域名。
- 最好
srv.example.com
重新配置日志记录以保存真实客户端的 IP 地址而不是代理地址10.8.0.1
。 - 确保
/etc/ssh/sshd_config
srv_pub已AllowTcpForwarding
启用 - 为 SSH 创建一个用户名来连接此srv_pub。只需要转发 SSH 连接即可。我将其称为
forward_user
。您将在srv_目标我们打电话吧target_user
。 - 我不知道您要使用哪种软件通过 SSH 进行连接。但是,我建议使用 OpenSSH,它已安装在 Linux 中,并且是最新 Windows 中的一项功能。您可以将其配置为通过 srv_pub 连接到 srv_target。为此,请将以下内容添加到
~/.ssh/config
:
Host pub.example.com
User forward_user
Host srv.example.com
User target_user
ProxyJump pub.example.com
HostName 10.8.0.2
- 您需要在要连接到这些服务器的每个系统上配置此项。此外,我强烈建议创建 SSH 密钥对,同样,每个系统都应该有自己的密钥对。在本地计算机上生成一对密钥,并将私钥分发给两个服务器,最简单的方法是运行
ssh-copy-id pub.example.com
和ssh-copy-id srv.example.com
。这里和那里有很多关于 SSH 密钥的说明。
srv.example.com
现在,http 将通过 上的代理到达pub.example.com
。
该命令ssh srv.example.com
将连接到pub.example.com
,设置端口转发srv.example.com
,并通过此转发连接到它。它将在后台执行此操作,一切都会像您刚刚连接到目标服务器一样出现,正如运行此命令所预期的那样。如果您设置了密钥,它将不会要求输入密码;您可以使用 SSH 代理在登录本地系统后仅输入一次密钥密码。
还有 ping。这毫无意义。如果您想要监控srv.example.com
,请在目标主机上配置 Zabbix 代理,然后配置代理pub.example.com
或其他方式。
确切方法
虽然我认为这不是实现目标的最佳方式,但我会描述它,因为它是按照你要求的方式构建的。
- 在您的 VPN 主机上,您首先需要将 SSH 移至其他端口。这样,在您安装转发规则后,就可以连接到那里。设置成
/etc/ssh/sshd_config
这样Port 2222
或类似的东西,然后重新启动服务。 - 然后转发端口。别忘了启用 IP 转发:
iptables -t nat -I PREROUTING -p tcp -m multiport --dport 22,80,443 -j DNAT --to-destination 10.8.0.2
iptables -t nat -I PREROUTING -p icmp --icmp-type echo-request -j DNAT --to-destination 10.8.0.2
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.d/forwarding.conf
- 现在您需要设置目标服务器,以便通过 VPN 路由所有服务器流量,或者设置策略路由,以便通过 VPN 回复来自 VPN 的数据包。
请注意,这种 ping 转发就像是搬起石头砸自己的脚。它会误导你。最好跳过它。永远不要转发 ping。或者当出现问题并需要调试时,准备好找乐子。