Implement a virtual network card that does two-way NAT

Source: Internet
Author: User

The description and solution of the problem is still an old problem. Nat configured with Iptables in a Linux system cannot be used in a two-way communication environment, and you cannot configure a NAT rule to do NAT for traffic that is actively initiated in two directions, there are several scenarios for solving the problem:
1. Configure two NAT rules the NAT configuration of the iptables itself is to match and then run a target, so a rule can only represent a conversion strategy, in order to implement "from the source address of the packet from X to Y, go to Y packet destination address to X" This logic, You must use two rules. So why not use two rules? Because the NAT configuration of Iptables is based on data flow, it only makes a rule lookup for the packet that creates the Ip_conntrack struct. So when a stream has been created and the data is being transferred. Adding a NAT configuration is not valid.
There is a rawnat in xtables-addons that is no longer based on Ip_conntrack, that is, it is a NAT based on a packet rather than a data stream. The immediate effect has been overcome, but since it is still a match-target rule, there are two rules to be configured to implement bidirectional Nat.
2. Writing a netfilter hook to write a netfilter hook module is not difficult, I wrote several myself, however, the NetFilter framework is to intercept packets on the processing path of the protocol stack for check-match/action. It checks each protocol stack for packets, which means that each packet is filtered by the hook function. In the NetFilter hook too much time, greatly reduced the efficiency.
3. Use of dedicated virtual appliances This is a new concept. Implement a virtual NIC, whose XMit function is this:
Static netdev_tx_t sdnat_net_xmit (struct sk_buff *skb, struct net_device *dev) {    struct sdnat_struct *sdnat = netdev_p Riv (dev);    unsigned int flags = sdnat->flags;    struct Nat_entry *entry;    Entry = Find_sdnat_policy (SKB, flags);    if (unlikely (!entry)) {        goto xmit;    }    if (Flags & SNAT) {        do_trans_src (entry, SKB);    } else if (Flags & DNAT) {        do_trans_dst (entry, SKB); 
   }    //At this time the SKB DST is to import the packet into the NAT device Dst_entry,    //In order to prevent circular routing, its drop,nat is complete. It's no longer practical.    Skb_dst_drop (SKB);    Clear Mark, because the packet is generally imported via the mark policy route to the NAT device    //This is also to prevent circular routing    Skb->mark = 0;xmit:    netif_rx_ni (SKB);d ROP:    KFREE_SKB (SKB);    return NETDEV_TX_OK;}

DO_TRANS_SRC/DST is fully capable of being implemented by a function, which is to make the interface clearer. Detailed conversion is not much to say, very easy, change the IP header source address or destination address, and then once again calculate L3,L4 check code.
The key is how to organize the NAT rules.

I use a nat_entry to save every rule:

struct Nat_entry {    struct hlist_node hash_list;    __be32 Key1;  For Snat that is the original IP address. For Dnat that is to be converted to the IP address    __be32 key2;  For Snat that is to be converted to the IP address, for Dnat that is the original IP address    __be32 hash;  /packet source IP or destination IP jhash_2words value    int flags;};

The calculation of the hash is as follows:
Static u32 Keys_get_hash (__be32 key) {    return jhash_2words (Key, 0x01, 0x0);}

When the module is loaded, two virtual network cards are created. One responsible for Snat. A responsible Dnat, the same time the system will also have two sdnat_struct structure, one responsible for SNAT, one responsible for Dnat:
struct SDNAT_STRUCT {    int flags;    struct Net_device   *dev;    struct Hlist_head entrys[1024];};

To configure on Linux is two policy routes:
A. From the intranet port into outgoing packets imported to the SNAT network card device for Sant;
B. The packet imported from the external network port into the intranet port is introduced into the DNAT network card device for Dnat.
In this way, you can change your own initiative in both directions. Regardless of which data was first initiated. The "Source address of the packet from X is translated to Y, and the destination address of the packet to Y is converted to X". Is it somewhat similar to the Cisco static NAT? Define the access device instead of the match to filter the packets by iptables.

I prefer to use PROCFS as a user interface because it is convenient for shell operations:
echo +192.168.1.1 9.24.100.1 >/proc/net/nat
Once the above command is run, a nat_entry,key1 of 192.168 will be added to the hash table shared by the two network cards. 1.1. Key2 is 9.24.100.1. In the Snat network card device, will use SKB iph->saddr do hash after the table to match its key1, take out Key2 as the IP address to convert, in the Dnat network card device, will be SKB iph->daddr do hash after check table matching Key2, Remove the Key1 as the IP address you want to convert to.

False assumption to delete a rule, then run:
echo-192.168.1.1 9.24.100.1 >/proc/net/nat
Policy Routing rules such as the following:
IP rule Add IIF $ intranet Port table Snat
IP rule add IIF $ external Port table Dnat
IP route add 0.0.0.0/0 dev snat0 table snat< Br>ip route add 0.0.0.0/0 dev dnat0 table Dnat
is it more efficient to rely on routing to make a NAT inference? It is no longer necessary to match each packet with the NetFilter module. There is no need to toss out inefficient ip_conntrack. It's worth noting that the XMit function of the Sdnat device finally runs a netif_rx_ni which is equivalent to injecting the packet into itself again, when the IIF of the packet is no longer an intranet or an external network port, but a real sdant virtual network card device, As a result, the packet arrives at the routing module again and will not enter the Sdnat device again. The idea and meaning of the
is beyond the netfilter framework, we can also use the Linux NIC device model to build a packet filtering system. Yes. The idea is shown above.

I've written a couple of times about saving information in a route item. Then by Anza the technique of obtaining information by way of a table. The Custom "routing table" is used. Query mode is still the longest prefix matching method, only the things stored in the route item have changed. In this article, I give the idea of using Linux native routing table (not custom) + custom virtual network card device to implement packet filtering, according to this idea, each target of Iptables is a virtual network card device, each series of matches is a route. The route entry for this route is to import the packet into the appropriate virtual network card device, and routing to match the packet will be more efficient than netfilter, since it uses an efficient data structure such as Hash/trie. Instead of traversing several layers of linked lists like NetFilter.
In fact, is this thought very new? No!

Does the route entry have unreachable or blackhole? Aren't they just iptables reject and drop?

Implement a virtual network card that does two-way NAT

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

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.