[lxc-devel] [PATCH] Add lxc-net tool

Christian Seiler christian at iwakd.de
Thu May 17 16:26:41 UTC 2012


Add a tool that switches context to enter the network namespace and then
execute an arbitrary command. Since we don't change mount / pid namespaces,
this allows the user to use the host's networking tools such as iputils,
iptables, netstat to query / configure the container from the outside. This
may be especially useful for administrators who have dropped network
configuration capabilities inside the container as a security measure.

Since network namespace switching via setns() was introduced in kernel 3.0,
this tool will work with any newer vanilla kernel version.
---
 configure.ac        |    1 +
 doc/Makefile.am     |    1 +
 doc/lxc-net.sgml.in |  131 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/lxc/Makefile.am |    4 +-
 src/lxc/attach.c    |   22 +++++++++
 src/lxc/attach.h    |    1 +
 src/lxc/lxc_net.c   |   92 ++++++++++++++++++++++++++++++++++++
 7 files changed, 251 insertions(+), 1 deletions(-)
 create mode 100644 doc/lxc-net.sgml.in
 create mode 100644 src/lxc/lxc_net.c

diff --git a/configure.ac b/configure.ac
index 0c8aa69..8605102 100644
--- a/configure.ac
+++ b/configure.ac
@@ -120,6 +120,7 @@ AC_CONFIG_FILES([
 	doc/lxc-cgroup.sgml
 	doc/lxc-kill.sgml
 	doc/lxc-attach.sgml
+	doc/lxc-net.sgml
 	doc/lxc.conf.sgml
 	doc/lxc.sgml
 	doc/common_options.sgml
diff --git a/doc/Makefile.am b/doc/Makefile.am
index b18c5eb..fd1a58b 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -24,6 +24,7 @@ man_MANS = \
 	lxc-cgroup.1 \
 	lxc-kill.1 \
 	lxc-attach.1 \
+	lxc-net.1 \
 	\
 	lxc.conf.5 \
 	\
diff --git a/doc/lxc-net.sgml.in b/doc/lxc-net.sgml.in
new file mode 100644
index 0000000..b675b4f
--- /dev/null
+++ b/doc/lxc-net.sgml.in
@@ -0,0 +1,131 @@
+<!--
+
+lxc: linux Container library
+
+(C) Copyright IBM Corp. 2007, 2008
+
+Authors:
+Daniel Lezcano <dlezcano at fr.ibm.com>
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+-->
+
+<!DOCTYPE refentry PUBLIC "-//Davenport//DTD DocBook V3.0//EN" [
+
+<!ENTITY commonoptions SYSTEM "@builddir@/common_options.sgml">
+<!ENTITY seealso SYSTEM "@builddir@/see_also.sgml">
+]>
+
+<refentry>
+
+  <docinfo><date>@LXC_GENERATE_DATE@</date></docinfo>
+
+  <refmeta>
+    <refentrytitle>lxc-net</refentrytitle>
+    <manvolnum>1</manvolnum>
+  </refmeta>
+
+  <refnamediv>
+    <refname>lxc-net</refname>
+
+    <refpurpose>
+      run a process in the network context of a container
+    </refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <cmdsynopsis><command>lxc-net <replaceable>-n
+    name</replaceable> -- command</command></cmdsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Description</title>
+
+    <para>
+      <command>lxc-net</command> runs the specified
+      <replaceable>command</replaceable> inside the network
+      namespace of the container specified by
+      <replaceable>name</replaceable>. The container
+      has to be running already.
+    </para>
+    <para>
+      This may be used to query or modify the network
+      devices of a container from the outside. Note that
+      the executable itself must reside outside of the
+      container, since only the network namespace is
+      changed; the command will still see the file system
+      and process ids of the outside container.
+    </para>
+
+  </refsect1>
+
+  &commonoptions;
+
+  <refsect1>
+    <title>Examples</title>
+      <para>
+        To show the ip addresses of the devices of a container,
+        assuming iputils is installed outside, use
+        <programlisting>
+          lxc-net -n container -- ip -4 addr show
+        </programlisting>
+      </para>
+      <para>
+        To show the connections inside a container via netstat
+        <programlisting>
+          lxc-net -n container -- netstat
+        </programlisting>
+      </para>
+      <para>
+        To add an iptables filter rule
+        <programlisting>
+          lxc-net -n container -- iptables -A INPUT -d someip -j DROP
+        </programlisting>
+      </para>
+  </refsect1>
+
+  <refsect1>
+    <title>Notes</title>
+    <para>
+      This requires kernel version 3.0 to work.
+    </para>
+  </refsect1>
+
+  &seealso;
+
+  <refsect1>
+    <title>Author</title>
+    <para>Daniel Lezcano <email>daniel.lezcano at free.fr</email></para>
+  </refsect1>
+
+</refentry>
+
+<!-- Keep this comment at the end of the file
+Local variables:
+mode: sgml
+sgml-omittag:t
+sgml-shorttag:t
+sgml-minimize-attributes:nil
+sgml-always-quote-attributes:t
+sgml-indent-step:2
+sgml-indent-data:t
+sgml-parent-document:nil
+sgml-default-dtd-file:nil
+sgml-exposed-tags:nil
+sgml-local-catalogs:nil
+sgml-local-ecat-files:nil
+End:
+-->
diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am
index 1c26952..7b6f795 100644
--- a/src/lxc/Makefile.am
+++ b/src/lxc/Makefile.am
@@ -95,7 +95,8 @@ bin_PROGRAMS = \
 	lxc-unfreeze \
 	lxc-checkpoint \
 	lxc-restart \
-	lxc-kill
+	lxc-kill \
+	lxc-net
 
 pkglibexec_PROGRAMS = \
 	lxc-init
@@ -122,6 +123,7 @@ lxc_unfreeze_SOURCES = lxc_unfreeze.c
 lxc_unshare_SOURCES = lxc_unshare.c
 lxc_wait_SOURCES = lxc_wait.c
 lxc_kill_SOURCES = lxc_kill.c
+lxc_net_SOURCES = lxc_net.c
 
 install-exec-local: install-soPROGRAMS
 	mv $(DESTDIR)$(libdir)/liblxc.so $(DESTDIR)$(libdir)/liblxc.so.$(VERSION)
diff --git a/src/lxc/attach.c b/src/lxc/attach.c
index a95b3d3..45a3fd3 100644
--- a/src/lxc/attach.c
+++ b/src/lxc/attach.c
@@ -156,6 +156,28 @@ int lxc_attach_to_ns(pid_t pid)
 	return 0;
 }
 
+int lxc_attach_to_ns_type(pid_t pid, char *type)
+{
+	char path[MAXPATHLEN];
+	int fd;
+	
+	snprintf(path, MAXPATHLEN, "/proc/%d/ns/%s", pid, type);
+	fd = open(path, O_RDONLY);
+	if (fd < 0) {
+		SYSERROR("failed to open '%s'", path);
+		return -1;
+	}
+	
+	if (setns(fd, 0)) {
+		SYSERROR("failed to set namespace '%s'", type);
+		return -1;
+	}
+	
+	close(fd);
+	
+	return 0;
+}
+
 int lxc_attach_drop_privs(struct lxc_proc_context_info *ctx)
 {
 	int last_cap = lxc_caps_last_cap();
diff --git a/src/lxc/attach.h b/src/lxc/attach.h
index 2d46c83..0cfd6ae 100644
--- a/src/lxc/attach.h
+++ b/src/lxc/attach.h
@@ -34,6 +34,7 @@ struct lxc_proc_context_info {
 extern struct lxc_proc_context_info *lxc_proc_get_context_info(pid_t pid);
 
 extern int lxc_attach_to_ns(pid_t other_pid);
+extern int lxc_attach_to_ns_type(pid_t pid, char *type);
 extern int lxc_attach_drop_privs(struct lxc_proc_context_info *ctx);
 
 #endif
diff --git a/src/lxc/lxc_net.c b/src/lxc/lxc_net.c
new file mode 100644
index 0000000..80f2ffd
--- /dev/null
+++ b/src/lxc/lxc_net.c
@@ -0,0 +1,92 @@
+/*
+ * lxc: linux Container library
+ *
+ * (C) Copyright IBM Corp. 2007, 2010
+ *
+ * Authors:
+ * Daniel Lezcano <dlezcano at fr.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <errno.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/personality.h>
+
+#include "attach.h"
+#include "commands.h"
+#include "arguments.h"
+#include "confile.h"
+#include "log.h"
+
+lxc_log_define(lxc_net_ui, lxc);
+
+static const struct option my_longopts[] = {
+	LXC_COMMON_OPTIONS
+};
+
+static struct lxc_arguments my_args = {
+	.progname = "lxc-net",
+	.help     = "\
+--name=NAME\n\
+\n\
+Execute the specified command - in the network namespace of container NAME\n\
+\n\
+Options :\n\
+  -n, --name=NAME   NAME for name of the container",
+	.options  = my_longopts,
+	.parser   = NULL,
+	.checker  = NULL,
+};
+
+int main(int argc, char *argv[])
+{
+	int ret;
+	pid_t init_pid;
+
+	ret = lxc_arguments_parse(&my_args, argc, argv);
+	if (ret)
+		return ret;
+	
+	if (!my_args.argc) {
+		ERROR("usage: %s -n container -- command", argv[0]);
+		return -1;
+	}
+
+	ret = lxc_log_init(my_args.log_file, my_args.log_priority,
+			   my_args.progname, my_args.quiet);
+	if (ret)
+		return ret;
+
+	init_pid = get_init_pid(my_args.name);
+	if (init_pid < 0) {
+		ERROR("failed to get the init pid");
+		return -1;
+	}
+	
+	ret = lxc_attach_to_ns_type(init_pid, "net");
+	if (ret)
+		return ret;
+
+	execvp(my_args.argv[0], my_args.argv);
+	SYSERROR("failed to exec '%s'", my_args.argv[0]);
+	return -1;
+}
-- 
1.7.2.5





More information about the lxc-devel mailing list