Linuxで状態検出はどうやって行いますか?
本文書のCopylityはyfydzの所有に帰属します.GPLを使って発表します.自由にコピー、転載できます.転載する時は文書の完全性を維持してください.商業用途に使用することは厳禁です.
msn:[email protected]
ソース:http://yfydz.cublog.cn
msn:[email protected]
ソース:http://yfydz.cublog.cn
1. iptables state
2.4/2.6 Linux netfilter (stateful inspection) , iptables “-m state” ,“-m state” :
NEW, ;
ESTABLISHED, ;
RELATED, ;
INVALID, 。
iptables , , , :
iptables -I FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -I FORWARD -m state --state INVALID -j DROP
( , FORWARD INPUT)
2. state
( 2.4.26 )
state ipt_state.c(net/ipv4/netfilter), , ip_conntrack_get() :
if (!ip_conntrack_get((struct sk_buff *)skb, &ctinfo))
statebit = IPT_STATE_INVALID;
else
statebit = IPT_STATE_BIT(ctinfo);
3. skb ip_conntrack
ip_conntrack_get() (net/ipv4/netfilter_ipv4 /ip_conntrack_core.c), , sk_buff skb, enum ip_conntrack_info , , ; struct ip_conntrack , , , , :
struct ip_conntrack *
ip_conntrack_get(struct sk_buff *skb, enum ip_conntrack_info *ctinfo)
{
if (skb->nfct)
return __ip_conntrack_get(skb->nfct, ctinfo);
return NULL;
}
ip_conntrack_get() , __ip_conntrack_get() (net/ipv4 /netfilter_ipv4/ip_conntrack_core.c) , skb nfct , ctinfo __ip_conntrack_get() ,nfct sk_buff netfilter conntrack struct nf_ct_info , CONFIG_NETFILTER 。struct nf_ct_info include/linux/sk_buff.h :
struct nf_conntrack {
atomic_t use;
void (*destroy)(struct nf_conntrack *);
};
struct nf_ct_info {
struct nf_conntrack *master;
};
__ip_conntrack_get() , nfct->master ct, nfct ct infos :
static inline struct ip_conntrack *
__ip_conntrack_get(struct nf_ct_info *nfct, enum ip_conntrack_info *ctinfo)
{
struct ip_conntrack *ct
= (struct ip_conntrack *)nfct->master;
/* ctinfo is the index of the nfct inside the conntrack */
*ctinfo = nfct - ct->infos;
IP_NF_ASSERT(*ctinfo >= 0 && *ctinfo < IP_CT_NUMBER);
return ct;
}
,netfilter , skb nfct , skb , 。 skb nfct ?
4. netfilter skb ip_conntrack
nfct resolve_normal_ct() (net/ipv4/netfilter/ip_conntrack_core.c) ,
ip_conntrack_in() (net/ipv4/netfilter/ip_conntrack_core.c) , ip_conntrack_local() (net/ipv4/netfilter/ip_conntrack_standalone.c)
ip_conntrack_in() , PREROUTING OUTPUT ,
(net/ipv4/netfilter/ip_conntrack_standalone.c):
static struct nf_hook_ops ip_conntrack_in_ops
= { { NULL, NULL }, ip_conntrack_in, PF_INET, NF_IP_PRE_ROUTING,
NF_IP_PRI_CONNTRACK };
static struct nf_hook_ops ip_conntrack_local_out_ops
= { { NULL, NULL }, ip_conntrack_local, PF_INET, NF_IP_LOCAL_OUT,
NF_IP_PRI_CONNTRACK };
netfilter , , , HASH , skb nfct, resolve_normal_ct() :
/* On success, returns conntrack ptr, sets skb->nfct and ctinfo */
static inline struct ip_conntrack *
resolve_normal_ct(struct sk_buff *skb, //
struct ip_conntrack_protocol *proto, // , , TCP
int *set_reply, // ,
unsigned int hooknum,
enum ip_conntrack_info *ctinfo)
{
struct ip_conntrack_tuple tuple;
struct ip_conntrack_tuple_hash *h;
IP_NF_ASSERT((skb->nh.iph->frag_off & htons(IP_OFFSET)) == 0);
// tuple, TCP/UDP 5
if (!get_tuple(skb->nh.iph, skb->len, &tuple, proto))
return NULL;
/* look for tuple match */
// tuple HASH
h = ip_conntrack_find_get(&tuple, NULL);
if (!h) {
// , ,
h = init_conntrack(&tuple, proto, skb);
if (!h)
return NULL;
// NULL,
if (IS_ERR(h))
return (void *)h;
}
/* It exists; we have (non-exclusive) reference. */
if (DIRECTION(h) == IP_CT_DIR_REPLY) {
//
*ctinfo = IP_CT_ESTABLISHED + IP_CT_IS_REPLY;
/* Please set reply bit if this packet OK */
//
*set_reply = 1;
} else {
//
/* Once we've had two way comms, always ESTABLISHED. */
if (test_bit(IPS_SEEN_REPLY_BIT, &h->ctrack->status)) {
DEBUGP("ip_conntrack_in: normal packet for %p
",
h->ctrack);
// , ESTABLISHED , ,
// , ip_conntrack_in()
*ctinfo = IP_CT_ESTABLISHED;
} else if (test_bit(IPS_EXPECTED_BIT, &h->ctrack->status)) {
DEBUGP("ip_conntrack_in: related packet for %p
",
h->ctrack);
// , FTP
// init_conntrack()
*ctinfo = IP_CT_RELATED;
} else {
DEBUGP("ip_conntrack_in: new packet for %p
",
h->ctrack);
// , , NEW
*ctinfo = IP_CT_NEW;
}
//
*set_reply = 0;
}
// infos IP_CT_NUMBER(=5) ,
// NEW(2)/ESTABLISHED(0)/RELATED(1)
// ESTABLISHED(3)/RELATED(4)
// skb , ctinfo
// skb , nfct infos
skb->nfct = &h->ctrack->infos[*ctinfo];
return h->ctrack;
}
init_conntrack() infos :
...
for (i=0; i < IP_CT_NUMBER; i++)
conntrack->infos[i].master = &conntrack->ct_general;
...
infos , , , 。 , , infos[0] ,infos , infos[0] 。
__ip_conntrack_get() nfct->master :
__ip_conntrack_get(struct nf_ct_info *nfct, enum ip_conntrack_info *ctinfo)
{
struct ip_conntrack *ct
= (struct ip_conntrack *)nfct->master;
...
skb nfct infos , master ct_general , ct_general , , Linux , 。
5.
skb netfilter ,netfilter , , 、 , , 。
infos , , , infos 。