linux的SNAT和DNAT目標函數

來源:互聯網
上載者:User

SNAT、DNAT目標函數

前面在ip_nat_fn()函數中調用的ip_nat_rule_find()用來尋找NAT規則,執行規則的動作,規則目標不是SNAT就是DNAT,該目標的具體實現在net/ipv4/netfilter/ip_nat_rule.c中。

不論是SNAT還是DNAT規則,其目標函數最終都是調用ip_nat_setup_info()函數來建立串連的NAT info資訊。

net/ipv4/netfilter/ip_nat_rule.c:

/* Source NAT */

static unsigned int ipt_snat_target(struct sk_buff **pskb,

unsigned int hooknum,

const struct net_device *in,

const struct net_device *out,

const void *targinfo,

void *userinfo)

{

struct ip_conntrack *ct;

enum ip_conntrack_info ctinfo;

IP_NF_ASSERT(hooknum == NF_IP_POST_ROUTING);

ct = ip_conntrack_get(*pskb, &ctinfo);

/* Connection must be valid and new. */

IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED));

IP_NF_ASSERT(out);

// 只有新串連才進行NAT info的建立

// targinfo實際是struct ip_nat_multi_range結構指標,記錄轉換後的

// 地址、連接埠等資訊, 一個NAT規則可以轉換到可以轉換到多個地址連接埠上

return ip_nat_setup_info(ct, targinfo, hooknum);

}

static unsigned int ipt_dnat_target(struct sk_buff **pskb,

unsigned int hooknum,

const struct net_device *in,

const struct net_device *out,

const void *targinfo,

void *userinfo)

{

struct ip_conntrack *ct;

enum ip_conntrack_info ctinfo;

#ifdef CONFIG_IP_NF_NAT_LOCAL

IP_NF_ASSERT(hooknum == NF_IP_PRE_ROUTING

|| hooknum == NF_IP_LOCAL_OUT);

#else

IP_NF_ASSERT(hooknum == NF_IP_PRE_ROUTING);

#endif

ct = ip_conntrack_get(*pskb, &ctinfo);

/* Connection must be valid and new. */

IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED));

// 只有新串連才進行NAT info的建立

// targinfo實際是struct ip_nat_multi_range結構指標,記錄轉換後的

// 地址、連接埠等資訊, 一個NAT規則可以轉換到可以轉換到多個地址連接埠上

return ip_nat_setup_info(ct, targinfo, hooknum);

}

......

int ip_nat_rule_find(struct sk_buff **pskb,

unsigned int hooknum,

const struct net_device *in,

const struct net_device *out,

struct ip_conntrack *ct,

struct ip_nat_info *info)

