获取和解释路由表信息

Getting and interpreting routing table information


Posted by Diego Assencio on 2014.12.30 under Linux (Networking)

This post will describe how you can obtain and interpret the routing table of your Linux device. A routing table is a list containing the routes which network packets take based on their destination IP addresses.

To understand this post, you must understanding two things first: the CIDR notation, which is used for specifying IP subnetworks in the format <network-prefix>/<netmask-length>, and the of longest prefix match algorithm. If you don't understand them, take the time to read the linked articles before proceeding. As a side note, our examples will study IPv4 networks, but all concepts we go over apply to IPv6 networks as well.

On Linux, there are two commands which are typically used for obtaining routing table information: route and ip. This post will use the ip command because its output is much easier to interpret than the output of route. To show the routing table of your system with the ip command, open a terminal and run:

ip route show

The output will depend on your network configuration. Here is an example which is very common for devices connected to a wireless router in home networks:

default via 192.168.1.1 dev wlan0
192.168.1.0/24 dev wlan0  proto kernel  scope link  src 192.168.1.100

Let's interpret the output above by starting with the second line. This line says that packets sent to any IP address within the subnetwork 192.168.1.0/24 must be sent through the network interface wlan0 (a wireless network ínterface) with 192.168.1.100 as the source IP address, which in this case is the IP address assigned to wlan0 via DHCP. The other parts are not so interesting: proto kernel means this entry in the routing table was created by the kernel during autoconfiguration, while scope link means the destination IP addresses within 192.168.1.0/24 are valid only on the device wlan0.

The first line says that the default route for any packet (i.e., the route which is taken by a packet when no other route applies) is through the network device wlan0 via the default gateway (the router) which has the IP address 192.168.1.1. Figure 1 shows this network scheme.

.

The ip command is very flexible in terms of its input parameters. You can write them only partially and ip will autocomplete them internally. To clarify, all commands below are equivalent:

ip r s
ip r show
ip ro sh
ip route show

A complex example: VPN routing

When you connect to a virtual private network (VPN), your network traffic is sent through an encrypted tunnel to the VPN server. As an example, let's analyze how OpenVPN does this. Consider what happens if the user of the laptop shown on figure 1 connects to an OpenVPN server. First, a virtual network interface (usually named tun0) is created. Routes are then added to the routing table to have all traffic be sent through this virtual interface, where packets are encrypted and sent through the (physical) interface wlan0 to the OpenVPN server. Figure 2 shows a summary of this setup.

Below is a possible routing table for the OpenVPN client after it connects to the OpenVPN server:

0.0.0.0/1 via 192.168.254.9 dev tun0
default via 192.168.1.1 dev wlan0
95.91.22.94 via 192.168.1.1 dev wlan0
128.0.0.0/1 via 192.168.254.9 dev tun0
192.168.1.0/24 dev wlan0  proto kernel  scope link  src 192.168.1.100
192.168.254.0/24 via 192.168.254.9 dev tun0
192.168.254.9 dev tun0  proto kernel  scope link  src 192.168.254.10

Going over all the details of this routing table would be tedious, so we will focus on what matters here. Notice the second line: the default route has not changed. However, the first and fourth lines introduce two new routes which completely change the rules of the game: packets with destination addresses matching either 0.0.0.0/1 or 128.0.0.0/1 are now sent through the device tun0 with 192.168.254.9 as the gateway IP address.

The catch here is the fact that 0.0.0.0/1 and 128.0.0.0/1 match packets with destination IP addresses having the first bit equal to 0 and 1 respectively. Together, they match all packets which are not matched by other routes and effectively make the original default route have no effect because of the longest prefix matching rule: the first bit of a packet will always be either 0 or 1, so the default route will never be applied. In other words, OpenVPN creates two routes which together swallow each packet by matching its first bit (except for packets matching other more specific routes, of course); the packet is then sent on the interface tun0. From there, packets are encrypted and then sent to 95.91.22.94 (the OpenVPN server). Not surprisingly, the route specified on the third line causes those packets to be sent through the physical interface wlan0 via the gateway 192.168.1.1.

