让建站和SEO变得简单

让不懂建站的用户快速建站,让会建站的提高建站效率!

栏目分类
热点资讯

首页

你的位置:易发购彩 > 首页 > 天天讲路由,那 Linux 路由到底咋扫尾的!?

天天讲路由,那 Linux 路由到底咋扫尾的!?

2022-03-13 20:11    点击次数:198

 

本文转载自微信公众号「设备内功修齐」,作家张彦飞allen。转载本文请琢磨设备内功修齐公众号。

众人好,我是飞哥。

容器是一种新的虚构化期间,每一个容器都是一个逻辑上孤苦的网罗环境。Linux 上提供了软件虚构出来的二层交换机 Bridge 不错搞定并吞个宿主机上多个容器之间互连的问题,但这是不够的。二层交换无法搞定容器和宿主机外部网罗的互通。

容器详情是需要和宿主机除外的外部网罗互通才具备实用价值的。比如在 Kubernets 中,就条款统统的 pod 之间都不错互通。极度于在原先物理机所构成的网罗之上,要再建一个互通的虚构网罗出来。这即是 Overlay 网罗的成见,用一个浮浅的示例图默示如下。

追溯在传统物理物理网罗中,不同子网之间的作事器是何如互联起来的呢,没错,即是在三层责任的路由器,也叫网关。路由器使得数据包不错从一个子网中传输到另一个子网中,进而扫尾更大范围的网罗互通。如下图所示,一台路由器将 192.168.0.x 和 192.168.1.x 两个子网聚拢了起来。

在容器虚构化网罗中,当然也需要这样一个扮装,将容器和宿主机除外的网罗聚拢起来。其实 Linux 天生就具备路由的功能,仅仅在云原生期间,它的路由功能再一次找到了用武之地。在容器和外部网罗通讯的流程中,Linux 就又承担起路由器的扮装,扫尾容器数据包的正确转发和送达。

在各式基于容器的云原生期间盛行的今天,再次回头潜入剖判路由责任旨趣显得尽头有必要,况兼也尽头的有价值。今天,咱们就再来强化一下 Linux 上的路由学问!

一、什么时辰需要路由

先来聊聊 Linux 在什么情况下需要路由流程。其确实发送数据时和摄取数据时都会波及到路由选定,为什么?咱们挨个来看。

1.1 发送数据时选路

Linux 之是以在发送数据包的时辰需要进行路由选定,这是因为作事器上是可能会有多张网卡建立存在的。数据包在发送的时辰,一齐通过用户态、TCP 层到了 IP 层的时辰,就要进行路由选定,以决定使用哪张网卡建立把数据包送出去。详备流程参见25 张图,一万字,拆解 Linux 网罗包发送流程

来大致过一下路由关联源码源码。网罗层发送的进口函数是 ip_queue_xmit。

//file: net/ipv4/ip_output.c int ip_queue_xmit(struct sk_buff *skb, struct flowi *fl) {  // 路由选定流程  // 选定完跋文录路由信息到 skb 上  rt = (struct rtable *)__sk_dst_check(sk, 0);  if (rt == NULL) {   // 莫得缓存则查找路由项   rt = ip_route_output_ports(...);   sk_setup_caps(sk, &rt->dst);  }  skb_dst_set_noref(skb, &rt->dst);  ...  //发送  ip_local_out(skb); } 

在 ip_queue_xmit 里咱们着手就看到了路由项查找, ip_route_output_ports 这个函数中完成路由选定。路由选定即是到路由表中进行匹配,然后决定使用哪个网卡发送出去。

Linux 中最多不错有 255 张路由表,其中默许情况下有 local 和 main 两张。使用 ip 大喊不错张望路由表的具体竖立。拿 local 路由表来例如。

#ip route list table local local 10.143.x.y dev eth0 proto kernel scope host src 10.143.x.y local 127.0.0.1 dev lo proto kernel scope host src 127.0.0.1 
1.2 摄取数据时选路

没错,摄取数据包的时辰也需要进行路由选定。这是因为 Linux 可能会像路由器相同责任,将收到的数据包通过合适的网卡将其转发出去。

Linux 在 IP 层的摄取进口 ip_rcv 引申后调用到 ip_rcv_finish。在这里张开路由选定。要是发现照实即是本建立的网罗包,那么就通过 ip_local_deliver 送到更表层的 TCP 层进行处理。

要是路由后发现非本建立的网罗包,那就插足到 ip_forward 进行转发,临了通过 ip_output 发送出去。

具体的代码如下。

