Compile a Linux virtual network card to implement NVI-like

Source: Internet
Author: User

In Linux, we can use the loopback interface to simulate ROUTING decisions in two stages. The first stage is to go through the PRE/post routing process to complete NAT implementation, the second stage completes pure route forwarding. However, you need to hook the child on Netfilter to cancel the route entry associated with skb and cancel the conntrack information associated with skb, because in the pure routing process in the second stage, I don't want any more conntrack-based actions. Therefore, if you need a conntrack-based operation, you must complete it in the first phase together with NAT.
Looking back, the implementation of loopback is not so perfect, because things like mounting a hook on Netfilter can be completed in the xmit operation of the virtual network card, so it is necessary to re-write a virtual network card, the reason for re-writing is that this module is super simple and can basically copy the loopback. the implementation of c is different from the operation of xmit:

Static netdev_tx_t implements _xmit (struct sk_buff * skb, struct net_device * dev) {int len; // note that I wrote the original packet entry interface in the mark of skb, why? Because... struct net_device * real_dev = dev_get_by_index (dev_net (dev), skb-> mark); skb_orphan (skb); skb-> protocol = eth_type_trans (skb, real_dev ); // cancel the associated route entry so that you can re-policy routing skb_dst_drop (skb) When ip_input; // cancel the conntrack, because its task has completed skb-> nfct = & nf_conntrack_untracked.ct_general; skb-> nfctinfo = IP_CT_NEW; nf_conntrack_get (skb-> nfct); len = skb-> len; if (likely (netif_rx (skb) = NET_RX_SUCCESS) ) {... // What should I do? Statistics? } Else {.../...} return NETDEV_TX_ OK ;}

Registering NVI interfaces is also very simple:
dev = alloc_netdev(0, "nvi", nvi_setup);
Why can I use the skb mark to save the index of the Input Interface? In fact, on a 32-bit machine, it can store the dev address of the original Nic and convert it to a net_device pointer. I didn't directly store the index of the ENI in the mark at the beginning, because the Netfilter hook may also use this mark, I didn't use the mark mask to hide some bits to store the index, because non-users may misuse it. The method I used was to "overwrite the mark into the index of the NIC when I confirmed that there could not be a Netfilter hook. When will it be appropriate? Anyone familiar with Netfilter knows that it is appropriate to do this at the end of POSTROUTING, so I will place this HOOK after the nf_confirm of POSTROUTING. Whether or not there will be traffic control using mark. After all, traffic control is done on the physical Nic and has nothing to do with the first round of routing. However, the problem is, when POSTROUTING is reached, can I still retrieve the index of the original Nic? Oh, NO! :
Int ip_output (struct sk_buff * skb) {struct net_device * dev = skb_dst (skb)-> dev; IP_UPD_PO_STATS (dev_net (dev), IPSTATS_MIB_OUT, skb-> len ); // here, POSTROUTING replaces dev of skb... skb-> dev = dev; skb-> protocol = htons (ETH_P_IP); return NF_HOOK_COND (PF_INET, NF_INET_POST_ROUTING, skb, NULL, dev, ip_finish_output ,! (IPCB (skb)-> flags & IPSKB_REROUTED ));}
Therefore, when POSTROUTING is reached, the index of the original NIC will no longer be obtained! The work und is to change the code of the Linux protocol stack:
Int ip_output (struct sk_buff * skb) {struct net_device * orig_dev struct net_device * dev = skb_dst (skb)-> dev; IP_UPD_PO_STATS (dev_net (dev), IPSTATS_MIB_OUT, skb-> len); // Save the dev of the original ENI (the forward package is used anyway ...) orig_dev = skb-> dev = dev; skb-> protocol = htons (ETH_P_IP ); // input indev if (orig_dev & orig_dev-> flags & IFF_LOOPBACK) {orig_dev = NULL;} return NF_HOOK_COND (PF_INET, NF_INET_POST_ROUT ING, skb, orig_dev, dev, ip_finish_output ,! (IPCB (skb)-> flags & IPSKB_REROUTED ));}
I personally think that for users who use Linux as the routing BOX, for FORWARDING packets, the packets can be retrieved from which Nic the packets enter during POSTROUTING, is it better to implement more control policies? Well, if you have to say that the change is not good, I still have a more standard practice, that is, registering a new extend in the conntrack struct is actually a struct, put the original Eni as a field. In the xmit of the nvi interface, before the conntrack is reset to nf_conntrack_untracked, retrieve the NIC and call the eth_type_trans interface, I didn't touch the main protocol stack of Linux kernel, but I still made expansion based on Netfilter! In fact, the scalability of Netfilter is unlimited!

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.