[Devel] [PATCH RHEL7 COMMIT] vzprivnet: Filter VM/CT to Host traffic

Konstantin Khorenko khorenko at virtuozzo.com
Thu Mar 24 08:53:38 PDT 2016


The commit is pushed to "branch-rh7-3.10.0-327.10.1.vz7.12.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-327.10.1.vz7.12.3
------>
commit ce8f9e7820366112d9f2339f6e7fffbc899825b9
Author: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
Date:   Thu Mar 24 19:53:38 2016 +0400

    vzprivnet: Filter VM/CT to Host traffic
    
    changes:
    1) vzpn_filter_hos ctl_table do not have ctl_name anymore
    2) make vzprivnet6 hooks correspond to nf_hookfn prototype
    
    Port diff-vz-privnet-filter-host-traffic
      privnet: Filter VM/CT to Host traffic
    
      Currently vzprivnet sits on the forward chain, but the CT-HN
      communications do not use one.
    
      Use the LOCAL_IN/LOCAL_OUT (happens after routing actually, so
      the dst cache optimization works here) chains for catching this
      traffic and check for the venet device being used.
    
      For bridged traffic this will work in one direction - to CT,
      since bridge calls the LOCAL_OUT hooks, but doesn't call the
      LOCAL_IN one.
    
      https://jira.sw.ru/browse/PSBM-6404
    
      Ported from rhel5
    
    Signed-off-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
---
 include/linux/vzprivnet.h          |  3 ++
 net/ipv4/netfilter/ip_vzprivnet.c  | 89 +++++++++++++++++++++++++++++++-------
 net/ipv6/netfilter/ip6_vzprivnet.c | 80 ++++++++++++++++++++++++++++------
 3 files changed, 144 insertions(+), 28 deletions(-)

diff --git a/include/linux/vzprivnet.h b/include/linux/vzprivnet.h
index 1e660e0..f93417c 100644
--- a/include/linux/vzprivnet.h
+++ b/include/linux/vzprivnet.h
@@ -1,6 +1,9 @@
 #ifndef __IP_VZPRIVNET_H__
 #define __IP_VZPRIVNET_H__
 
+extern int vzpn_handle_bridged;
+extern int vzpn_filter_host;
+
 struct proc_dir_entry;
 extern struct proc_dir_entry *vzpriv_proc_dir;
 
diff --git a/net/ipv4/netfilter/ip_vzprivnet.c b/net/ipv4/netfilter/ip_vzprivnet.c
index d96043f..b7035c2 100644
--- a/net/ipv4/netfilter/ip_vzprivnet.c
+++ b/net/ipv4/netfilter/ip_vzprivnet.c
@@ -234,20 +234,20 @@ static noinline unsigned int vzprivnet_classify(struct sk_buff *skb, int type)
 	return res;
 }
 
-static int vzpn_handle_bridged = 0;
+int vzpn_handle_bridged = 0;
+EXPORT_SYMBOL(vzpn_handle_bridged);
 
