当前位置:Linux教程 - 网络安全 - LIDS精通与进阶--八、内核的网络安全

LIDS精通与进阶--八、内核的网络安全

冰块


用LIDS,你可以用下面的功能来保护你的网络。

1、保护防火墙和路由的规则

如果你的主机包含一些防火墙规则。你可以用LIDS来保护它们。你可以开启

CONFIG_LIDS_ALLOW_CHANGE_ROUTESLAI 实现这个功能。你也必须在密封内核的时候关闭CAP_NET_ADMIN。

然后,你也可以允许程序更改路由规则。


让我们来看看保护防火墙规则的代码吧。每一个改变防火墙的请求都会调用内核的ip_setsockopt()函数。

int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int optlen)

{

........

switch(optname)

{

.......

case IP_FW_DELETE_NUM:

case IP_FW_INSERT:

case IP_FW_FLUSH:

case IP_FW_ZERO:

case IP_FW_CHECK:

case IP_FW_CREATECHAIN:

case IP_FW_DELETECHAIN:

case IP_FW_POLICY:

#ifdef CONFIG_LIDS_ALLOW_CHANGE_ROUTES

if (!(capable(CAP_NET_ADMIN) || (current->flags & PF_CHROUTES))) {

#else

if (!capable(CAP_NET_ADMIN)) {

#endif

#ifdef CONFIG_LIDS

lids_security_alert(""CAP_NET_ADMIN violation: try to change IP firewall rules with option %d"",optname);

#endif

return -EACCES;

}

........

从上面的代码,我们可以看到如果有人要改变防火墙的规则,你必须把CAP_NET_ADMIN开启,并且你要修改规则的程序必须用routing_changeable来标记。


2、禁止嗅探

这个功能也是在上面的changing_route来实现的。让我们来看看net/core/dev.c的代码。

int dev_ioctl(unsigned int cmd, void *arg)

{

........

switch(cmd)

{

........

case SIOCSIFMETRIC:

case SIOCSIFMTU:

case SIOCSIFMAP:

case SIOCSIFHWADDR:

case SIOCSIFSLAVE:

case SIOCADDMULTI:

case SIOCDELMULTI:

case SIOCSIFHWBROADCAST:

case SIOCSIFTXQLEN:

case SIOCSIFNAME:

#ifdef CONFIG_LIDS_ALLOW_CHANGE_ROUTES

if (!(capable(CAP_NET_ADMIN) || (current->flags & PF_CHROUTES))) {

#else

if (!capable(CAP_NET_ADMIN)) {

#endif

#ifdef CONFIG_LIDS

lids_security_alert(""CAP_NET_ADMIN violation: ioctl SIOC #%i"",cmd);

#endif

return -EPERM;

.........

你能发现,如果你要为嗅探改变状态的话, 你必须让CAP_NET_ADMIN开启来实现这个功能。你可以在内核密封前启动CAP_NET_ADMIN,然后在内核密封后禁止它。


3、内核的检测端口扫描的功能

为什么要在内核里需要一个端口扫描的检测?

因为一个端口扫描的时候能检测到半连接的扫描。所以,端口扫描检测需要作为一个嗅探的程序来运行。如果我们需要检测端口扫描。我们又要开启允许嗅探程序的运行,在内核中的端口扫描检测很有用处。


端口扫描的主要思想是在一段短的时间内扫描一个范围的端口,然后,它们会在扫描后记录那些端口是开放的。用这个方法,扫描器就可以检测到远端的机器开放了什么端口。在内核里,我们能发现下面的代码。


内核中的端口扫描检测

让我们看看tcp的端口扫描

/* in net/ipv4/tcp_ipv4.c */

int tcp_v4_rcv(struct sk_buff *skb, unsigned short len)

{

........

__skb_queue_tail(&sk->back_log, skb);

return 0;

no_tcp_socket:

#ifdef CONFIG_LIDS

lids_check_scan(skb->nh.iph->saddr,ntohs(th->dest));

#endif

tcp_v4_send_reset(skb);

discard_it:

.........

}

lids_check_scan()有两个参数,一个是影响no_sock_srror的源地址,另外一个是你要通讯的机器上的端口。


Lids_check_scan()主要的任务是统计由同一个资源发出的错误信息。但是lids_check_scan()在源地址是一个端口扫描器的时候不会做检查,它会要timer来做。现在,让我们看看lids_check_scan()的代码。

/* in net/ipv4/lids_check_scan.c */

int lids_check_scan(__u32 addr,__u16 port)

{

...........

if((p = lids_find_scan(addr)) == NULL) {

p1 = &lids_scan_head;

p = (struct lids_scan*)kmalloc(sizeof(struct lids_scan),GFP_ATOMIC);

if(p == NULL ) {

return -1;

}

while((p1->next)!=NULL)p1=p1->next;

/* init the structure. */

p1->next = p;

spin_unlock(p->lock);

p->next = NULL;

p->addr = addr;

p->counter = 0;

p->lower_counter = 0;

p->create_time = current_time;

/* init a timer to do the detect thing */

init_timer(&(p->timer));

p->timer.expires = LIDS_SCAN_TIMEOUT + current_time;

p->timer.data = (unsigned long) p;

p->timer.function = lids_proceed_scan ;

add_timer(&(p->timer));

}

/* add the counter when hit */

spin_lock(p->lock);

(p->counter)++;

/* we here defined the port < 1024 and > 1024 */

if(port < 1024)

(p->lower_counter)++;

spin_unlock(p->lock);

return 0;

}

从上面的代码,我们能看到这个函数的主要是一个列表,所以它很快。为了防止在kmalloc()的DoS的攻击,我们也需要来限制检测的列表。在这个代码里可能是错误的,但是因为记时的函数timer lids_proceed_scan能非常快的更新这个列表(每3秒一次)。所以DoS攻击很难让内核迷惑扫描源的真实性