#!/usr/bin/perl # Reprequisites: # Install Linux::Unshare from CPAN # Ensure conntrack is installed use strict; use warnings; use POSIX "setsid"; use Linux::Unshare qw(unshare :clone); # get this from CPAN # Parent returns PID, child returns 0 sub daemonize { chdir("/") || die "can't chdir to /: $!"; open(STDIN, "< /dev/null") || die "can't read /dev/null: $!"; open(STDOUT, "> /dev/null") || die "can't write to /dev/null: $!"; defined(my $pid = fork()) || die "can't fork: $!"; return $pid if $pid; # non-zero now means I am the parent (setsid() != -1) || die "Can't start a new session: $!"; open(STDERR, ">&STDOUT") || die "can't dup stdout: $!"; return 0; } sub docontainer { print STDERR "Child: container starting\n"; sleep (5); print STDERR "Child: setting ip addresses\n"; system("ip link set vethr up"); system("ip link show"); system("ip addr add 10.99.99.2/24 dev vethr"); system("ip addr add 127.0.0.1/8 dev lo"); system("ip link set lo up"); system("echo 1 > /proc/sys/net/ipv4/ip_forward"); system("echo 1 > /proc/sys/net/ipv4/conf/all/forwarding"); system("echo 1 > /proc/sys/net/ipv6/conf/all/forwarding"); system("echo 2 > /proc/sys/net/ipv4/conf/all/rp_filter"); system("echo 0 > /proc/sys/net/ipv4/conf/all/accept_source_route"); system("echo 0 > /proc/sys/net/ipv4/conf/all/send_redirects"); system("echo 0 > /proc/sys/net/ipv4/conf/all/accept_redirects"); system("echo 1 > /proc/sys/net/ipv4/conf/all/proxy_arp"); system("iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT"); system("iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT"); print STDERR "Child: pinging parent and running conntrack\n"; while (1) { system("conntrack -L"); system("ping -n -c1 10.99.99.2"); sleep(1); } exit(0); } sub startcontainer { system("ip link add vethl type veth peer name vethr"); system("ip addr add 10.99.99.1/24 dev vethl"); system("ip link set vethl up"); print "Parent: Start container\n"; defined(my $cpid = fork()) || die "can't fork: $!"; if (!$cpid) { print STDERR "Child: starting\n"; unshare(CLONE_NEWNET); docontainer(); exit 0; } print STDERR "Parent: Container started pid $cpid\n"; system("ip addr show | fgrep veth"); sleep(1); print STDERR "Parent: running ip link set vethr netns $cpid\n"; (system("ip link set vethr netns $cpid") ==0) || print STDERR "WARNING!: ip link netns failed\n"; sleep(1); system("ip addr show | fgrep veth"); print STDERR "Parent: Moved vethr, parent pinging child\n"; system("ping -n -c5 10.99.99.2"); print STDERR "Parent: Moved vethr, ping done\n"; sleep(2); system("kill -KILL $cpid"); } while (1) { startcontainer; }