-static unsigned int vzprivnet_hook(const struct nf_hook_ops *ops,
-				  struct sk_buff *skb,
-				  const struct net_device *in,
-				  const struct net_device *out,
-				  const struct nf_hook_state *state)
+int vzpn_filter_host = 0;
+EXPORT_SYMBOL(vzpn_filter_host);
+
+static unsigned int vzprivnet_hook(struct sk_buff *skb, int can_be_bridge)
 {
 	struct dst_entry *dst;
 	unsigned int pmark = VZPRIV_MARK_UNKNOWN;
 
 	dst = skb_dst(skb);
 	if (dst != NULL) {
-		if (dst->input != ip_forward) { /* bridge */
+		if (can_be_bridge && dst->output != ip_output) { /* bridge */
 			if (!vzpn_handle_bridged)
 				return NF_ACCEPT;
 			else
@@ -266,12 +266,64 @@ static unsigned int vzprivnet_hook(const struct nf_hook_ops *ops,
 	return pmark == VZPRIV_MARK_ACCEPT ? NF_ACCEPT : NF_DROP;
 }
 
-static struct nf_hook_ops vzprivnet_ops = {
-	.hook = vzprivnet_hook,
-	.owner = THIS_MODULE,
-	.pf = PF_INET,
-	.hooknum = NF_INET_FORWARD,
-	.priority = NF_IP_PRI_FIRST
+static unsigned int vzprivnet_fwd_hook(const struct nf_hook_ops *ops,
+		struct sk_buff *skb, const struct net_device *in,
+		const struct net_device *out, const struct nf_hook_state *state)
+{
+	return vzprivnet_hook(skb, 1);
+}
+
+static unsigned int vzprivnet_host_hook(struct sk_buff *skb,
+		const struct net_device *dev, int can_be_bridge)
+{
+	if (!vzpn_filter_host)
+		return NF_ACCEPT;
+
+	/*
+	 * Only packets coming from venet or going to one matter
+	 */
+	if (!(dev->features & NETIF_F_VENET))
+		return NF_ACCEPT;
+
+	return vzprivnet_hook(skb, can_be_bridge);
+}
+
+static unsigned int vzprivnet_in_hook(const struct nf_hook_ops *ops,
+		struct sk_buff *skb, const struct net_device *in,
+		const struct net_device *out, const struct nf_hook_state *state)
+{
+	return vzprivnet_host_hook(skb, in, 0); /* bridge doesn't call it */
+}
+
+static unsigned int vzprivnet_out_hook(const struct nf_hook_ops *ops,
+		struct sk_buff *skb, const struct net_device *in,
+		const struct net_device *out, const struct nf_hook_state *state)
+{
+	return vzprivnet_host_hook(skb, out, 1);
+}
+
+static struct nf_hook_ops vzprivnet_ops[] = {
+	{
+		.hook = vzprivnet_fwd_hook,
+		.owner = THIS_MODULE,
+		.pf = PF_INET,
+		.hooknum = NF_INET_FORWARD,
+		.priority = NF_IP_PRI_FIRST
+	},
+	{
+		.hook = vzprivnet_in_hook,
+		.owner = THIS_MODULE,
+		.pf = PF_INET,
+		.hooknum = NF_INET_LOCAL_IN,
+		.priority = NF_IP_PRI_FIRST
+	},
+	{
+		.hook = vzprivnet_out_hook,
+		.owner = THIS_MODULE,
+		.pf = PF_INET,
+		.hooknum = NF_INET_LOCAL_OUT,
+		.priority = NF_IP_PRI_FIRST
+	},
 };
 
 static inline u32 to_netmask(int prefix)
@@ -1030,6 +1082,13 @@ static struct ctl_table vzprivnet_table[] = {
 		.mode = 0600,
 		.proc_handler = proc_dointvec,
 	},
+	{
+		.procname = "vzpriv_filter_host",
+		.data = &vzpn_filter_host,
+		.maxlen = sizeof(vzpn_filter_host),
+		.mode = 0600,
+		.proc_handler = proc_dointvec,
+	},
 	{ },
 };
 
@@ -1073,7 +1132,7 @@ static int __init iptable_vzprivnet_init(void)
 	if (ctl == NULL)
 		goto err_ctl;
 
-	err = nf_register_hook(&vzprivnet_ops);
+	err = nf_register_hooks(vzprivnet_ops, 3);
 	if (err)
 		goto err_reg;
 
@@ -1099,7 +1158,7 @@ err_mkdir:
 
 static void __exit iptable_vzprivnet_exit(void)
 {
-	nf_unregister_hook(&vzprivnet_ops);
+	nf_unregister_hooks(vzprivnet_ops, 3);
 	unregister_sysctl_table(ctl);
 	remove_proc_entry(VZPRIV_PROCNAME, init_net.proc_net);
 	remove_proc_entry("classify", vzpriv_proc_dir);
diff --git a/net/ipv6/netfilter/ip6_vzprivnet.c b/net/ipv6/netfilter/ip6_vzprivnet.c
index 3586c72..f87509f 100644
--- a/net/ipv6/netfilter/ip6_vzprivnet.c
+++ b/net/ipv6/netfilter/ip6_vzprivnet.c
@@ -301,16 +301,16 @@ static int sparse6_del(unsigned netid, u32 *ip, int weak)
 	return err;
 }
 
-static unsigned int vzprivnet6_hook(const struct nf_hook_ops *ops,
-				  struct sk_buff *skb,
-				  const struct net_device *in,
-				  const struct net_device *out,
-				  const struct nf_hook_state *state)
+static unsigned int vzprivnet6_hook(struct sk_buff *skb, int can_be_bridge)
 {
 	int verdict = NF_DROP;
 	struct vzprivnet *dst, *src;
 	struct ipv6hdr *hdr;
 
+	if (can_be_bridge && !vzpn_handle_bridged &&
+			skb_dst(skb) != NULL && skb_dst(skb)->output != ip6_output)
+		return NF_ACCEPT;
+
 	read_lock(&vzpriv6lock);
 
 	hdr = ipv6_hdr(skb);
@@ -327,12 +327,66 @@ static unsigned int vzprivnet6_hook(const struct nf_hook_ops *ops,
 	return verdict;
 }
 
-static struct nf_hook_ops vzprivnet6_ops = {
-	.hook = vzprivnet6_hook,
-	.owner = THIS_MODULE,
-	.pf = PF_INET6,
-	.hooknum = NF_INET_FORWARD,
-	.priority = NF_IP6_PRI_FIRST
+static unsigned int vzprivnet6_fwd_hook(const struct nf_hook_ops *ops,
+				  struct sk_buff *skb,
+				  const struct net_device *in,
+				  const struct net_device *out,
+				  const struct nf_hook_state *state)
+{
+	return vzprivnet6_hook(skb, 1);
+}
+
+static unsigned int vzprivnet6_host_hook(struct sk_buff *skb,
+		const struct net_device *dev, int can_be_bridge)
+{
+	if (!vzpn_filter_host)
+		return NF_ACCEPT;
+	if (!(dev->features & NETIF_F_VENET))
+		return NF_ACCEPT;
+
+	return vzprivnet6_hook(skb, can_be_bridge);
+}
+
+static unsigned int vzprivnet6_in_hook(const struct nf_hook_ops *ops,
+				  struct sk_buff *skb,
+				  const struct net_device *in,
+				  const struct net_device *out,
+				  const struct nf_hook_state *state)
+{
+	return vzprivnet6_host_hook(skb, in, 0);
+}
+
+static unsigned int vzprivnet6_out_hook(const struct nf_hook_ops *ops,
+				  struct sk_buff *skb,
+				  const struct net_device *in,
+				  const struct net_device *out,
+				  const struct nf_hook_state *state)
+{
+	return vzprivnet6_host_hook(skb, out, 1);
+}
+
+static struct nf_hook_ops vzprivnet6_ops[] = {
+	{
+		.hook = vzprivnet6_fwd_hook,
+		.owner = THIS_MODULE,
+		.pf = PF_INET6,
+		.hooknum = NF_INET_FORWARD,
+		.priority = NF_IP6_PRI_FIRST
+	},
+	{
+		.hook = vzprivnet6_in_hook,
+		.owner = THIS_MODULE,
+		.pf = PF_INET6,
+		.hooknum = NF_INET_LOCAL_IN,
+		.priority = NF_IP6_PRI_FIRST
+	},
+	{
+		.hook = vzprivnet6_out_hook,
+		.owner = THIS_MODULE,
+		.pf = PF_INET6,
+		.hooknum = NF_INET_LOCAL_OUT,
+		.priority = NF_IP6_PRI_FIRST
+	},
 };
 
 static char *nextline(char *s)
@@ -634,7 +688,7 @@ static int __init ip6_vzprivnet_init(void)
 	if (proc == NULL)
 		goto err_classify6;
 
-	err = nf_register_hook(&vzprivnet6_ops);
+	err = nf_register_hooks(vzprivnet6_ops, 3);
 	if (err)
 		goto err_reg;
 
@@ -652,7 +706,7 @@ err_sparse6:
 static void __exit ip6_vzprivnet_exit(void)
 {
 	vzprivnet_unreg_show(vzprivnet6_show_stat);
-	nf_unregister_hook(&vzprivnet6_ops);
+	nf_unregister_hooks(vzprivnet6_ops, 3);
 	remove_proc_entry("classify6", vzpriv_proc_dir);
 	remove_proc_entry("sparse6", vzpriv_proc_dir);
 	vzprivnet6_cleanup();


More information about the Devel mailing list