激活IP转发时的路由问题

激活IP转发时的路由问题

工作场景

我有以下两个场景子网

  Subnet 1: 192.168.1.0/24
  Subnet 2: 192.168.2.0/24

和三个路由器

Router 1: 192.168.1.1
Router 2: 192.168.2.1
Router 3: 192.168.1.10 / 192.168.2.10

路由器 1 和 2 将每个子网连接到 Internet,并在所有客户端计算机上配置为默认网关。路由器 3 连接两个子网。为了使子网之间的路由正常工作,我配置了 2静态路由

  Router 1: Destination 192.168.2.0, Netmask 255.255.255.0, Gateway 192.168.1.10
  Router 2: Destination 192.168.1.0, Netmask 255.255.255.0, Gateway 192.168.2.10

我的目标是子网 1 中的客户端能够访问子网 2 上的 http/https 服务器

Client 1: 192.168.1.20        (Debian 9)
Server 1: 192.168.2.20        (Windows Server)

从客户端 1 我可以 ping 和 wget 服务器 1:

# ping 192.168.2.20
PING 192.168.2.20 (192.168.2.20) 56(84) bytes of data.
64 bytes from 192.168.2.20: icmp_seq=2 ttl=128 time=0.993 ms
64 bytes from 192.168.2.20: icmp_seq=3 ttl=128 time=0.943 ms
64 bytes from 192.168.2.20: icmp_seq=4 ttl=128 time=1.06 ms
64 bytes from 192.168.2.20: icmp_seq=5 ttl=128 time=1.77 ms
^C
--- 192.168.2.20 ping statistics ---
5 packets transmitted, 4 received, 20% packet loss, time 4046ms
rtt min/avg/max/mdev = 0.943/1.193/1.774/0.338 ms

# wget -O- http://192.168.2.20/
--2019-06-26 08:59:12--  http://192.168.2.20/
Connecting to 192.168.2.20:80... connected.
HTTP request sent, awaiting response... 302 Found
Location: /Test [following]
--2019-06-26 08:59:15--  http://192.168.2.20/Test
Reusing existing connection to 192.168.2.20:80.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [text/html]
Saving to: ‘STDOUT’

-                                   [<=>                                                   ]       0  --.-KB/s
<!DOCTYPE html>
<html>Hello World!</html>
-                                   [ <=>                                                  ]   5.77K  --.-KB/s    in 0.002s

2019-06-26 08:59:15 (2.79 MB/s) - written to stdout [5912]

到目前为止一切正常。只有第一个 ping 有时会丢失,据我了解,这不应该是一个问题。

问题

现在我必须在客户端 1(tun0,子网 10.0.0.0/24)上设置 OpenVPN 服务器。为了使 VPN 客户端不仅可以访问客户端 1,还可以访问子网 1 中的其他客户端,我激活了IP转发在 /etc/sysctl.conf 中

net.ipv4.ip_forward=1

当我激活 IP 转发时,我的上述路由设置就开始出现问题。从客户端 1 我仍然可以 ping 服务器 1,但使用 wget 通信不再正常工作:

# ping 192.168.2.20
PING 192.168.2.20 (192.168.2.20) 56(84) bytes of data.
From 192.168.1.1: icmp_seq=2 Redirect Host(New nexthop: 192.168.1.10)
64 bytes from 192.168.2.20: icmp_seq=2 ttl=128 time=0.935 ms
From 192.168.1.1: icmp_seq=3 Redirect Host(New nexthop: 192.168.1.10)
64 bytes from 192.168.2.20: icmp_seq=3 ttl=128 time=0.880 ms
From 192.168.1.1: icmp_seq=4 Redirect Host(New nexthop: 192.168.1.10)
64 bytes from 192.168.2.20: icmp_seq=4 ttl=128 time=0.975 ms
^C
--- 192.168.2.20 ping statistics ---
4 packets transmitted, 3 received, 25% packet loss, time 3041ms
rtt min/avg/max/mdev = 0.880/0.930/0.975/0.038 ms

# wget -O-  http://192.168.2.20
--2019-06-26 14:08:38--  http://192.168.2.20/
Connecting to 192.168.2.20:80... connected.
HTTP request sent, awaiting response... Read error (Connection reset by peer) in headers.
Retrying.

--2019-06-26 14:09:12--  (try: 2)  http://192.168.2.20/
Connecting to 192.168.2.20:80... connected.
HTTP request sent, awaiting response... Read error (Connection reset by peer) in headers.
Retrying.

^C

wget 仍然设法建立与服务器 1 的连接,但随后等待大约 30 秒以获得响应,然后才显示上述错误。

关于为什么 IP 转发会破坏客户端 1 和服务器 1 之间的通信有什么想法吗?关于如何正确配置客户端 1,以便同时路由到服务器 1 和从 OpenVPN 客户端访问子网 1,有什么建议吗?

我不想在客户端 1 上配置额外的静态路由,而是在默认网关上保留静态路由。

答案1

总结当前设置的影响和后果:

