本文介绍怎么使用C/C++从Linux路由表中添加移除无效的(Null Route)路由条目。
我们首先看一下怎么从命令行操作Linux路由表。
Linux路由表是在内核中的;查看:
$ sudo route -n
你也可以查看 /proc/net/route 文件。
添加Null Routes
Null routes简单的忽略和它相匹配的包。使用它可以有效的屏蔽某个有问题的IP。
例如:
$ sudo route add 123.123.123.123 reject
现在你不能和IP(123.123.123.123) 发送、接收数据包。
移除Null Routes
$ route del 123.123.123.123 reject
在操作路由表时要格外小心;如果你不小心移除了和SSH相关的远程主机路由,你只能通过访问物理主机解决。
使用C/C++更改路由表
要使用程序添加null route,你需要使用ioctl,控制参数SIOCADDRT:
#include <sys/types.h>
#include <sys/socket.h>
#include <net/route.h>
#include <sys/ioctl.h>
bool addNullRoute( long host )
{
// create the control socket.
int fd = socket( PF_INET, SOCK_DGRAM, IPPROTO_IP );
struct rtentry route;
memset( &route, 0, sizeof( route ) );
// set the gateway to 0.
struct sockaddr_in *addr = (struct sockaddr_in *)&route.rt_gateway;
addr->sin_family = AF_INET;
addr->sin_addr.s_addr = 0;
// set the host we are rejecting.
addr = (struct sockaddr_in*) &route.rt_dst;
addr->sin_family = AF_INET;
addr->sin_addr.s_addr = htonl(host);
// Set the mask. In this case we are using 255.255.255.255, to block a single
// IP. But you could use a less restrictive mask to block a range of IPs.
// To block and entire C block you would use 255.255.255.0, or 0x00FFFFFFF
addr = (struct sockaddr_in*) &route.rt_genmask;
addr->sin_family = AF_INET;
addr->sin_addr.s_addr = 0xFFFFFFFF;
// These flags mean: this route is created "up", or active
// The blocked entity is a "host" as opposed to a "gateway"
// The packets should be rejected. On BSD there is a flag RTF_BLACKHOLE
// that causes packets to be dropped silently. We would use that if Linux
// had it. RTF_REJECT will cause the network interface to signal that the
// packets are being actively rejected.
route.rt_flags = RTF_UP | RTF_HOST | RTF_REJECT;
route.rt_metric = 0;
// this is where the magic happens..
if ( ioctl( fd, SIOCADDRT, &route ) )
{
close( fd );
return false;
}
// remember to close the socket lest you leak handles.
close( fd );
return true;
}
注意:重启系统更改失效。
上面代码的反操作,移除route:
bool delNullRoute( long host )
{
int fd = socket( PF_INET, SOCK_DGRAM, IPPROTO_IP );
struct rtentry route;
memset( &route, 0, sizeof( route ) );
struct sockaddr_in *addr = (struct sockaddr_in *)&route.rt_gateway;
addr->sin_family = AF_INET;
addr->sin_addr.s_addr = 0;
addr = (struct sockaddr_in*) &route.rt_dst;
addr->sin_family = AF_INET;
addr->sin_addr.s_addr = htonl(host);
addr = (struct sockaddr_in*) &route.rt_genmask;
addr->sin_family = AF_INET;
addr->sin_addr.s_addr = 0xFFFFFFFF;
route.rt_flags = RTF_UP | RTF_HOST | RTF_REJECT;
route.rt_metric = 0;
// this time we are deleting the route:
if ( ioctl( fd, SIOCDELRT, &route ) )
{
close( fd );
return false;
}
close( fd );
return true;
}