//file: net/ipv4/ip_input.c static int ip_rcv_finish(struct sk_buff *skb){     ...     if (!skb_dst(skb)) {         int err = ip_route_input_noref(skb, iph->daddr, iph->saddr,                            iph->tos, skb->dev);         ...     }     ...     return dst_input(skb); } 

其中 ip_route_input_noref 即是在进行路由查找。

//file: net/ipv4/route.c int ip_route_input_noref(struct sk_buff *skb, __be32 daddr, __be32 saddr,     u8 tos, struct net_device *dev) {  ...  res = ip_route_input_slow(skb, daddr, saddr, tos, dev);  return res; } 

这里记住 ip_route_input_slow 就行了,背面咱们再看。

1.3 linux 路由小结

路由在内核合同栈中的位置不错用如下一张图来默示。

网罗包在发送的时辰,需要从本机的多个网卡建立中选定一个合适的发送出去。网罗包在摄取的时辰,也需要进行路由选定,要是是属于本建立的包就往表层送到网罗层、传输层直到 socket 的摄取缓存区中。要是不是本建立上的包,就选定合适的建立将其转发出去。

二、Linux 的路由扫尾 2.1 路由表

路由表(routing table)在内核源码中的另外一个叫法是转发信息库(Forwarding Information Base,FIB)。是以你在源码中看到的 fib 着手的界说基本上即是和路由表关联的功能。

其中路由表自己是用 struct fib_table 来默示的。

struct fib_table {  struct hlist_node tb_hlist;  u32   tb_id;  int   tb_default;  int   tb_num_default;  unsigned long  tb_data[0]; }; 

统统的路由表都通过一个 hash - fib_table_hash 来组织和管制。它是放在网罗定名空间 net 下的。这也就诠释每个定名空间都有我方孤苦的路由表。

//file:include/net/net_namespace.h struct net {  struct netns_ipv4 ipv4;  ... }  //file: include/net/netns/ipv4.h struct netns_ipv4 {  // 统统路由表   struct hlist_head *fib_table_hash;   // netfilter  ... } 

在默许情况下,Linux 只消 local 和 main 两个路由表。要是内核编译时扶植战术路由,那么管制员最多不错竖立 255 个孤苦的路由表。

要是你的作事器上创建了多个网罗定名空间的话,那么就会存在多套路由表。以除了默许定名网罗空间外,又创显明一个新网罗定名空间的情况为例,路由表在统统这个词内核数据结构中的关联关联记忆如下图所示。

2.2 路由查找

在上头的末节中咱们看到,发送流程调用 ip_route_output_ports 来查找路由,摄取流程调用 ip_route_input_slow 来查找。但其实这两个函数都又最终会调用到 fib_lookup 这个中枢函数,源码如下。

//file: net/ipv4/route.c struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4) {  ...  // 插足 fib_lookup  if (fib_lookup(net, fl4, &res)) {  } }  //file: net/ipv4/route.c static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,           u8 tos, struct net_device *dev) {  ...  // 插足 fib_lookup  err = fib_lookup(net, &fl4, &res); } 

咱们来看下 fib_loopup 都干了啥。为了容易剖判,咱们只看一下不扶植多路由表版块的 fib_lookup。

//file: include/net/ip_fib.h static inline int fib_lookup(struct net *net, const struct flowi4 *flp,         struct fib_result *res) {  struct fib_table *table;   table = fib_get_table(net, RT_TABLE_LOCAL);  if (!fib_table_lookup(table, flp, res, FIB_LOOKUP_NOREF))   return 0;   table = fib_get_table(net, RT_TABLE_MAIN);  if (!fib_table_lookup(table, flp, res, FIB_LOOKUP_NOREF))   return 0;  return -ENETUNREACH; } 

这个函数即是次第到 local 和 main 表中进行匹配,匹配到后就复返,不会不息往下匹配。从上头不错看到 local 表的优先级要高于 main 表,要是 local 表中找到了规矩,则路由流程就规矩了。

这也即是许多同学说为什么 ping 本机的时辰在 eth0 上抓不到包的压根原因。统统掷中 local 表的包都会被送往 loopback 缔造,不会过 eth0。

三、路由的使用形式 3.1 开启转发路由

在默许情况下,Linux 上的转发功能是关闭的,这时辰 Linux 发现收到的网罗包不属于我方就会将其丢弃。

但在某些场景下,例如关于容器网罗来说,Linux 需要转发本机上其它网罗定名空间中过来的数据包,需要手工开启转发。如下这两种形式都不错。

# sysctl -w net.ipv4.ip_forward=1 # sysctl net.ipv4.conf.all.forwarding=1 

开启后,Linux 就能像路由器相同对不属于本机(严格地说是本网罗定名空间)的 IP 数据包进行路由转发了。

3.2 张望路由表

