通过“lo”接口跳过传出数据包的路由

通过“lo”接口跳过传出数据包的路由

介绍

我有以下负载平衡配置:

10.0.1.31 - lb
10.0.1.35 - virtual IP
10.0.1.32 - node1 (tomcat + mysql)
10.0.1.33 - node2 (tomcat + mysql)

我正在使用keepalived它将数据包重定向到活动节点 - 共享 IP 地址是 10.0.1.35。 lb 需要配置:

echo "net.ipv4.ip_nonlocal_bind = 1" >> /etc/sysctl.conf

要正确处理传入数据包,node1 和 node2 需要打开 10.0.1.35lo

[root@lb-node1 ~]# ip addr list dev lo
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN 
   link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
   inet 127.0.0.1/8 scope host lo
   inet 10.0.1.35/32 scope global lo
   inet6 ::1/128 scope host 
   valid_lft forever preferred_lft forever

问题

由于事实上,lo如果区域设置 tomcat 尝试通过 lb 连接到 mysql,则我们的端口为 10.0.1.35 - 已建立到本地实例的连接。

我想跳过lo传出数据包

测试

从已禁用 mysql 服务和lo接口上 10.0.1.35 ip 的node1 中,我尝试连接到node2 上的mysql。不幸的是结果是

   [root@lb-node1 ~]# telnet 10.0.1.35 3306
   Trying 10.0.1.35...
   telnet: connect to address 10.0.1.35: Connection refused 

当然,如果我从lo接口中删除10.0.1.35 IP,我就可以连接到node2上的mysql实例

解决方案(?)

我试图添加具有适当指标的路线,但这没有帮助:/

    [root@lb-node1 ~]# route -n
    Kernel IP routing table
    Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
    10.0.1.0        0.0.0.0         255.255.255.255 UH    0      0        0 eth0
    10.0.1.0        0.0.0.0         255.255.255.255 UH    100    0        0 lo
    169.254.0.0     0.0.0.0         255.255.0.0     U     1002   0        0 eth0
    0.0.0.0         10.0.1.1        0.0.0.0         UG    0      0        0 eth0

@帕特里克解决方案

vip=10.0.1.35

ip route add local $vip dev lo table 10 proto kernel scope host
ip rule add to $vip lookup 10 prio 1
ip route del local $vip dev lo table local
ip rule add to $vip iif lo lookup main prio 0

@Patrick 解决方案问题

初始状态

VIP+你的ip路由配置,mysql在两个节点上都工作


P Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  10.0.1.35:http rr persistent 6
TCP  10.0.1.35:mysql rr persistent 6
  -> 10.0.1.32:mysql              Route   10     0          0
  -> 10.0.1.33:mysql              Route   10     0          2
UDP  10.0.1.35:snmptrap rr persistent 6
  -> 10.0.1.32:snmptrap           Route   10     0          0
  -> 10.0.1.33:snmptrap           Route   10     0          1




root@lb-node1 ~]# mysql -h 10.0.1.35 -u test -p
Enter password: 
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 126
Server version: 5.5.36-MariaDB-wsrep-log MariaDB Server, wsrep_25.9.r3961

Copyright (c) 2000, 2014, Oracle, Monty Program Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> SHOW VARIABLES WHERE Variable_name = 'hostname';
+---------------+----------+
| Variable_name | Value    |
+---------------+----------+
| hostname      | lb-node2 |
+---------------+----------+
1 row in set (0.00 sec)

MariaDB [(none)]> 


[root@lb-node2 ~]# mysql -h 10.0.1.35 -u test -p
Enter password: 
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 133
Server version: 5.5.36-MariaDB-wsrep-log MariaDB Server, wsrep_25.9.r3961

Copyright (c) 2000, 2014, Oracle, Monty Program Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

ariaDB [(none)]> ;
ERROR: No query specified

MariaDB [(none)]> SHOW VARIABLES WHERE Variable_name = 'hostname';
+---------------+----------+
| Variable_name | Value    |
+---------------+----------+
| hostname      | lb-node2 |
+---------------+----------+
1 row in set (0.00 sec)

MariaDB [(none)]> 

如您所见,一切正常。

问题

但是当我关闭当前活动的 mysql 服务器时:

[root@lb-node2 ~]# service mysql stop
Shutting down MySQL.... SUCCESS! 
[root@lb-node2 ~]# 



