it-swarm.cn

从本地网络环回到转发的公共IP地址-发夹NAT

这是关于发夹NAT(环回NAT)的 (规范问题 )。

这个问题的一般形式是:

我们有一个包含客户端,服务器和NAT路由器的网络。路由器上有到服务器的端口转发功能,因此某些服务可以从外部获得。我们有指向外部IP的DNS。本地网络客户端无法连接,但是需要外部工作。

  • 为什么失败了?
  • 如何创建统一的命名方案(在本地和外部均可使用的DNS名称)?

该问题的答案已与其他多个问题合并。他们最初引用了FreeBSD,D-Link,Microtik和其他设备。他们都在尝试解决相同的问题。

46
adopilot

您正在寻找的被称为“发夹NAT”。来自内部接口的对分配给外部接口的IP地址的请求应该经过NAT处理,就像它们是从外部接口传入的一样。

我完全不熟悉FreeBSD,但是请阅读OpenBSD的“ pf”手册( http://www.openbsd.org/faq/pf/rdr.html )建议的解决方案水平分割DNS,使用DMZ=网络,或TCP代理),让我相信“ pf”不支持发夹式NAT。

我会看一下水平分割DNS的路由,而不是内部使用URL中的IP地址,而是使用名称。

16
Evan Anderson

由于这已被提升为关于发夹NAT的规范问题,所以我认为它应该比当前接受的答案更普遍有效,尽管这一答案特别出色,但与FreeBSD。

此问题适用于由RFC1918寻址的IPv4网络上的服务器提供的服务,通过在网关处引入目标NAT(DNAT)),外部用户可以使用这些服务。内部用户然后尝试访问这些服务他们的数据包从客户端发送到网关设备,网关设备重写目的地地址,然后立即将其重新注入内部网络。正是这种急剧的转向,使得数据包在网关处产生了名称发夹NAT,类似于 发夹转

当网关设备重写目标地址而不是源地址时,就会出现问题。然后,服务器接收到一个数据包,该数据包包含一个内部目标地址(自己的地址)和一个内部源地址(客户的地址);它知道它可以直接回复这样的地址,所以就这样做了。由于该答复是直接的,因此它不会通过网关,因此永远不会有机会通过重写返回的源地址来平衡入站目的地NAT包。

客户端因此将数据包发送到外部 IP地址,但收到来自内部 IP地址的答复。不知道这两个数据包是同一对话的一部分,因此没有对话发生。

解决方案是对于需要此类目标NAT并从内部网络到达网关的数据包,还要对入站数据包执行源NAT(SNAT) ,通常是通过将源地址重写为网关的地址,然后服务器认为客户端是网关本身,并直接对其进行回复,从而使网关有机会平衡DNAT和SNAT对网关的影响。通过在返回数据包上重写源地址和目标地址来实现入站数据包。

客户端认为它正在与外部服务器通信。服务器认为它正在与网关设备通信。各方都很高兴。此时,图表可能会有所帮助:

enter image description here

一些消费者网关设备足够明亮,可以识别那些需要第二个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服务器配置为根据请求客户的地址。

49
MadHatter

这里的问题是,您的路由器没有NAT内部客户端的地址。因此,TCP握手失败。

假设以下IP

  • 客户端:192.168.1.3
  • 伺服器:192.168.1.2
  • 路由器内部:192.168.1
  • 外部路由器:123.123.123.1

这是正在发生的事情:

  1. 客户端(192.168.1.3)将TCP-SYN发送到您的外部IP端口80(123.123.123.1:80)
  2. 路由器会看到端口转发规则,并将数据包转发到服务器(192.168.1.2:80),而无需更改源IP(192.168.1.3)
  3. 客户端等待来自外部IP的SYN-ACK
  4. 服务器将其答案直接发送回客户端,因为它在同一子网中。它不会将数据包发送到路由器,这将使NAT反向。
  5. 客户端从192.168.1.2而不是123.123.123.1接收SYN-ACK。并丢弃它。
  6. 客户端仍在等待来自123.123.123.1的SYN-ACK并超时。
9
PEra

为什么不使用水平DNS而不是在各处硬编码IP地址?您将使ext.yourdomain在外部指向217.x.x.x,然后在内部指向192.x.x.x。

4
Ryaner

如果它是原始的D-Link路由器(即不是Virgin Media的Rev. D /固件版本1.00VG),则您应该能够调整设置以解决此问题。 (但是,出于许多其他原因,我同意上一个海报作者对DD-WRT的建议!)

  1. 登录路由器的Web界面
  2. 点击顶部的高级标签
  3. 单击左侧的防火墙设置选项卡
  4. 单击TCP端点过滤下的端点独立单选按钮,如图所示下面的屏幕截图(或在D-Link的网站上查看 路由器仿真器
  5. 保存更改;你完成了

D-Link router web UI screenshot

该屏幕截图来自Rev.C模型;您的可能会略有不同。

2
David

最近回答了类似的问题: Cisco static NAT在LAN端不起作用) ,并且刚刚意识到这是一个规范问题。所以请允许我总结一下解决方案在这里。