For the more curious reader, the IP address 192.168.254.9 comes from the fact that in the example above, OpenVPN creates the tun0 interface in point-to-point mode, meaning this interface works as if directly connected to another endpoint: the OpenVPN server. The server creates a virtual local network 192.168.254.0/24 and assigns IP addresses from this pool to each endpoint of the connection. As shown on the last line, the IP address assigned to the client is 192.168.254.10, with 192.168.254.9 being the IP address of the server endpoint. This can be seen more clearly by running:

ip addr show dev tun0

In our example, this gives us a clear indication of the point-to-point connection mentioned in the previous paragraph:

21: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 100
    link/none
    inet 192.168.254.10 peer 192.168.254.9/32 scope global tun0
       valid_lft forever preferred_lft forever

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用Socket编程来获取Linux的IPv6路由表。下面是一个使用C语言编写的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> #include <netinet/ip6.h> #include <netinet/icmp6.h> #include <arpa/inet.h> #include <net/if.h> #include <net/route.h> #define BUF_SIZE 4096 int main() { int sock; struct rtmsg *route_entry; struct nlmsghdr *nl_header; struct rtattr *rt_attribute; char buffer[BUF_SIZE]; // 创建socket sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); if (sock < 0) { perror("socket"); exit(1); } // 初始化请求消息 memset(buffer, 0, BUF_SIZE); nl_header = (struct nlmsghdr *)buffer; nl_header->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); nl_header->nlmsg_type = RTM_GETROUTE; nl_header->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; nl_header->nlmsg_seq = 1; nl_header->nlmsg_pid = getpid(); // 设置请求消息的路由属性 rt_attribute = (struct rtattr *)NLMSG_DATA(nl_header); rt_attribute->rta_type = RTA_DST; rt_attribute->rta_len = RTA_LENGTH(sizeof(struct in6_addr)); inet_pton(AF_INET6, "2001:db8::/32", RTA_DATA(rt_attribute)); // 发送请求消息 if (send(sock, nl_header, nl_header->nlmsg_len, 0) < 0) { perror("send"); exit(1); } // 接收并处理回复消息 while (1) { int len = recv(sock, buffer, BUF_SIZE, 0); if (len < 0) { perror("recv"); exit(1); } for (nl_header = (struct nlmsghdr *)buffer; NLMSG_OK(nl_header, len); nl_header = NLMSG_NEXT(nl_header, len)) { if (nl_header->nlmsg_type == NLMSG_DONE) { break; } route_entry = (struct rtmsg *)NLMSG_DATA(nl_header); rt_attribute = (struct rtattr *)RTM_RTA(route_entry); int rt_attr_len = RTM_PAYLOAD(nl_header); for (; RTA_OK(rt_attribute, rt_attr_len); rt_attribute = RTA_NEXT(rt_attribute, rt_attr_len)) { if (rt_attribute->rta_type == RTA_DST) { struct in6_addr *addr = (struct in6_addr *)RTA_DATA(rt_attribute); char ip_str[INET6_ADDRSTRLEN]; inet_ntop(AF_INET6, addr, ip_str, sizeof(ip_str)); printf("Route: %s\n", ip_str); } } } } // 关闭socket close(sock); return 0; } ``` 注意:需要在代码中修改`inet_pton(AF_INET6, "2001:db8::/32", RTA_DATA(rt_attribute))`这一行,将`"2001:db8::/32"`改为你想要查询的IPv6网段。 这段代码使用Netlink套接字接口向内核发送RTM_GETROUTE消息,并解析内核的回复,将获取到的IPv6路由表打印出来。请确保以root权限运行代码,因为获取路由表需要特权访问。 希望对你有帮助!如果有任何疑问,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值