Every 2.0s: ipvsadm -l                                                                                          Fri May  9 10:20:49 2014

IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  10.0.1.35:http rr persistent 6
TCP  10.0.1.35:mysql rr persistent 6
  -> 10.0.1.32:mysql              Route   10     0          0
UDP  10.0.1.35:snmptrap rr persistent 6
  -> 10.0.1.32:snmptrap           Route   10     0          0
  -> 10.0.1.33:snmptrap           Route   10     0          1

我无法从两个节点连接到 mysql

[root@lb-node2 ~]# mysql -h 10.0.1.35 -u test -p
Enter password: 

..... 

在我看来,node1 不接受传入数据包,因为负载均衡器正确重定向数据包

[root@lb-node1 ~]# tcpdump -i eth0 'port 3306' and src 10.0.1.33 or dst 10.0.1.33
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
10:35:26.915640 ARP, Reply 10.0.1.35 is-at 52:54:00:30:a3:4b (oui Unknown), length 28
10:35:26.915987 IP 10.0.1.33.38517 > 10.0.1.35.mysql: Flags [S], seq 2024730796, win 14600, options [mss 1460,sackOK,TS val 1298907 ecr 0,nop,wscale 7], length 0
10:35:27.914788 IP 10.0.1.33.38517 > 10.0.1.35.mysql: Flags [S], seq 2024730796, win 14600, options [mss 1460,sackOK,TS val 1299907 ecr 0,nop,wscale 7], length 0
10:35:29.914784 IP 10.0.1.33.38517 > 10.0.1.35.mysql: Flags [S], seq 2024730796, win 14600, options [mss 1460,sackOK,TS val 1301907 ecr 0,nop,wscale 7], length 0

有什么奇怪的,因为我仍然有 VIP 权限

[root@lb-node1 ~]# ip addr list dev lo
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet 10.0.1.35/32 scope global lo
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever



[root@lb-node1 ~]# ip route
10.0.1.0/24 dev eth0  proto kernel  scope link  src 10.0.1.32 
169.254.0.0/16 dev eth0  scope link  metric 1002 
default via 10.0.1.1 dev eth0 

答案1

我挖出了一些非常旧的代码,它所做的事情与您想要完成的事情类似。您可以执行以下操作来获得所需的效果:

vip=10.0.1.35

ip route add local $vip dev lo table 10 proto kernel scope host
ip rule add to $vip lookup 10 prio 1
ip route del local $vip dev lo table local
ip rule add to $vip iif lo lookup main prio 0

这将导致该盒子将任何流量发送10.0.1.35到网络(从而发送到正在应答该 IP 的 ARP 请求的负载平衡器)。但该盒子仍会接受负载均衡器提供的任何流量。


解释

我将不按顺序解释它们,因为这样更有意义。
 

ip route del local $vip dev lo table local

10.0.1.35这将删除表示通过 发送所有流量到本地主机的路由lo
 

ip route add local $vip dev lo table 10 proto kernel scope host

这会替换我们刚刚删除的表,但会将其放入一个全新的表 ( 10) 中。
 

ip rule add to $vip iif lo lookup main prio 0

这告诉系统当从本地盒子 ( iif lo)发送流量时10.0.1.35使用主路由而不是“本地”路由。这将使10.0.1.35流量选择10.0.1.0/24子网的路由(如果不是,则选择您的本地子网的路由/24)。
 

ip rule add to $vip lookup 10 prio 1

这条规则被添加为比上面的规则更低的优先级(更高的数字),以便它在后面匹配。如果流量与上述规则不匹配(不是iif lo),它将检查表10中是否有匹配的路由,这将选择我们之前添加的路由。
该规则(以及我们添加到 table 的路由10)的原因是负载均衡器发送到此框(因此不是iif lo)的任何流量都不会被拒绝。基本上它告诉内核“是的,这个IP属于我”。
 

我们将“本地”路由移至表中的原因10是我们希望iif lo lookup main prio 0规则匹配。但“本地”表具有最高优先级,因此它始终首先匹配。

 

我们按顺序添加规则的原因是为了防止中断。如果您按照说明中介绍的顺序添加它们,则会出现间隙,没有路由10.0.1.35会导致10.0.1.35发送到本地盒子的任何流量被拒绝。

相关内容