Skip to content

Instantly share code, notes, and snippets.

@fqrouter
Created April 16, 2011 17:04
Show Gist options
  • Save fqrouter/923295 to your computer and use it in GitHub Desktop.
Save fqrouter/923295 to your computer and use it in GitHub Desktop.
西厢1服务器
/*
* "CUI" target extension for Xtables
* copied from "DELUDE" target
* Copyright © Jan Engelhardt <jengelh [at] medozas de>, 2007 - 2008
* Klzgrad <klzgrad@gmail.com>, 2010
*
* Based upon linux-2.6.18.5/net/ipv4/netfilter/ipt_REJECT.c:
* (C) 1999-2001 Paul `Rusty' Russell
* (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/netfilter/x_tables.h>
#ifdef CONFIG_BRIDGE_NETFILTER
# include <linux/netfilter_bridge.h>
#endif
#include <net/tcp.h>
#include "compat_xtables.h"
#define PFX KBUILD_MODNAME ": "
static void cui_send_reset(struct sk_buff *oldskb, unsigned int hook)
{
struct tcphdr _otcph, *tcph;
const struct tcphdr *oth;
const struct iphdr *oiph;
struct sk_buff *skb;
struct iphdr *iph;
unsigned int addr_type;
oiph = ip_hdr(oldskb);
/* do not deal with fragment */
if (oiph->frag_off & htons(IP_OFFSET))
return;
oth = skb_header_pointer(oldskb, ip_hdrlen(oldskb),
sizeof(_otcph), &_otcph);
if (oth == NULL)
return;
/* syn[ack] only */
if (!oth->syn || oth->ack || oth->rst || oth->fin)
return;
/* check checksum */
if (nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), IPPROTO_TCP))
return;
skb = alloc_skb(sizeof(struct iphdr) + sizeof(struct tcphdr) +
LL_MAX_HEADER, GFP_ATOMIC);
if (skb == NULL)
return;
/* construct from scratch */
skb_reserve(skb, LL_MAX_HEADER);
skb_reset_network_header(skb);
iph = (struct iphdr *)skb_put(skb, sizeof(struct iphdr));
iph->version = 4;
iph->ihl = sizeof(struct iphdr) / 4;
iph->tos = 0;
iph->id = 0;
iph->frag_off = htons(IP_DF);
iph->protocol = IPPROTO_TCP;
iph->check = 0;
iph->saddr = oiph->daddr;
iph->daddr = oiph->saddr;
tcph = (struct tcphdr *)skb_put(skb, sizeof(struct tcphdr));
memset(tcph, 0, sizeof(*tcph));
tcph->source = oth->dest;
tcph->dest = oth->source;
tcph->doff = sizeof(struct tcphdr) / 4;
tcph->window = 0xffffU;
tcph->rst = true;
tcph->seq = 0;
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 20)
tcph->check = tcp_v4_check(tcph, sizeof(struct tcphdr), iph->saddr,
iph->daddr, csum_partial((char *)tcph,
sizeof(struct tcphdr), 0));
#else
tcph->check = tcp_v4_check(sizeof(struct tcphdr), iph->saddr,
iph->daddr, csum_partial((char *)tcph,
sizeof(struct tcphdr), 0));
#endif
addr_type = RTN_UNSPEC;
#ifdef CONFIG_BRIDGE_NETFILTER
if (hook != NF_INET_FORWARD || (skb->nf_bridge != NULL &&
skb->nf_bridge->mask & BRNF_BRIDGED))
#else
if (hook != NF_INET_FORWARD)
#endif
addr_type = RTN_LOCAL;
/* ip_route_me_harder expects skb->dst to be set */
skb_dst_set(skb, dst_clone(skb_dst(oldskb)));
if (ip_route_me_harder(&skb, addr_type))
goto free_skb;
else
iph = ip_hdr(skb);
iph->ttl = dst_metric(skb_dst(skb), RTAX_HOPLIMIT);
skb->ip_summed = CHECKSUM_NONE;
/* "Never happens" */
if (skb->len > dst_mtu(skb_dst(skb)))
goto free_skb;
ip_local_out(skb);
return;
free_skb:
kfree_skb(skb);
}
static void cui_send_synack(struct sk_buff *oldskb, unsigned int hook)
{
struct tcphdr _otcph, *tcph;
const struct tcphdr *oth;
const struct iphdr *oiph;
struct sk_buff *skb;
struct iphdr *iph;
unsigned int addr_type;
oiph = ip_hdr(oldskb);
/* do not deal with fragment */
if (oiph->frag_off & htons(IP_OFFSET))
return;
oth = skb_header_pointer(oldskb, ip_hdrlen(oldskb),
sizeof(_otcph), &_otcph);
if (oth == NULL)
return;
/* syn[ack] only */
if (!oth->syn || oth->ack || oth->rst || oth->fin)
return;
/* check checksum */
if (nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), IPPROTO_TCP))
return;
skb = alloc_skb(sizeof(struct iphdr) + sizeof(struct tcphdr) +
LL_MAX_HEADER, GFP_ATOMIC);
if (skb == NULL)
return;
/* construct from scratch */
skb_reserve(skb, LL_MAX_HEADER);
skb_reset_network_header(skb);
iph = (struct iphdr *)skb_put(skb, sizeof(struct iphdr));
iph->version = 4;
iph->ihl = sizeof(struct iphdr) / 4;
iph->tos = 0;
iph->id = 0;
iph->frag_off = htons(IP_DF);
iph->protocol = IPPROTO_TCP;
iph->check = 0;
iph->saddr = oiph->daddr;
iph->daddr = oiph->saddr;
tcph = (struct tcphdr *)skb_put(skb, sizeof(struct tcphdr));
memset(tcph, 0, sizeof(*tcph));
tcph->source = oth->dest;
tcph->dest = oth->source;
tcph->doff = sizeof(struct tcphdr) / 4;
tcph->window = 0xffffU;
tcph->syn = true;
tcph->ack = true;
tcph->seq = 0;
tcph->ack_seq = oth->seq;
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 20)
tcph->check = tcp_v4_check(tcph, sizeof(struct tcphdr), iph->saddr,
iph->daddr, csum_partial((char *)tcph,
sizeof(struct tcphdr), 0));
#else
tcph->check = tcp_v4_check(sizeof(struct tcphdr), iph->saddr,
iph->daddr, csum_partial((char *)tcph,
sizeof(struct tcphdr), 0));
#endif
addr_type = RTN_UNSPEC;
#ifdef CONFIG_BRIDGE_NETFILTER
if (hook != NF_INET_FORWARD || (skb->nf_bridge != NULL &&
skb->nf_bridge->mask & BRNF_BRIDGED))
#else
if (hook != NF_INET_FORWARD)
#endif
addr_type = RTN_LOCAL;
/* ip_route_me_harder expects skb->dst to be set */
skb_dst_set(skb, dst_clone(skb_dst(oldskb)));
if (ip_route_me_harder(&skb, addr_type))
goto free_skb;
else
iph = ip_hdr(skb);
iph->ttl = dst_metric(skb_dst(skb), RTAX_HOPLIMIT);
skb->ip_summed = CHECKSUM_NONE;
/* "Never happens" */
if (skb->len > dst_mtu(skb_dst(skb)))
goto free_skb;
ip_local_out(skb);
return;
free_skb:
kfree_skb(skb);
}
static unsigned int
cui_tg(struct sk_buff **pskb, const struct xt_action_param *par)
{
/* WARNING: This code causes reentry within iptables.
This means that the iptables jump stack is now crap. We
must return an absolute verdict. --RR */
cui_send_synack(*pskb, par->hooknum);
cui_send_reset(*pskb, par->hooknum);
cui_send_synack(*pskb, par->hooknum);
cui_send_reset(*pskb, par->hooknum);
return NF_ACCEPT;
}
static struct xt_target cui_tg_reg __read_mostly = {
.name = "CUI",
.revision = 0,
.family = NFPROTO_IPV4,
.table = "filter",
.hooks = (1 << NF_INET_LOCAL_IN),
.proto = IPPROTO_TCP,
.target = cui_tg,
.me = THIS_MODULE,
};
static int __init cui_tg_init(void)
{
return xt_register_target(&cui_tg_reg);
}
static void __exit cui_tg_exit(void)
{
xt_unregister_target(&cui_tg_reg);
}
module_init(cui_tg_init);
module_exit(cui_tg_exit);
MODULE_DESCRIPTION("Xtables: Cui Yingying");
MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>");
MODULE_AUTHOR("Klzgrad <klzgrad@gmail.com>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_CUI");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment