init: 以 ipv4 為例,初始化程式放置在 ~/net/ipv4/netfilter/nf_nat_rule.c
int __init nf_nat_rule_init(void)
ret = xt_register_target(&ipt_snat_reg); 註冊 snat 的 target
ret = xt_register_target(&ipt_dnat_reg); 註冊 dnat 的 target
int __init nf_nat_rule_init(void)
ret = xt_register_target(&ipt_snat_reg); 註冊 snat 的 target
ret = xt_register_target(&ipt_dnat_reg); 註冊 dnat 的 target
static struct xt_target ipt_snat_reg __read_mostly = {
.name= "SNAT",
.target= ipt_snat_target,
.targetsize= sizeof(struct nf_nat_multi_range_compat),
.table= "nat", table: nat,iptables 裡面用 -t nat 來使用
.hooks= (1 << NF_INET_POST_ROUTING) | (1 << NF_INET_LOCAL_IN), 只用到兩個 hook
.checkentry= ipt_snat_checkentry, 指定規則檢查函數,同樣實做在 nf_nat_rule.c
.family= AF_INET,
} dnat 只有 .hooks 跟 .checkentry 不同
.name= "SNAT",
.target= ipt_snat_target,
.targetsize= sizeof(struct nf_nat_multi_range_compat),
.table= "nat", table: nat,iptables 裡面用 -t nat 來使用
.hooks= (1 << NF_INET_POST_ROUTING) | (1 << NF_INET_LOCAL_IN), 只用到兩個 hook
.checkentry= ipt_snat_checkentry, 指定規則檢查函數,同樣實做在 nf_nat_rule.c
.family= AF_INET,
} dnat 只有 .hooks 跟 .checkentry 不同
ipt_snat_target() {
ct = nf_ct_get(skb, &ctinfo); 取得 conntrack 訊息
/* Connection must be valid and new. */ 作驗證
return nf_nat_setup_info(ct, &mr->range[0], IP_NAT_MANIP_SRC);
}
ct = nf_ct_get(skb, &ctinfo); 取得 conntrack 訊息
/* Connection must be valid and new. */ 作驗證
return nf_nat_setup_info(ct, &mr->range[0], IP_NAT_MANIP_SRC);
}
nf_nat_setup_info() { 實做在 ~/net/ipv4/netfilter/nf_nat_core.c
struct nf_conntrack_tuple ...; 定義在 ~/include/net/netfilter/nf_conntrack_tuple.h,用來作連線識別
nat = nfct_nat(ct); 從 conntrack 取出 nat 資訊
if (!nat) { 如果沒有,就新增一個
nat = nf_ct_ext_add(ct, NF_CT_EXT_NAT, GFP_ATOMIC);
}
nf_ct_invert_tuplepr(&curr_tuple, ...) 根據 reply 逆推當前的 tuple
get_unique_tuple(&new_tuple, ...) 獲取作過 snat 之後的 tuple
if (!nf_ct_tuple_equal(&new_tuple, &curr_tuple)) {
兩者不相等表示 tuple 發生變化了,要更新 conntrack 裡面 reply 的 tuple
}
if (maniptype == IP_NAT_MANIP_SRC) {
第一次作 NAT 必須將 ORIGINAL 的 tuple 加入 hash 列表
}
/* It's done. */ 打上 NAT 完成標記
}
struct nf_conntrack_tuple ...; 定義在 ~/include/net/netfilter/nf_conntrack_tuple.h,用來作連線識別
nat = nfct_nat(ct); 從 conntrack 取出 nat 資訊
if (!nat) { 如果沒有,就新增一個
nat = nf_ct_ext_add(ct, NF_CT_EXT_NAT, GFP_ATOMIC);
}
nf_ct_invert_tuplepr(&curr_tuple, ...) 根據 reply 逆推當前的 tuple
get_unique_tuple(&new_tuple, ...) 獲取作過 snat 之後的 tuple
if (!nf_ct_tuple_equal(&new_tuple, &curr_tuple)) {
兩者不相等表示 tuple 發生變化了,要更新 conntrack 裡面 reply 的 tuple
}
if (maniptype == IP_NAT_MANIP_SRC) {
第一次作 NAT 必須將 ORIGINAL 的 tuple 加入 hash 列表
}
/* It's done. */ 打上 NAT 完成標記
}
沒有留言:
張貼留言