首先:忘掉NAT(如果可以的话)-问题根本不在于配置NAT。这是关于访问位于NAT无论是Internet还是LAN,都可以使用两个DNS区域,但并非总是解决方案,但是该解决方案确实存在并且非常简单(尽管可能并不完美):

(1)在服务器上:使用255.255.255.255掩码在服务器的网络接口上将公用IP地址添加为辅助IP地址(Web服务或服务器上您想要的任何内容也应侦听此IP地址);所有现代操作系统都允许您执行此操作(或者可以使用分配了公共IP地址的环回接口,而不是在主接口上添加辅助IP)。

(2)在LAN主机上:为公共IP地址添加主机路由,例如,对于Windows主机,请使用以下命令:route -p add 203.0.113.130 mask 255.255.255.255 192.168 .1.11(您也可以使用DHCP“静态路由”选项来分发路由)。或者,如果在客户端和面向Internet的路由器之间存在一个或多个L3交换机/路由器,则在此(这些)中间交换机/路由器上配置该主机路由,而不是在客户身上。

对于那些使用TCP三向握手:在建议的配置中可以正常工作的人。

请提供反馈(至少是投票)。

2
Sergio

从技术角度来看,解决此问题的最佳方法是在网络上启用IPv6。启用IPv6后,您需要为您的域创建AAAA记录。保持现有的A记录指向路由器的外部IPv4。创建一个指向服务器的IPv6地址的AAA​​A记录。

IPv6具有足够的地址来避免NAT,因此您不需要发夹NAT。并且一旦启用IPv6并创建AAAA,记录任何支持 RFC 8305 的客户端将在IPv4之前尝试IPv6。这意味着您也不需要发夹NAT,因为客户端不会使用它。

您将仍然需要现有的IPv4 NAT)用于传出连接,而端口转发则用于传入连接,直到世界上大多数地区也都启用了IPv6。

也更快。

与发夹式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,后者最好稍微慢一点,或者最坏的情况不会发生。

1
kasperd

病态回答我的问题仅仅是为了拓宽有类似问题的人的视野。

我与我的ISP联系并要求他们尝试解决我的问题。他们提供给我的是服务器专用的另一个公共IP地址,现在我在FreeBSD的WAN

1
adopilot

我将在此处添加答案,因为此处的评论未解决我的特定问题。我怀疑那是因为我遇到了一个讨厌的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,而LAN上的计算机尝试通过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,因此它可以工作一段时间。然后发生了以下情况(我不在乎重复该实验):

  1. 跨LAN到网关的ping时间以大约10秒的间隔增加了一倍,从0.1毫秒增加到0.2毫秒,0.4毫秒,0.8毫秒,2毫秒等,直到无法从LAN访问网关盒。它像数据包风暴一样闻起来,但是STP到处都打开了。
  2. 所有无线接入点都死了不久。
  3. 在尝试诊断无线问题时,所有IP电话都重新启动。
  4. 此后不久,有线机器失去了与局域网的所有联系。

唯一的解决方法是重新引导建筑物中的每台计算机。一个例外是硬件开关,无法重新启动。它们必须重新通电。

0
Russell Stuart

由于我也问过这个问题(请参阅 如何使用外部IP从内部访问在防火墙后面经过NAT的网络服务? )并在此处重定向,但此处的答案未提供解决方案(与通用解释相比)让我提供我的Linux(iptables具体)解决方案,以节省大家几个小时的实验时间。该文件为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.localweb.localweb.public.com替换为您的本地网络(例如10.0.x.0/24),网络服务器的本地IP(例如10.0.1.2)和路由器的公共IP (例如4.5.6.7)。 -4仅允许在同一文件中使用IPv6和IPv4规则(此类行被ip6tables忽略)。另外,当IPv6地址包含端口声明时,请记住将它们放在[括号]中,例如[fe0a:bd52::2]:80

这些都是导致我尝试实际实施这个问题的解释时引起我注意的所有事情。我希望我没有遗漏任何东西。

0
Jens

因为这是规范的问题。如果您有Sonicwall路由器,我会回答。

要知道的表达式是NAT环回策略

本文档介绍了SonicWall LAN上的主机如何使用服务器的FQDN公用IP地址访问SonicWall LAN上的服务器。想象一个NSA 4500(SonicOS增强))网络,其中主LAN子网是10.100.0.0/24,而主LAN 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将识别您尝试联系的外部服务,并将重写目标地址以适合服务器内部的地址,因此它将与计算机透明。

0
yagmoth555