猛士設計了Netfilter,在失眠的時候就有事作了,安息日應守爲聖日,不然會激怒神,所以雙休日我通常不學習和工做,相反,我會在午夜玩一些本身喜歡的東西。我沒有受過洗,不是由於不是篤信者,沒有安息夜...
linux
識別了協議好壞的標準以後,擴展字段如何佈局就純粹成了一個編碼問題,通常而言,「類型-長度-值」的方式是首選,它能夠很方便的編碼任意類型,任意長度的擴展字段,在TCP的協議頭擴展中,其名稱叫作options,即TCP選項,它即是採用了上述的編碼方式,每個選項我能夠稱之爲一個「塊」,整個TCP options由多個塊組成,每個塊由下面的結構組成:服務器
/* * xt_yyy - kernel module to drop TCP timestamps * * Original author: Wanagran <marywangran@126.com> */ #include <linux/module.h> #include <linux/netfilter/x_tables.h> #include <linux/netfilter.h> #include <linux/skbuff.h> #include <linux/tcp.h> #include <net/tcp.h> #include <linux/ip.h> #include "compat_xtables.h" MODULE_AUTHOR("Wanagran <marywangran@126.com>"); MODULE_DESCRIPTION("Xtables: yyy match module"); MODULE_LICENSE("GPL"); MODULE_ALIAS("ipt_yyy"); static unsigned int yyy_tg4(struct sk_buff **skb, const struct xt_action_param *par) { const struct iphdr *iph = (struct iphdr *)((*skb)->data); struct tcphdr *hdr; unsigned int hdroff = iph->ihl*4; int datalen = (*skb)->len - hdroff; int hdrsize = 8; /* TCP connection tracking guarantees this much */ const unsigned char *ptr; unsigned char buff[(15 * 4) - sizeof(struct tcphdr)]; int length; int recalc = 0; if (iph->protocol != IPPROTO_TCP) { return XT_CONTINUE; } hdr = (struct tcphdr *)((*skb)->data + hdroff); /** * 如下這個判斷不適合在代碼中寫死,由於: * iptables徹底能夠用TCP的flags match來完成這個判斷 * * if (!hdr->syn) { * return XT_CONTINUE; * } * * 另外,不少人應該以爲檢查一下conntrack是否已經加載,若是沒有加載就 * 直接CONTINUE,可是我沒有這麼作,由於NAT的實現並不必定要基於conntrack */ if ((*skb)->len >= hdroff + sizeof(struct tcphdr)) hdrsize = sizeof(struct tcphdr); if (!skb_make_writable(skb, hdroff + hdrsize)) return XT_CONTINUE; length = (hdr->doff*4) - sizeof(struct tcphdr); ptr = skb_header_pointer(*skb, sizeof(struct tcphdr) + hdroff, length, buff); while (length > 0) { int opcode=*ptr++; int opsize; switch (opcode) { case TCPOPT_EOL: returni XT_CONTINUE; case TCPOPT_NOP: /* Ref: RFC 793 section 3.1 */ length--; continue; case TCPOPT_TIMESTAMP: { int i = 0; char *base = ptr-1; opsize=*ptr; /** * 爲了減小數據移動以及指針移動,進而減小內存拷貝 * 我只是將時間戳替換成了NOP而已 */ for (; i < opsize; i++, base++) { *base = 0x01; } recalc = 1; } default: opsize=*ptr++; length -= opsize; ptr += opsize - 2; } } /** * 改變了TCP頭後,從新計算校驗碼是必然的,可是如下的 * 代碼太粗糙,由於它沒有考慮硬件也有能力計算校驗碼 * 這麼一件事! */ if (recalc) { hdr->check = 0; hdr->check = tcp_v4_check(datalen, iph->saddr, iph->daddr, csum_partial(hdr, datalen, 0)); } return XT_CONTINUE; } static struct xt_target yyy_tg_reg[] __read_mostly = { { .name = "YYY", .revision = 1, .family = NFPROTO_IPV4, .target = yyy_tg4, .me = THIS_MODULE, }, }; static int __init xt_yyy_target_init(void) { int status = 0; status = xt_register_targets(yyy_tg_reg, ARRAY_SIZE(yyy_tg_reg)); if (status < 0) { printk("YYY: register target error\n"); goto err; } err: return status; } static void __exit xt_yyy_target_exit(void) { return xt_unregister_targets(yyy_tg_reg, ARRAY_SIZE(yyy_tg_reg)); } module_init(xt_yyy_target_init); module_exit(xt_yyy_target_exit);
新建鏈接的SYN包:tcp
ESTABLISHED狀態的非SYN包:ide