这是关于发夹式NAT(环回NAT)的规范问题。
这个问题的一般形式是:
我们有一个包含客户端,服务器和NAT路由器的网络。路由器上有到服务器的端口转发功能,因此某些服务可以从外部获得。我们有指向外部IP的DNS。本地网络客户端无法连接,但是需要外部工作。
- 为什么会失败?
- 如何创建统一的命名方案(在本地和外部均可使用的DNS名称)?
该问题的答案已与其他多个问题合并。他们最初引用了FreeBSD,D-Link,Microtik和其他设备。他们都在尝试解决相同的问题。
这是关于发夹式NAT(环回NAT)的规范问题。
这个问题的一般形式是:
我们有一个包含客户端,服务器和NAT路由器的网络。路由器上有到服务器的端口转发功能,因此某些服务可以从外部获得。我们有指向外部IP的DNS。本地网络客户端无法连接,但是需要外部工作。
该问题的答案已与其他多个问题合并。他们最初引用了FreeBSD,D-Link,Microtik和其他设备。他们都在尝试解决相同的问题。
Answers:
您正在寻找的被称为“发夹NAT”。来自内部接口的对分配给外部接口的IP地址的请求应该经过NAT处理,就像它们是从外部接口传入的一样。
我完全不熟悉FreeBSD,但是请阅读OpenBSD的“ pf”手册(http://www.openbsd.org/faq/pf/rdr.html)使用水平分割DNS的建议解决方案。 DMZ网络或TCP代理使我相信“ pf”不支持发夹式NAT。
我会看一下水平分割DNS的路由,而不是内部使用URL中的IP地址,而是使用名称。
no nat on $int_if proto tcp from $int_if to $int_net
, nat on $int_if proto tcp from $int_net to $hairpin_int port $hairpin_ports -> $int_if
, rdr on $int_if proto tcp from $int_net to $ext_if port $hairpin_ports -> $hairpin_int
由于这已经成为发夹式NAT的典型问题,我认为它应该比目前接受的答案更普遍有效,后者(尽管非常好)特别与FreeBSD有关。
此问题适用于由RFC1918寻址的IPv4网络上的服务器提供的服务,通过在网关上引入目标NAT(DNAT),外部用户可以使用这些服务。然后,内部用户尝试通过外部地址访问那些服务。他们的数据包从客户端发送到网关设备,网关设备重写目标地址,然后立即将其重新注入内部网络。类似于发夹式转折,正是分组在网关处做出的这种急转弯产生了发夹式NAT名称。
当网关设备重写目标地址而不是源地址时,就会出现问题。然后,服务器接收到一个数据包,该数据包包含一个内部目标地址(自己的地址)和一个内部源地址(客户的地址);它知道它可以直接回复这样的地址,所以就这样做了。由于该答复是直接的,因此它不会通过网关,因此网关永远不会有机会通过重写返回数据包的源地址来平衡入站目标NAT对初始数据包的影响。
客户端因此将数据包发送到外部 IP地址,但从内部 IP地址得到答复。不知道这两个数据包是同一对话的一部分,因此没有对话发生。
解决方案是,对于需要此类目标NAT并从内部网络到达网关的数据包,通常还通过将源地址重写为网关的地址,从而对入站数据包也执行源NAT(SNAT)。然后,服务器认为客户端就是网关本身,并直接对其进行回复。这样,通过在返回数据包上重写源地址和目标地址,网关便有机会平衡DNAT和SNAT对入站数据包的影响。
客户端认为它正在与外部服务器通信。服务器认为它正在与网关设备通信。各方都很高兴。此时,图表可能会有所帮助:
一些消费者网关设备足够亮,足以识别那些需要第二个NAT步骤的数据包,并且这些数据包可能在发夹式NAT场景中开箱即用。其他的则不是,所以也不会,因此不太可能使其正常工作。讨论哪些消费者级设备对服务器故障不适用。
通常可以告诉适当的网络设备正常工作,但是-因为它们不负责管理员,所以必须告知他们这样做。Linux用于iptables
执行DNAT:
iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.3.11
它将为HTTP端口启用简单的DNAT到上的内部服务器192.168.3.11
。但是要启用发夹式NAT,还需要一个规则,例如:
iptables -t nat -A POSTROUTING -d 192.168.3.11 -p tcp --dport 80 -j MASQUERADE
请注意,此类规则需要在相关链中的正确位置才能正常工作,并且根据filter
链中的设置,可能需要其他规则以允许NATted通信流。所有此类讨论均不在此答案的范围内。
但是,正如其他人所说,正确启用发夹NAT并不是解决问题的最佳方法。最佳的是水平分割DNS,您的组织可以根据请求客户端的位置为原始查询提供不同的答案,方法是为内部用户或外部用户使用不同的物理服务器,或者将DNS服务器配置为根据请求客户的地址。
iptables
,则当然可以选择进行配置。
这里的问题是,您的路由器没有对内部客户端的地址进行NAT。因此,TCP握手失败。
假设以下IP
这是正在发生的事情:
最近回答了一个类似的问题:Cisco静态NAT在LAN端不起作用,只是意识到这是一个规范问题。因此,请允许我在这里总结解决方案。
首先:忘记NAT(如果可以的话)-问题根本不在于配置NAT。这是关于从Internet和LAN访问位于NAT后面的服务器。使用两个DNS区域是一种可行的选择,但并非总是解决方案。但是解决方案确实存在并且非常简单(尽管可能并不完美):
(1)在服务器上:使用255.255.255.255掩码在服务器的网络接口上将公用IP地址添加为辅助IP地址(Web服务或服务器上您想要的任何内容也应监听该IP地址);所有现代操作系统都允许您执行此操作(或者可以使用分配了公共IP地址的环回接口,而不是在主接口上添加辅助IP)。
(2)在LAN主机上:为公共IP地址添加主机路由,例如,对于Windows主机,请使用以下命令:route -p添加203.0.113.130 mask 255.255.255.255 192.168.1.11(也可以使用DHCP“静态路由”选项来分配路由)。或者,如果在客户端和面向Internet的路由器之间存在一个或多个L3交换机/路由器,则在此(这些)中间交换机/路由器上配置该主机路由,而不是在客户身上。
对于那些涉及TCP三向握手的用户:在建议的配置中它可以正常工作。
请提供反馈(至少是投票)。
从技术角度来看,解决此问题的最佳方法是在网络上启用IPv6。启用IPv6后,您需要为您的域创建AAAA记录。保持现有的A记录指向路由器的外部IPv4 。创建一个指向服务器的IPv6地址的AAAA记录。
IPv6具有足够的地址来避免NAT,因此您不需要发夹式NAT即可实现IPv6。一旦启用了IPv6并创建了AAAA记录,任何支持RFC 8305的客户端都将在IPv4之前尝试IPv6。这意味着您也不需要IPv4的发夹式NAT,因为客户端不会使用它。
直到世界上大多数地区也启用了IPv6之前,您仍将需要现有的IPv4 NAT用于传出连接和端口转发以用于传入连接。
它也更快。
与发夹式NAT相比,使用IPv6将为您提供更好的性能。
使用发夹式NAT,您的客户端将通过交换机将数据包发送到路由器,然后路由器将执行两轮转换,最后通过交换机将数据包发送到服务器。从服务器到客户端的数据包将反向经过整个路径。
使用IPv6,您可以避免NAT,而是直接通过客户端和服务器之间的交换机发送数据包。这意味着在往返中,将通过交换机的次数从4减少到2,并且避免通过路由器的两次旅行以及路由器执行的4次转换。这转化为更好的性能。
即使您使用与路由器位于同一盒子中的交换机也是如此。
如果ISP没有IPv6怎么办?
如果您使用的是不支持IPv6的ISP,我会质疑您是否应该在该网络上托管服务器。这些是我对ISP当前不支持IPv6时应该怎么做的建议。
首先告诉ISP您需要 IPv6。也许提醒他们,IPv6协议已经存在了20年,因此他们早就应该支持它了。如果这还不足以让ISP认真对待您,请开始寻找其他ISP。
如果找到支持IPv6的ISP,则可以在过渡期内与这两个ISP一起运行。在连接到新ISP的路由器上,可以在LAN端禁用IPv4,然后将两个路由器的LAN端连接到同一交换机。IPv4和IPv6是两个独立的协议,因此,如果这些连接通过不同的路由器,则完全没有问题。附带的好处是,如果其中一个连接中断,它将为您提供一定程度的冗余。
如果找不到支持IPv6的ISP,则应考虑将服务器移至托管设施。在托管设施中使用服务器,您将不再依赖地理位置,因此,提供商之间的竞争会更加激烈,这将有助于确保有一个服务器能够满足您的需求。
将服务器移至托管设施并不会为您的客户端提供IPv6,但移动服务器意味着您不再需要发夹式NAT即可到达服务器。
你不应该做什么
如果您没有路由IPv6流量的方法,请不要打开IPv6并创建AAAA记录。如果您的ISP不支持IPv6,但是您仍然选择在LAN上启用IPv6(也许使用RFC 4193地址)并创建AAAA记录,它将对LAN上的客户端和LAN上的服务器起作用。但是,您的LAN与外部世界之间的通信将首先尝试使用IPv6(该方法无法正常工作),并且您将依赖回落到IPv4,后者最好稍微慢一点,或者最坏的情况不会发生。
由于我也问了这个问题(请参阅如何使用外部IP从内部访问在防火墙后面经过NAT的网络服务?)并在此处重定向,但此处的答案没有提供解决方案(与一般说明相反)iptables
在此处提供我的Linux(特定)解决方案,以节省每个人几个小时的实验时间。该文件具有iptables-restore
格式,可以直接读到iptables中(当然是在编辑IP地址之后)。这是针对Web服务器(端口80)且仅用于IPv4的-IPv6和SSL(端口443)的规则类似。
# Port forwarding for VM / Container access with „hairpin NAT“.
*nat
:PREROUTING ACCEPT [3:205]
:INPUT ACCEPT [59:670]
:OUTPUT ACCEPT [16:172]
:POSTROUTING ACCEPT [20:257]
# This was simple port forwarding - access works from outside but not from inside
#-A PREROUTING -4 -p tcp -i eth0 --dport 80 -j DNAT --to web.local:80
# This is real hairpin NAT which allows „web.local“ to access itself via the VM hosts external IP.
# First we need to masquerade any traffic going out the external interface:
-A POSTROUTING -o eth0 -j MASQUERADE
# Then we need to reroute incoming traffic on the public IP to the local IP:
-A PREROUTING -4 -p tcp -d web.public.com --dport 80 -j DNAT --to web.local:80
# And finally we need to tell the router that the source IP of any traffic
# coming from the LAN must be source-rewritten when going to the web server:
-A POSTROUTING -4 -p tcp -s lan.local/24 -d web.local --dport 80 -j SNAT --to-source web.public.com:80
COMMIT
替换为lan.local
,web.local
并将web.public.com
其替换为您的本地网络(例如10.0.x.0 / 24),Web服务器的本地IP(例如10.0.1.2)和路由器的公共IP(例如4.5.6.7)。在-4
仅仅允许在同一个文件IPv6和IPv4规则(无视这样的线ip6tables
)。另外,请记住在IPv6地址包含端口声明时将它们放在[花括号]中,例如[fe0a:bd52::2]:80
。
这些都是导致我在尝试实际实施此问题中的解释时拉扯头发的所有事情。我希望我没有遗漏任何东西。
我将在此处添加答案,因为此处的评论未解决我的特定问题。我怀疑那是因为我遇到了一个讨厌的linux内核错误。设置为:
internet <--> modem 1.1.1.1/30 <--> switch <---> LAN 10.1.1.0/24
^
+----------------------+ |
| /--eth0 o <----/
| | |
| 10.1.1.1/24 br0 | v (antenna)
| 1.1.1.2/30 | | |
| \-wlan0 o ----------/
+----------------------+
尽管外观复杂,但其他注释中涉及的情况的唯一相关更改是增加了软件桥br0。之所以在那里,是因为网关盒也是LAN的无线访问点。
我们的网关仍在为LAN上的计算机执行NAT任务。由于它只有1个以太网端口,因此被迫进行发夹式NAT。我怀疑它应该只与此处其他注释中给出的iptables规则一起使用,但是在Linux内核4.9上至少不是这样。在4.9以下,我们的网关盒可以访问Internet,而试图通过NAT访问它的局域网上的计算机则不能。
tcpdump
显示了对到达eth0的传入数据包的响应,但它们并非来自br0。运行此命令可修复以下问题:
ebtables -t brouter -A BROUTING -d 01:00:00:00:00:00/01:00:00:00:00:00 -j ACCEPT
ebtables -t brouter -A BROUTING -p IPv4 --ip-dst 10.1.1.0/24 -j ACCEPT
ebtables -t brouter -A BROUTING -p IPv4 --ip-src 10.1.1.0/24 -j ACCEPT
ebtables -t brouter -A BROUTING -p IPv4 -j DROP
在运行该命令之前,将根据内核的默认行为来处理传入的数据包,即将它们提供给网桥,然后将其传递给内核的路由模块。该命令强制非LAN的数据包绕过网桥,直接进入路由,这意味着网桥没有机会丢弃它们。广播和多播地址必须桥接,否则DHCP和mDNS之类的内容将无法正常工作。如果使用的是IPv6,则还必须为其添加规则。
您可能会尝试使用以下方法解决问题:
brctl hairpin br0 eth0 on
brctl hairpin br0 wlan0 on
我当然很受诱惑-这是我的第一次尝试。我一完成,局域网上的机器就可以访问Internet,因此它可以工作一段时间。然后发生了以下情况(我不在乎重复该实验):
唯一的解决方法是重新引导建筑物中的每台计算机。一个例外是硬件交换机,无法重新启动。它们必须重新通电。
因为这是规范的问题。如果您有Sonicwall路由器,我会回答。
要知道的表达式是NAT环回策略
本文档介绍了SonicWall LAN上的主机如何使用服务器的FQDN公用IP地址访问SonicWall LAN上的服务器。想象一下一个NSA 4500(SonicOS增强型)网络,其中主LAN子网为10.100.0.0 / 24,主WAN IP为3.3.2.1。假设您有一个供客户使用的网站,其主机名是。您已经编写了所需的策略和规则,以便外部人员可以访问该网站,但是它实际上在私有侧服务器10.100.0.2上运行。现在,假设您是一个使用IP为10.100.0.200的便携式计算机的人。您想使用服务器的公用名访问服务器,因为在旅途中笔记本电脑随身携带时,您会做同样的事情。如果您是坐在私人一侧,并请求http://www.example.com>,即使服务器实际上在本地IP地址上就在您旁边,也可以通过环回使它工作。
要启用此功能,您将需要创建NAT环回策略,也称为NAT反射或发夹。
使用WAN接口IP地址的环回策略
Login to the SonicWall Management GUI.
Navigate to Manage | Rules | NAT Policies submenu.
Click on the Add button.
Create the following NAT Policy.
Original Source: LAN Subnets (or Firewalled Subnets if you want hosts in other zones to be included)
Translated Source: WAN Interface IP
Original Destination: WAN Interface IP
Translated Destination: (LAN server object)
Original Service: Any
Translated Service: Original
Inbound Interface: Any
Outbound Interface: Any
SonicWALL将识别您尝试联系的外部服务,并将重写目标地址以适合服务器内部的地址,因此它将与计算机透明。