你的系统客户1具有标准配置,它不知道有关 192.168.2.0/24 的任何具体信息。这其实是路由器1其中通过以下方式定义了到 192.168.2.0/24 的特定路由路由器3。所以当客户1尝试访问 192.168.2.20,它在其路由表中查找,没有找到任何具体内容,使用默认路由:via路由器1路由器1检测到它自己的路由在同一个 LAN 上,因此不进行路由,而是告诉客户1,通过使用ICMP 重定向, 使用路由器3(的192.168.1.10网关IP)直接。客户1默认情况下,作为简单主机,接受 ICMP 重定向消息并将当前目标 192.168.2.20 的路由更改为经过 192.168.1.10 而不是 192.168.1.1。

由于您的系统客户1现在充当 10.0.0.0/24 中的节点和 192.168.1.0/24 中的节点之间的路由器,它还必须设置为路由器(例如通过使用net.ipv4.ip_forward=1)。

问题是之间的默认交互ip转发接受重定向:

accept_redirects - BOOLEAN
  Accept Redirects.

  Functional default: enabled if local forwarding is disabled.
              disabled if local forwarding is enabled.

现在这就是您当前的问题:由于启用了转发,所以接受重定向被禁用。因此它将忽略 ICMP 重定向并且不再使用 192.168.1.10。有两种方法可以避免:

  • 你不想做的事(但无论如何我会首先建议):因为客户1无论如何,现在是一个具有特定配置的路由器(VPN...),完成特定配置:添加正确的特定路由到192.168.2.0/24:

    # ip route add 192.168.2.0/24 via 192.168.1.10
    

    如果客户1配置为如果向上向下,您可以添加正确的接口节这一附加行:

        up ip route add 192.168.2.0/24 via 192.168.1.10
    

    对于其他方法,请搜索等效方法(例如:NetworkManager 甚至可以使用 GUI 小程序进行配置)。

    现在,充当路由器的系统可以随意忽略 ICMP 重定向,因为它不需要任何重定向,也不会触发接收任何重定向。

  • 或者,您可以调整特定接口上的特定行为,以便即使在转发时也不会忽略 ICMP 重定向:

    特定于接口的变体详细描述提供了更多选项:

    accept_redirects - BOOLEAN
      Accept ICMP redirect messages.
      accept_redirects for the interface will be enabled if:
      - both conf/{all,interface}/accept_redirects are TRUE in the case
        forwarding for the interface is enabled
      or
      - at least one of conf/{all,interface}/accept_redirects is TRUE in the
        case forwarding for the interface is disabled
      accept_redirects for the interface will be disabled otherwise
      default TRUE (host)
          FALSE (router)
    

    默认设置net.ipv4.ip_forward=1设置会有副作用net.ipv4.conf.all.accept_redirects=0(并设置回ip_forward=0会重置回来net.ipv4.conf.all.accept_redirects=1!)如第一段引文中所述。所以现在将出现:

    # sysctl net.ipv4.conf.all.accept_redirects net.ipv4.conf.default.accept_redirects
    net.ipv4.conf.all.accept_redirects = 0
    net.ipv4.conf.default.accept_redirects = 1
    

    所以所有接口都继承默认并且值为 1,但全局切换全部(对于此特定设置,不会强制接口值)未设置。您几乎必须反转这些值:设置全部至 1,默认并且每个接口都为 0,除了连接到的接口之外子网1(假设它被称为以太网0)也将设置为 1。忽略 ICMP 重定向通常是出于安全原因,或者可能是为了避免在多个配置错误的路由器之间触发循环,因此最好在不需要的地方忽略它。无论如何,在这里我将只激活所需的内容,而不停用任何内容(主要是因为我不知道其他接口名称),请随意完成。再次考虑接口子网1叫做以太网0:

    # sysctl -w net.ipv4.conf.all.accept_redirects=1 # must be done AFTER net.ipv4.ip_forward=1
    # sysctl -w net.ipv4.conf.eth0.accept_redirects=1 # which should be already set
    

    这可以在启动时配置sysctl.d设置您之前的设置。

现在为什么 ping 仍然有效并且连接在失败之前开始工作,我真的不知道。

在这两种情况下请注意:10.0.0.0/24 中的系统现在可能可以部分访问 192.168.2.0/24(可能通过调整自己的 VPN 配置)。部分原因是因为没有人知道返回 10.0.0.0/24 的路由,除非客户1正在做NAT。请务必考虑安全效果。您可能需要添加防火墙设置(例如iptables) 来禁止路由。

答案2

我建议您在客户端 1 上不需要 ip_forwarding,因为 OpenVPN 应该将数据包定向到正确的目的地(如果配置正确)。但无论如何:输出(转发打开后)表明数据包首先发送到路由器 1,问题是为什么,因为您的路由应该将其直接传递到路由器 3。所以你可以先检查路由器3上路由的数据包,看看源地址和目标地址。 “tcpdump -v -s0 -X”就可以了。

相关内容