{

int ret;

ret = ipt_do_table(pskb, hooknum, in, out, &nat_table, NULL);

if (ret == NF_ACCEPT) {

// 資料接受但有沒有初始化,分配一個NULL binding,實際不作任何修改,也就是

// 說對該包沒有相應的NAT規則對於,不需要進行NAT處理

if (!(info->initialized & (1 nat.info;

// 如果info->initialized不為0,表示已經初始化過了

int in_hashes = info->initialized;

MUST_BE_WRITE_LOCKED(&ip_nat_lock);

IP_NF_ASSERT(hooknum == NF_IP_PRE_ROUTING

|| hooknum == NF_IP_POST_ROUTING

|| hooknum == NF_IP_LOCAL_OUT);

IP_NF_ASSERT(info->num_manips initialized & (1 tuplehash[IP_CT_DIR_ORIGINAL].tuple) */

// 根據串連的回應方向的tuple進行反轉得到原始方向的tuple

invert_tuplepr(&orig_tp,

&conntrack->tuplehash[IP_CT_DIR_REPLY].tuple);

#if 0

{

unsigned int i;

DEBUGP("Hook %u (%s), ", hooknum,

HOOK2MANIP(hooknum)==IP_NAT_MANIP_SRC ? "SRC" : "DST");

DUMP_TUPLE(&orig_tp);

DEBUGP("Range %p: ", mr);

for (i = 0; i rangesize; i++) {

DEBUGP("%u:%s%s%s %u.%u.%u.%u - %u.%u.%u.%u %u - %u\n",

i,

(mr->range.flags & IP_NAT_RANGE_MAP_IPS)

? " MAP_IPS" : "",

(mr->range.flags

& IP_NAT_RANGE_PROTO_SPECIFIED)

? " PROTO_SPECIFIED" : "",

(mr->range.flags & IP_NAT_RANGE_FULL)

? " FULL" : "",

NIPQUAD(mr->range.min_ip),

NIPQUAD(mr->range.max_ip),

mr->range.min.all,

mr->range.max.all);

}

}

#endif

do {

// 找一個未使用的進行了轉換後的tuple結構參數,mr是NAT規則確定的要轉換後的

// 地址連接埠參數, new_tuple保持轉換後的串連原始方向的tuple

if (!get_unique_tuple(&new_tuple, &orig_tp, mr, conntrack,

hooknum)) {

DEBUGP("ip_nat_setup_info: Can't get unique for %p.\n",

conntrack);

return NF_DROP;

}

#if 0

DEBUGP("Hook %u (%s) %p\n", hooknum,

HOOK2MANIP(hooknum)==IP_NAT_MANIP_SRC ? "SRC" : "DST",

conntrack);

DEBUGP("Original: ");

DUMP_TUPLE(&orig_tp);

DEBUGP("New: ");

DUMP_TUPLE(&new_tuple);

#endif

/* We now have two tuples (SRCIP/SRCPT/DSTIP/DSTPT):

本文URL地址:http://www.bianceng.cn/OS/Linux/201410/45494.htm

the original (A/B/C/D') and the mangled one (E/F/G/H').

We're only allowed to work with the SRC per-proto

part, so we create inverses of both to start, then

derive the other fields we need. */

/* Reply connection: simply invert the new tuple

(G/H/E/F') */

// 建立串連地址轉換後的反向的tuple,這使netfilter能自動對串連的反方向資料

// 進行處理,也就是說定義了一條SNAT規則後,並不需要再定義一條DNAT規則來處理

// 返回的資料,netfilter已經自動處理了

invert_tuplepr(&reply, &new_tuple);

/* Alter conntrack table so it recognizes replies.

If fail this race (reply tuple now used), repeat. */

// 修改串連參數使能正確識別返回資料,如果reply已經對應一條串連

// ip_conntrack_alter_reply()函數返回0,表示要繼續修改轉換後的參數值

} while (!ip_conntrack_alter_reply(conntrack, &reply));

/* FIXME: We can simply used existing conntrack reply tuple

here --RR */

/* Create inverse of original: C/D/A/B' */

invert_tuplepr(&inv_tuple, &orig_tp);

/* Has source changed?. */

// 源NAT

if (!ip_ct_tuple_src_equal(&new_tuple, &orig_tp)) {

/* In this direction, a source manip. */

// 串連正方向是SNAT

info->manips[info->num_manips++] =

((struct ip_nat_info_manip)

{ IP_CT_DIR_ORIGINAL, hooknum,

IP_NAT_MANIP_SRC, new_tuple.src });

IP_NF_ASSERT(info->num_manips manips[info->num_manips++] =

((struct ip_nat_info_manip)

{ IP_CT_DIR_REPLY, opposite_hook[hooknum],

IP_NAT_MANIP_DST, orig_tp.src });

IP_NF_ASSERT(info->num_manips manips[info->num_manips++] =

((struct ip_nat_info_manip)

{ IP_CT_DIR_ORIGINAL, hooknum,

IP_NAT_MANIP_DST, reply.src });

IP_NF_ASSERT(info->num_manips manips[info->num_manips++] =

((struct ip_nat_info_manip)

{ IP_CT_DIR_REPLY, opposite_hook[hooknum],

IP_NAT_MANIP_SRC, inv_tuple.src });

IP_NF_ASSERT(info->num_manips master)

info->helper = LIST_FIND(&helpers, helper_cmp, struct ip_nat_helper *,

&reply);

/* It's done. */

// 完成該方向的NAT info初始化

info->initialized |= (1 bysource.conntrack);

replace_in_hashes(conntrack, info);

} else {

place_in_hashes(conntrack, info);

}

return NF_ACCEPT;

}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.