在默许情况下,Linux 只消 local 和 main 两个路由表。要是内核编译时扶植战术路由,那么管制员最多不错竖立 255 个孤苦的路由表。在 centos 上不错通过以下相貌张望是否开启了 CONFIG_IP_MULTIPLE_TABLES 多路由表扶植。

# cat /boot/config-3.10.0-693.el7.x86_64  CONFIG_IP_MULTIPLE_TABLES=y ... 

统统的路由表按照从 0 - 255 进行编号,每个编号都有一个别称。编号和别称的对应关联在 /etc/iproute2/rt_tables 这个文献里不错查到。

# cat /etc/iproute2/rt_tables 255     local 254     main 253     default 0       unspec 200     eth0_table 

张望某个路由表的竖立,通过使用 ip route list table {表名} 来张望。

#ip route list table local local 10.143.x.y dev eth0 proto kernel scope host src 10.143.x.y local 127.0.0.1 dev lo proto kernel scope host src 127.0.0.1 

要是是张望 main 路由表,也不错获胜使用 route 大喊

# route -n Kernel IP routing table Destination     Gateway         Genmask         Flags Metric Ref    Use Iface 10.0.0.0        10.*.*.254      255.0.0.0       UG    0      0        0 eth0 10.*.*.0        0.0.0.0         255.255.248.0   U     0      0        0 eth0 

上头字段中的含义如下

Destination:办法地址,不错是一个具体的 IP,也不错是一个网段,和 Genmask 沿途默示。 Gateway:网关地址,要是是 0.0.0.0 默示不需要经过网关。 Flags: U 默示有用,G 默示聚拢路由,H 这条文矩是主机路由,而不是网罗路由。 Iface:网卡建立,使用哪个网卡将包送已往。

上述恶果中输出的第一条路由规矩默示这台机器下,真正地说这个网罗环境下,统统打算为 10.0.0.0/8(Genmask 255.0.0.0 默示前 8 位为子网掩码) 网段的网罗包都要通过 eth0 建立送到 10...254 这个网关,由它再匡助转发。

第二条路由规矩默示,要是办法地址是 10...0/21(Genmask 255.255.248.0 默示前 21 位为子网掩码)则获胜通过 eth0 发出即可,不需要经过网关就可通讯。

3.3 修改路由表

默许的 local 路由表是内核笔据刻下机器的网卡建立竖立自动生成的,不需要手工珍惜。关于main 的路由表竖立咱们一般只需要使用 route add 大喊就不错了,删除使用 route del。

修改主机路由

# route add -host 192.168.0.100 dev eth0 //直连无须网关 # route add -host 192.168.1.100 dev eth0 gw 192.168.0.254 //下一跳网关 

修改网罗路由

# route add -net 192.168.1.0/24 dev eth0 //直连无须网关 # route add -net 192.168.1.0/24 dev eth0 gw 10.162.132.110 //下一跳网关 

也不错指定一条默许规矩,不掷中其它规矩的时辰会引申到这条。

# route add default gw 192.168.0.1 eth0 

关于其它编号的路由表想要修改的话,就需要使用 ip route 大喊了。这里不外多张开,只用 main 表举一个例子,有更多使用需求的同学请自行搜索。

# ip route add 192.168.5.0/24 via 10.*.*.110 dev eth0 table main 
3.4 路由规矩测试

在竖立了一系列路由规矩后,为了快速校验是否适应预期,不错通过 ip route get 大喊来阐发。

# ip route get 192.168.2.25 192.168.2.25 via 10.*.*.110 dev eth0 src 10.*.*.161     cache 
本文记忆

在现如今各式网罗虚构化期间里,到处都能看着对路由功能的活泼控制。是以咱们今天特意深入征询了一下 Linux 路由责任旨趣。

在 Linux 内核中,关于发送流程和摄取流程都会波及路由选定,其中摄取流程的路由选定是为了判断是该腹地摄取依然将它转发出去。

 

默许有 local 和 main 两个路由表,不外要是安设的 linux 开启了 CONFIG_IP_MULTIPLE_TABLES 选项的话,最多能扶植 255 张路由表。

路由选定流程其实不复杂,即是笔据各个路由表的竖立找到合适的网卡建立,以及下一跳的地址,然后把包转发出去就算是完事。

通过合适地竖立路由规矩,容器中的网罗环境和外部的通讯不再是难事。通过大宗地干扰路由规矩就不错扫尾虚构网罗互通。

 

好了,今天的共享就到这里了,期待你的点赞、再看和转发~~

 



Powered by 易发购彩 @2013-2022 RSS地图 HTML地图

Copyright 365建站 © 2013-2021 365建站器 版权所有