From 886b41c6ff109d823894ae10233a84ba039617d9 Mon Sep 17 00:00:00 2001 From: Donald Buczek Date: Fri, 2 Nov 2018 13:47:11 +0100 Subject: [PATCH 01/10] uvpn: Add dhclient-script This file is taken from dhcp-4.3.2-0.x86_64/source/client/scripts/linux. The code will be embedded in th uvpn script in a later commit, but in an updated and reduced form. This external copy of the file serves as documentation so we can track the changes done to the code in the repository. --- uvpn/dhclient-script | 316 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 316 insertions(+) create mode 100755 uvpn/dhclient-script diff --git a/uvpn/dhclient-script b/uvpn/dhclient-script new file mode 100755 index 0000000..e6792c6 --- /dev/null +++ b/uvpn/dhclient-script @@ -0,0 +1,316 @@ +#!/bin/bash +# dhclient-script for Linux. Dan Halbert, March, 1997. +# Updated for Linux 2.[12] by Brian J. Murrell, January 1999. +# No guarantees about this. I'm a novice at the details of Linux +# networking. + +# Notes: + +# 0. This script is based on the netbsd script supplied with dhcp-970306. + +# 1. ifconfig down apparently deletes all relevant routes and flushes +# the arp cache, so this doesn't need to be done explicitly. + +# 2. The alias address handling here has not been tested AT ALL. +# I'm just going by the doc of modern Linux ip aliasing, which uses +# notations like eth0:0, eth0:1, for each alias. + +# 3. I have to calculate the network address, and calculate the broadcast +# address if it is not supplied. This might be much more easily done +# by the dhclient C code, and passed on. + +# 4. TIMEOUT not tested. ping has a flag I don't know, and I'm suspicious +# of the $1 in its args. + +# 'ip' just looks too weird. /sbin/ip looks less weird. +ip=/sbin/ip + +make_resolv_conf() { + if [ x"$new_domain_name_servers" != x ]; then + cat /dev/null > /etc/resolv.conf.dhclient + chmod 644 /etc/resolv.conf.dhclient + if [ x"$new_domain_search" != x ]; then + echo search $new_domain_search >> /etc/resolv.conf.dhclient + elif [ x"$new_domain_name" != x ]; then + # Note that the DHCP 'Domain Name Option' is really just a domain + # name, and that this practice of using the domain name option as + # a search path is both nonstandard and deprecated. + echo search $new_domain_name >> /etc/resolv.conf.dhclient + fi + for nameserver in $new_domain_name_servers; do + echo nameserver $nameserver >>/etc/resolv.conf.dhclient + done + + mv /etc/resolv.conf.dhclient /etc/resolv.conf + elif [ "x${new_dhcp6_name_servers}" != x ] ; then + cat /dev/null > /etc/resolv.conf.dhclient6 + chmod 644 /etc/resolv.conf.dhclient6 + + if [ "x${new_dhcp6_domain_search}" != x ] ; then + echo search ${new_dhcp6_domain_search} >> /etc/resolv.conf.dhclient6 + fi + shopt -s nocasematch + for nameserver in ${new_dhcp6_name_servers} ; do + # If the nameserver has a link-local address + # add a (interface name) to it. + if [[ "$nameserver" =~ ^fe80:: ]] + then + zone_id="%$interface" + else + zone_id= + fi + echo nameserver ${nameserver}$zone_id >> /etc/resolv.conf.dhclient6 + done + shopt -u nocasematch + + mv /etc/resolv.conf.dhclient6 /etc/resolv.conf + fi +} + +# Must be used on exit. Invokes the local dhcp client exit hooks, if any. +exit_with_hooks() { + exit_status=$1 + if [ -f /etc/dhclient-exit-hooks ]; then + . /etc/dhclient-exit-hooks + fi +# probably should do something with exit status of the local script + exit $exit_status +} + +# Invoke the local dhcp client enter hooks, if they exist. +if [ -f /etc/dhclient-enter-hooks ]; then + exit_status=0 + . /etc/dhclient-enter-hooks + # allow the local script to abort processing of this state + # local script must set exit_status variable to nonzero. + if [ $exit_status -ne 0 ]; then + exit $exit_status + fi +fi + +### +### DHCPv4 Handlers +### + +if [ x$new_broadcast_address != x ]; then + new_broadcast_arg="broadcast $new_broadcast_address" +fi +if [ x$old_broadcast_address != x ]; then + old_broadcast_arg="broadcast $old_broadcast_address" +fi +if [ x$new_subnet_mask != x ]; then + new_subnet_arg="netmask $new_subnet_mask" +fi +if [ x$old_subnet_mask != x ]; then + old_subnet_arg="netmask $old_subnet_mask" +fi +if [ x$alias_subnet_mask != x ]; then + alias_subnet_arg="netmask $alias_subnet_mask" +fi +if [ x$new_interface_mtu != x ]; then + mtu_arg="mtu $new_interface_mtu" +fi +if [ x$IF_METRIC != x ]; then + metric_arg="metric $IF_METRIC" +fi + +if [ x$reason = xMEDIUM ]; then + # Linux doesn't do mediums (ok, ok, media). + exit_with_hooks 0 +fi + +if [ x$reason = xPREINIT ]; then + if [ x$alias_ip_address != x ]; then + # Bring down alias interface. Its routes will disappear too. + ifconfig $interface:0- inet 0 + fi + ifconfig $interface 0 up + + # We need to give the kernel some time to get the interface up. + sleep 1 + + exit_with_hooks 0 +fi + +if [ x$reason = xARPCHECK ] || [ x$reason = xARPSEND ]; then + exit_with_hooks 0 +fi + +if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \ + [ x$reason = xREBIND ] || [ x$reason = xREBOOT ]; then + current_hostname=`hostname` + if [ x$current_hostname = x ] || \ + [ x$current_hostname = "x(none)" ] || \ + [ x$current_hostname = xlocalhost ] || \ + [ x$current_hostname = x$old_host_name ]; then + if [ x$new_host_name != x$old_host_name ]; then + hostname "$new_host_name" + fi + fi + + if [ x$old_ip_address != x ] && [ x$alias_ip_address != x ] && \ + [ x$alias_ip_address != x$old_ip_address ]; then + # Possible new alias. Remove old alias. + ifconfig $interface:0- inet 0 + fi + if [ x$old_ip_address != x ] && [ x$old_ip_address != x$new_ip_address ]; then + # IP address changed. Bringing down the interface will delete all routes, + # and clear the ARP cache. + ifconfig $interface inet 0 down + + fi + if [ x$old_ip_address = x ] || [ x$old_ip_address != x$new_ip_address ] || \ + [ x$reason = xBOUND ] || [ x$reason = xREBOOT ]; then + + ifconfig $interface inet $new_ip_address $new_subnet_arg \ + $new_broadcast_arg $mtu_arg + # Add a network route to the computed network address. + for router in $new_routers; do + if [ "x$new_subnet_mask" = "x255.255.255.255" ] ; then + route add -host $router dev $interface + fi + route add default gw $router $metric_arg dev $interface + done + else + # we haven't changed the address, have we changed other options + # that we wish to update? + if [ x$new_routers != x ] && [ x$new_routers != x$old_routers ] ; then + # if we've changed routers delete the old and add the new. + for router in $old_routers; do + route del default gw $router + done + for router in $new_routers; do + if [ "x$new_subnet_mask" = "x255.255.255.255" ] ; then + route add -host $router dev $interface + fi + route add default gw $router $metric_arg dev $interface + done + fi + fi + if [ x$new_ip_address != x$alias_ip_address ] && [ x$alias_ip_address != x ]; + then + ifconfig $interface:0- inet 0 + ifconfig $interface:0 inet $alias_ip_address $alias_subnet_arg + route add -host $alias_ip_address $interface:0 + fi + make_resolv_conf + exit_with_hooks 0 +fi + +if [ x$reason = xEXPIRE ] || [ x$reason = xFAIL ] || [ x$reason = xRELEASE ] \ + || [ x$reason = xSTOP ]; then + if [ x$alias_ip_address != x ]; then + # Turn off alias interface. + ifconfig $interface:0- inet 0 + fi + if [ x$old_ip_address != x ]; then + # Shut down interface, which will delete routes and clear arp cache. + ifconfig $interface inet 0 down + fi + if [ x$alias_ip_address != x ]; then + ifconfig $interface:0 inet $alias_ip_address $alias_subnet_arg + route add -host $alias_ip_address $interface:0 + fi + exit_with_hooks 0 +fi + +if [ x$reason = xTIMEOUT ]; then + if [ x$alias_ip_address != x ]; then + ifconfig $interface:0- inet 0 + fi + ifconfig $interface inet $new_ip_address $new_subnet_arg \ + $new_broadcast_arg $mtu_arg + set $new_routers + if ping -q -c 1 $1; then + if [ x$new_ip_address != x$alias_ip_address ] && \ + [ x$alias_ip_address != x ]; then + ifconfig $interface:0 inet $alias_ip_address $alias_subnet_arg + route add -host $alias_ip_address dev $interface:0 + fi + for router in $new_routers; do + if [ "x$new_subnet_mask" = "x255.255.255.255" ] ; then + route add -host $router dev $interface + fi + route add default gw $router $metric_arg dev $interface + done + make_resolv_conf + exit_with_hooks 0 + fi + ifconfig $interface inet 0 down + exit_with_hooks 1 +fi + +### +### DHCPv6 Handlers +### + +if [ x$reason = xPREINIT6 ] ; then + # Ensure interface is up. + ${ip} link set ${interface} up + + # Remove any stale addresses from aborted clients. + ${ip} -f inet6 addr flush dev ${interface} scope global permanent + + exit_with_hooks 0 +fi + +if [ x${old_ip6_prefix} != x ] || [ x${new_ip6_prefix} != x ] ; then + echo Prefix ${reason} old=${old_ip6_prefix} new=${new_ip6_prefix} + + exit_with_hooks 0 +fi + +if [ x$reason = xBOUND6 ] ; then + if [ x${new_ip6_address} = x ] || [ x${new_ip6_prefixlen} = x ] ; then + exit_with_hooks 2; + fi + + ${ip} -f inet6 addr add ${new_ip6_address}/${new_ip6_prefixlen} \ + dev ${interface} scope global + + # Check for nameserver options. + make_resolv_conf + + exit_with_hooks 0 +fi + +if [ x$reason = xRENEW6 ] || [ x$reason = xREBIND6 ] ; then + if [ x${new_ip6_address} != x ] && [ x${new_ip6_prefixlen} != x ] ; then + ${ip} -f inet6 addr add ${new_ip6_address}/${new_ip6_prefixlen} \ + dev ${interface} scope global + fi + + # Make sure nothing has moved around on us. + + # Nameservers/domains/etc. + if [ "x${new_dhcp6_name_servers}" != "x${old_dhcp6_name_servers}" ] || + [ "x${new_dhcp6_domain_search}" != "x${old_dhcp6_domain_search}" ] ; then + make_resolv_conf + fi + + exit_with_hooks 0 +fi + +if [ x$reason = xDEPREF6 ] ; then + if [ x${new_ip6_prefixlen} = x ] ; then + exit_with_hooks 2; + fi + + ${ip} -f inet6 addr change ${new_ip6_address}/${new_ip6_prefixlen} \ + dev ${interface} scope global preferred_lft 0 + + exit_with_hooks 0 +fi + +if [ x$reason = xEXPIRE6 -o x$reason = xRELEASE6 -o x$reason = xSTOP6 ] ; then + if [ x${old_ip6_address} = x ] || [ x${old_ip6_prefixlen} = x ] ; then + exit_with_hooks 2; + fi + + ${ip} -f inet6 addr del ${old_ip6_address}/${old_ip6_prefixlen} \ + dev ${interface} + + exit_with_hooks 0 +fi + +exit_with_hooks 0 From 27ce83a48d188f3cabf42a1d93414c2cd1540bb0 Mon Sep 17 00:00:00 2001 From: Donald Buczek Date: Fri, 2 Nov 2018 13:51:30 +0100 Subject: [PATCH 02/10] uvpn/dhclient-script: Remove useless comments --- uvpn/dhclient-script | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/uvpn/dhclient-script b/uvpn/dhclient-script index e6792c6..b288a9e 100755 --- a/uvpn/dhclient-script +++ b/uvpn/dhclient-script @@ -1,28 +1,5 @@ #!/bin/bash -# dhclient-script for Linux. Dan Halbert, March, 1997. -# Updated for Linux 2.[12] by Brian J. Murrell, January 1999. -# No guarantees about this. I'm a novice at the details of Linux -# networking. -# Notes: - -# 0. This script is based on the netbsd script supplied with dhcp-970306. - -# 1. ifconfig down apparently deletes all relevant routes and flushes -# the arp cache, so this doesn't need to be done explicitly. - -# 2. The alias address handling here has not been tested AT ALL. -# I'm just going by the doc of modern Linux ip aliasing, which uses -# notations like eth0:0, eth0:1, for each alias. - -# 3. I have to calculate the network address, and calculate the broadcast -# address if it is not supplied. This might be much more easily done -# by the dhclient C code, and passed on. - -# 4. TIMEOUT not tested. ping has a flag I don't know, and I'm suspicious -# of the $1 in its args. - -# 'ip' just looks too weird. /sbin/ip looks less weird. ip=/sbin/ip make_resolv_conf() { @@ -172,7 +149,7 @@ if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \ route add default gw $router $metric_arg dev $interface done else - # we haven't changed the address, have we changed other options + # we haven't changed the address, have we changed other options # that we wish to update? if [ x$new_routers != x ] && [ x$new_routers != x$old_routers ] ; then # if we've changed routers delete the old and add the new. From 5b00c2fc065db0e3e2020712a4238c9c49b3e76f Mon Sep 17 00:00:00 2001 From: Donald Buczek Date: Fri, 2 Nov 2018 13:53:33 +0100 Subject: [PATCH 03/10] uvpn/dhclient-script: Remove make_resolv_conf() --- uvpn/dhclient-script | 53 -------------------------------------------- 1 file changed, 53 deletions(-) diff --git a/uvpn/dhclient-script b/uvpn/dhclient-script index b288a9e..ad11229 100755 --- a/uvpn/dhclient-script +++ b/uvpn/dhclient-script @@ -2,48 +2,6 @@ ip=/sbin/ip -make_resolv_conf() { - if [ x"$new_domain_name_servers" != x ]; then - cat /dev/null > /etc/resolv.conf.dhclient - chmod 644 /etc/resolv.conf.dhclient - if [ x"$new_domain_search" != x ]; then - echo search $new_domain_search >> /etc/resolv.conf.dhclient - elif [ x"$new_domain_name" != x ]; then - # Note that the DHCP 'Domain Name Option' is really just a domain - # name, and that this practice of using the domain name option as - # a search path is both nonstandard and deprecated. - echo search $new_domain_name >> /etc/resolv.conf.dhclient - fi - for nameserver in $new_domain_name_servers; do - echo nameserver $nameserver >>/etc/resolv.conf.dhclient - done - - mv /etc/resolv.conf.dhclient /etc/resolv.conf - elif [ "x${new_dhcp6_name_servers}" != x ] ; then - cat /dev/null > /etc/resolv.conf.dhclient6 - chmod 644 /etc/resolv.conf.dhclient6 - - if [ "x${new_dhcp6_domain_search}" != x ] ; then - echo search ${new_dhcp6_domain_search} >> /etc/resolv.conf.dhclient6 - fi - shopt -s nocasematch - for nameserver in ${new_dhcp6_name_servers} ; do - # If the nameserver has a link-local address - # add a (interface name) to it. - if [[ "$nameserver" =~ ^fe80:: ]] - then - zone_id="%$interface" - else - zone_id= - fi - echo nameserver ${nameserver}$zone_id >> /etc/resolv.conf.dhclient6 - done - shopt -u nocasematch - - mv /etc/resolv.conf.dhclient6 /etc/resolv.conf - fi -} - # Must be used on exit. Invokes the local dhcp client exit hooks, if any. exit_with_hooks() { exit_status=$1 @@ -170,7 +128,6 @@ if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \ ifconfig $interface:0 inet $alias_ip_address $alias_subnet_arg route add -host $alias_ip_address $interface:0 fi - make_resolv_conf exit_with_hooks 0 fi @@ -210,7 +167,6 @@ if [ x$reason = xTIMEOUT ]; then fi route add default gw $router $metric_arg dev $interface done - make_resolv_conf exit_with_hooks 0 fi ifconfig $interface inet 0 down @@ -245,9 +201,6 @@ if [ x$reason = xBOUND6 ] ; then ${ip} -f inet6 addr add ${new_ip6_address}/${new_ip6_prefixlen} \ dev ${interface} scope global - # Check for nameserver options. - make_resolv_conf - exit_with_hooks 0 fi @@ -259,12 +212,6 @@ if [ x$reason = xRENEW6 ] || [ x$reason = xREBIND6 ] ; then # Make sure nothing has moved around on us. - # Nameservers/domains/etc. - if [ "x${new_dhcp6_name_servers}" != "x${old_dhcp6_name_servers}" ] || - [ "x${new_dhcp6_domain_search}" != "x${old_dhcp6_domain_search}" ] ; then - make_resolv_conf - fi - exit_with_hooks 0 fi From 3335147d6f396c15258fe7f2952fd9f51261408a Mon Sep 17 00:00:00 2001 From: Donald Buczek Date: Fri, 2 Nov 2018 13:56:01 +0100 Subject: [PATCH 04/10] uvpn/dhclient-script: Remove hooks --- uvpn/dhclient-script | 55 ++++++++++++++------------------------------ 1 file changed, 17 insertions(+), 38 deletions(-) diff --git a/uvpn/dhclient-script b/uvpn/dhclient-script index ad11229..6713a0c 100755 --- a/uvpn/dhclient-script +++ b/uvpn/dhclient-script @@ -2,27 +2,6 @@ ip=/sbin/ip -# Must be used on exit. Invokes the local dhcp client exit hooks, if any. -exit_with_hooks() { - exit_status=$1 - if [ -f /etc/dhclient-exit-hooks ]; then - . /etc/dhclient-exit-hooks - fi -# probably should do something with exit status of the local script - exit $exit_status -} - -# Invoke the local dhcp client enter hooks, if they exist. -if [ -f /etc/dhclient-enter-hooks ]; then - exit_status=0 - . /etc/dhclient-enter-hooks - # allow the local script to abort processing of this state - # local script must set exit_status variable to nonzero. - if [ $exit_status -ne 0 ]; then - exit $exit_status - fi -fi - ### ### DHCPv4 Handlers ### @@ -51,7 +30,7 @@ fi if [ x$reason = xMEDIUM ]; then # Linux doesn't do mediums (ok, ok, media). - exit_with_hooks 0 + exit 0 fi if [ x$reason = xPREINIT ]; then @@ -64,11 +43,11 @@ if [ x$reason = xPREINIT ]; then # We need to give the kernel some time to get the interface up. sleep 1 - exit_with_hooks 0 + exit 0 fi if [ x$reason = xARPCHECK ] || [ x$reason = xARPSEND ]; then - exit_with_hooks 0 + exit 0 fi if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \ @@ -128,7 +107,7 @@ if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \ ifconfig $interface:0 inet $alias_ip_address $alias_subnet_arg route add -host $alias_ip_address $interface:0 fi - exit_with_hooks 0 + exit 0 fi if [ x$reason = xEXPIRE ] || [ x$reason = xFAIL ] || [ x$reason = xRELEASE ] \ @@ -145,7 +124,7 @@ if [ x$reason = xEXPIRE ] || [ x$reason = xFAIL ] || [ x$reason = xRELEASE ] \ ifconfig $interface:0 inet $alias_ip_address $alias_subnet_arg route add -host $alias_ip_address $interface:0 fi - exit_with_hooks 0 + exit 0 fi if [ x$reason = xTIMEOUT ]; then @@ -167,10 +146,10 @@ if [ x$reason = xTIMEOUT ]; then fi route add default gw $router $metric_arg dev $interface done - exit_with_hooks 0 + exit 0 fi ifconfig $interface inet 0 down - exit_with_hooks 1 + exit 1 fi ### @@ -184,24 +163,24 @@ if [ x$reason = xPREINIT6 ] ; then # Remove any stale addresses from aborted clients. ${ip} -f inet6 addr flush dev ${interface} scope global permanent - exit_with_hooks 0 + exit 0 fi if [ x${old_ip6_prefix} != x ] || [ x${new_ip6_prefix} != x ] ; then echo Prefix ${reason} old=${old_ip6_prefix} new=${new_ip6_prefix} - exit_with_hooks 0 + exit 0 fi if [ x$reason = xBOUND6 ] ; then if [ x${new_ip6_address} = x ] || [ x${new_ip6_prefixlen} = x ] ; then - exit_with_hooks 2; + exit 2; fi ${ip} -f inet6 addr add ${new_ip6_address}/${new_ip6_prefixlen} \ dev ${interface} scope global - exit_with_hooks 0 + exit 0 fi if [ x$reason = xRENEW6 ] || [ x$reason = xREBIND6 ] ; then @@ -212,29 +191,29 @@ if [ x$reason = xRENEW6 ] || [ x$reason = xREBIND6 ] ; then # Make sure nothing has moved around on us. - exit_with_hooks 0 + exit 0 fi if [ x$reason = xDEPREF6 ] ; then if [ x${new_ip6_prefixlen} = x ] ; then - exit_with_hooks 2; + exit 2; fi ${ip} -f inet6 addr change ${new_ip6_address}/${new_ip6_prefixlen} \ dev ${interface} scope global preferred_lft 0 - exit_with_hooks 0 + exit 0 fi if [ x$reason = xEXPIRE6 -o x$reason = xRELEASE6 -o x$reason = xSTOP6 ] ; then if [ x${old_ip6_address} = x ] || [ x${old_ip6_prefixlen} = x ] ; then - exit_with_hooks 2; + exit 2; fi ${ip} -f inet6 addr del ${old_ip6_address}/${old_ip6_prefixlen} \ dev ${interface} - exit_with_hooks 0 + exit 0 fi -exit_with_hooks 0 +exit 0 From 23a1cb9df74c89487dd82dccb9c283d4b6a95147 Mon Sep 17 00:00:00 2001 From: Donald Buczek Date: Fri, 2 Nov 2018 14:01:21 +0100 Subject: [PATCH 05/10] uvpn/dhclient-script: Remove ip6 methods --- uvpn/dhclient-script | 64 -------------------------------------------- 1 file changed, 64 deletions(-) diff --git a/uvpn/dhclient-script b/uvpn/dhclient-script index 6713a0c..1f29cf6 100755 --- a/uvpn/dhclient-script +++ b/uvpn/dhclient-script @@ -152,68 +152,4 @@ if [ x$reason = xTIMEOUT ]; then exit 1 fi -### -### DHCPv6 Handlers -### - -if [ x$reason = xPREINIT6 ] ; then - # Ensure interface is up. - ${ip} link set ${interface} up - - # Remove any stale addresses from aborted clients. - ${ip} -f inet6 addr flush dev ${interface} scope global permanent - - exit 0 -fi - -if [ x${old_ip6_prefix} != x ] || [ x${new_ip6_prefix} != x ] ; then - echo Prefix ${reason} old=${old_ip6_prefix} new=${new_ip6_prefix} - - exit 0 -fi - -if [ x$reason = xBOUND6 ] ; then - if [ x${new_ip6_address} = x ] || [ x${new_ip6_prefixlen} = x ] ; then - exit 2; - fi - - ${ip} -f inet6 addr add ${new_ip6_address}/${new_ip6_prefixlen} \ - dev ${interface} scope global - - exit 0 -fi - -if [ x$reason = xRENEW6 ] || [ x$reason = xREBIND6 ] ; then - if [ x${new_ip6_address} != x ] && [ x${new_ip6_prefixlen} != x ] ; then - ${ip} -f inet6 addr add ${new_ip6_address}/${new_ip6_prefixlen} \ - dev ${interface} scope global - fi - - # Make sure nothing has moved around on us. - - exit 0 -fi - -if [ x$reason = xDEPREF6 ] ; then - if [ x${new_ip6_prefixlen} = x ] ; then - exit 2; - fi - - ${ip} -f inet6 addr change ${new_ip6_address}/${new_ip6_prefixlen} \ - dev ${interface} scope global preferred_lft 0 - - exit 0 -fi - -if [ x$reason = xEXPIRE6 -o x$reason = xRELEASE6 -o x$reason = xSTOP6 ] ; then - if [ x${old_ip6_address} = x ] || [ x${old_ip6_prefixlen} = x ] ; then - exit 2; - fi - - ${ip} -f inet6 addr del ${old_ip6_address}/${old_ip6_prefixlen} \ - dev ${interface} - - exit 0 -fi - exit 0 From c7d8c086bddb34197f75257477cb0c4142f8adff Mon Sep 17 00:00:00 2001 From: Donald Buczek Date: Fri, 2 Nov 2018 14:02:44 +0100 Subject: [PATCH 06/10] uvpn/dhclient-script: Remove noop methods --- uvpn/dhclient-script | 9 --------- 1 file changed, 9 deletions(-) diff --git a/uvpn/dhclient-script b/uvpn/dhclient-script index 1f29cf6..5c3e657 100755 --- a/uvpn/dhclient-script +++ b/uvpn/dhclient-script @@ -28,11 +28,6 @@ if [ x$IF_METRIC != x ]; then metric_arg="metric $IF_METRIC" fi -if [ x$reason = xMEDIUM ]; then - # Linux doesn't do mediums (ok, ok, media). - exit 0 -fi - if [ x$reason = xPREINIT ]; then if [ x$alias_ip_address != x ]; then # Bring down alias interface. Its routes will disappear too. @@ -46,10 +41,6 @@ if [ x$reason = xPREINIT ]; then exit 0 fi -if [ x$reason = xARPCHECK ] || [ x$reason = xARPSEND ]; then - exit 0 -fi - if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \ [ x$reason = xREBIND ] || [ x$reason = xREBOOT ]; then current_hostname=`hostname` From 7117d99a6858638153e17b77049d535a2e7cb6a7 Mon Sep 17 00:00:00 2001 From: Donald Buczek Date: Fri, 2 Nov 2018 14:03:14 +0100 Subject: [PATCH 07/10] uvpn/dhclient-script: Remove PREINIT method --- uvpn/dhclient-script | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/uvpn/dhclient-script b/uvpn/dhclient-script index 5c3e657..4b67126 100755 --- a/uvpn/dhclient-script +++ b/uvpn/dhclient-script @@ -28,19 +28,6 @@ if [ x$IF_METRIC != x ]; then metric_arg="metric $IF_METRIC" fi -if [ x$reason = xPREINIT ]; then - if [ x$alias_ip_address != x ]; then - # Bring down alias interface. Its routes will disappear too. - ifconfig $interface:0- inet 0 - fi - ifconfig $interface 0 up - - # We need to give the kernel some time to get the interface up. - sleep 1 - - exit 0 -fi - if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \ [ x$reason = xREBIND ] || [ x$reason = xREBOOT ]; then current_hostname=`hostname` From 72226468971dc9ec49172f8ead0d32285b2c73f7 Mon Sep 17 00:00:00 2001 From: Donald Buczek Date: Fri, 2 Nov 2018 14:03:46 +0100 Subject: [PATCH 08/10] uvpn/dhclient-script: Remove hostname manipulation --- uvpn/dhclient-script | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/uvpn/dhclient-script b/uvpn/dhclient-script index 4b67126..50612bb 100755 --- a/uvpn/dhclient-script +++ b/uvpn/dhclient-script @@ -30,16 +30,7 @@ fi if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \ [ x$reason = xREBIND ] || [ x$reason = xREBOOT ]; then - current_hostname=`hostname` - if [ x$current_hostname = x ] || \ - [ x$current_hostname = "x(none)" ] || \ - [ x$current_hostname = xlocalhost ] || \ - [ x$current_hostname = x$old_host_name ]; then - if [ x$new_host_name != x$old_host_name ]; then - hostname "$new_host_name" - fi - fi - + if [ x$old_ip_address != x ] && [ x$alias_ip_address != x ] && \ [ x$alias_ip_address != x$old_ip_address ]; then # Possible new alias. Remove old alias. From 9f5824957c4d48caf84cd775269bc6b94b25eb7e Mon Sep 17 00:00:00 2001 From: Donald Buczek Date: Fri, 2 Nov 2018 14:20:22 +0100 Subject: [PATCH 09/10] uvpn/dhclient-script: Use `ip route` instead of `route` --- uvpn/dhclient-script | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/uvpn/dhclient-script b/uvpn/dhclient-script index 50612bb..52183e1 100755 --- a/uvpn/dhclient-script +++ b/uvpn/dhclient-script @@ -50,9 +50,9 @@ if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \ # Add a network route to the computed network address. for router in $new_routers; do if [ "x$new_subnet_mask" = "x255.255.255.255" ] ; then - route add -host $router dev $interface + ip route add $router dev $interface fi - route add default gw $router $metric_arg dev $interface + ip route add default via $router dev $interface $metric_arg done else # we haven't changed the address, have we changed other options @@ -60,13 +60,13 @@ if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \ if [ x$new_routers != x ] && [ x$new_routers != x$old_routers ] ; then # if we've changed routers delete the old and add the new. for router in $old_routers; do - route del default gw $router + ip route del default via $router done for router in $new_routers; do if [ "x$new_subnet_mask" = "x255.255.255.255" ] ; then - route add -host $router dev $interface - fi - route add default gw $router $metric_arg dev $interface + ip route add $router dev $interface + fi + ip route add default via $router dev $interface $metric_arg done fi fi @@ -74,7 +74,7 @@ if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \ then ifconfig $interface:0- inet 0 ifconfig $interface:0 inet $alias_ip_address $alias_subnet_arg - route add -host $alias_ip_address $interface:0 + ip route add $alias_ip_address dev $interface:0 fi exit 0 fi @@ -91,7 +91,7 @@ if [ x$reason = xEXPIRE ] || [ x$reason = xFAIL ] || [ x$reason = xRELEASE ] \ fi if [ x$alias_ip_address != x ]; then ifconfig $interface:0 inet $alias_ip_address $alias_subnet_arg - route add -host $alias_ip_address $interface:0 + ip route add $alias_ip_address dev $interface:0 fi exit 0 fi @@ -107,13 +107,13 @@ if [ x$reason = xTIMEOUT ]; then if [ x$new_ip_address != x$alias_ip_address ] && \ [ x$alias_ip_address != x ]; then ifconfig $interface:0 inet $alias_ip_address $alias_subnet_arg - route add -host $alias_ip_address dev $interface:0 + ip route add $alias_ip_address dev $interface:0 fi for router in $new_routers; do if [ "x$new_subnet_mask" = "x255.255.255.255" ] ; then - route add -host $router dev $interface + ip route add $router dev $interface fi - route add default gw $router $metric_arg dev $interface + ip route add default via $router dev $interface $metric_arg done exit 0 fi From 02dce7b6c18ed80d51a002035897d0043a5a2bae Mon Sep 17 00:00:00 2001 From: Donald Buczek Date: Fri, 2 Nov 2018 13:50:50 +0100 Subject: [PATCH 10/10] uvpn: Add initial version This tools allows a user to create a (net,mnt,user)-namespace container which can be used to run openvpn. This tools uses sudo to gain privileges for the setup and requires a line like ALL ALL=NOPASSWD: /usr/bin/uvpn start_as_root,/usr/bin/uvpn stop_as_root in the sudoers file. The container will be connected to the guest network. For this the system needs a working vlan.guest0 vlan interface into the guest network. The usage for the user might be along this pattern: uvpn start uvpn exec openvpn ~/.charite-username.ovpn echo -e "search charite.de\nnameserver 141.42.1.1\nnameserver 141.14.16.1" | uvpn exec bash -c 'cat > /etc/resolv.conf' uvpn exec firefox --new-instance --ProfileManager uvpn exec firefox --new-instance -P charite uvpn show uvpn stop_container Because the network of the container is separate from the host system, ip based X11-forward will not work without more setup. So the above example would only work on the local workstation. --- install.sh | 1 + uvpn/uvpn | 303 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 304 insertions(+) create mode 100755 uvpn/uvpn diff --git a/install.sh b/install.sh index c5a45ed..9bdf6e0 100755 --- a/install.sh +++ b/install.sh @@ -126,4 +126,5 @@ install_data blink/51-blink.rules "$DESTDIR$udev_rulesdir install_data clusterd/clusterd.service "$DESTDIR$systemdunitdir/clusterd.service" install_exec clusterd/clusterd "$DESTDIR$usr_sbindir/clusterd" install_exec setuid/setuid "$DESTDIR$usr_sbindir/setuid" +install_exec uvpn/uvpn "$DESTDIR$usr_bindir/uvpn" exit diff --git a/uvpn/uvpn b/uvpn/uvpn new file mode 100755 index 0000000..c678551 --- /dev/null +++ b/uvpn/uvpn @@ -0,0 +1,303 @@ +#! /bin/bash + +die() { + echo "$@">&2 + exit 1 +} + +die_usage() { + cat </var/run/uvpn/$USER/dhclient-script << '_EOF_' +#!/bin/bash + +ip=/sbin/ip + +### +### DHCPv4 Handlers +### + +if [ x$new_broadcast_address != x ]; then + new_broadcast_arg="broadcast $new_broadcast_address" +fi +if [ x$old_broadcast_address != x ]; then + old_broadcast_arg="broadcast $old_broadcast_address" +fi +if [ x$new_subnet_mask != x ]; then + new_subnet_arg="netmask $new_subnet_mask" +fi +if [ x$old_subnet_mask != x ]; then + old_subnet_arg="netmask $old_subnet_mask" +fi +if [ x$alias_subnet_mask != x ]; then + alias_subnet_arg="netmask $alias_subnet_mask" +fi +if [ x$new_interface_mtu != x ]; then + mtu_arg="mtu $new_interface_mtu" +fi +if [ x$IF_METRIC != x ]; then + metric_arg="metric $IF_METRIC" +fi + +if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \ + [ x$reason = xREBIND ] || [ x$reason = xREBOOT ]; then + + if [ x$old_ip_address != x ] && [ x$alias_ip_address != x ] && \ + [ x$alias_ip_address != x$old_ip_address ]; then + # Possible new alias. Remove old alias. + ifconfig $interface:0- inet 0 + fi + if [ x$old_ip_address != x ] && [ x$old_ip_address != x$new_ip_address ]; then + # IP address changed. Bringing down the interface will delete all routes, + # and clear the ARP cache. + ifconfig $interface inet 0 down + + fi + if [ x$old_ip_address = x ] || [ x$old_ip_address != x$new_ip_address ] || \ + [ x$reason = xBOUND ] || [ x$reason = xREBOOT ]; then + + ifconfig $interface inet $new_ip_address $new_subnet_arg \ + $new_broadcast_arg $mtu_arg + # Add a network route to the computed network address. + for router in $new_routers; do + if [ "x$new_subnet_mask" = "x255.255.255.255" ] ; then + ip route add $router dev $interface + fi + ip route add default via $router dev $interface $metric_arg + done + else + # we haven't changed the address, have we changed other options + # that we wish to update? + if [ x$new_routers != x ] && [ x$new_routers != x$old_routers ] ; then + # if we've changed routers delete the old and add the new. + for router in $old_routers; do + ip route del default via $router + done + for router in $new_routers; do + if [ "x$new_subnet_mask" = "x255.255.255.255" ] ; then + ip route add $router dev $interface + fi + ip route add default via $router dev $interface $metric_arg + done + fi + fi + if [ x$new_ip_address != x$alias_ip_address ] && [ x$alias_ip_address != x ]; + then + ifconfig $interface:0- inet 0 + ifconfig $interface:0 inet $alias_ip_address $alias_subnet_arg + ip route add $alias_ip_address dev $interface:0 + fi + exit 0 +fi + +if [ x$reason = xEXPIRE ] || [ x$reason = xFAIL ] || [ x$reason = xRELEASE ] \ + || [ x$reason = xSTOP ]; then + if [ x$alias_ip_address != x ]; then + # Turn off alias interface. + ifconfig $interface:0- inet 0 + fi + if [ x$old_ip_address != x ]; then + # Shut down interface, which will delete routes and clear arp cache. + ifconfig $interface inet 0 down + fi + if [ x$alias_ip_address != x ]; then + ifconfig $interface:0 inet $alias_ip_address $alias_subnet_arg + ip route add $alias_ip_address dev $interface:0 + fi + exit 0 +fi + +if [ x$reason = xTIMEOUT ]; then + if [ x$alias_ip_address != x ]; then + ifconfig $interface:0- inet 0 + fi + ifconfig $interface inet $new_ip_address $new_subnet_arg \ + $new_broadcast_arg $mtu_arg + set $new_routers + if ping -q -c 1 $1; then + if [ x$new_ip_address != x$alias_ip_address ] && \ + [ x$alias_ip_address != x ]; then + ifconfig $interface:0 inet $alias_ip_address $alias_subnet_arg + ip route add $alias_ip_address dev $interface:0 + fi + for router in $new_routers; do + if [ "x$new_subnet_mask" = "x255.255.255.255" ] ; then + ip route add $router dev $interface + fi + ip route add default via $router dev $interface $metric_arg + done + exit 0 + fi + ifconfig $interface inet 0 down + exit 1 +fi + +exit 0 +_EOF_ + chmod +x /var/run/uvpn/$USER/dhclient-script +} + +have_interface() { + local if="$1" + ip link show "$1" >/dev/null 2>&1 +} + +cmd_start() { + test $# -eq 0 || die_usage + + sudo $0 start_as_root || exit 1 + create_dhclient-script + cat >/var/run/uvpn/$USER/resolv.conf<<_EOF_ +search molgen.mpg.de +nameserver 141.14.16.1 +_EOF_ + cmd_exec ip link set lo up + cmd_exec ip link set "uvpn.$USER.1" up + cmd_exec mount --bind /var/run/uvpn/$USER/resolv.conf /etc/resolv.conf + cmd_exec dhclient -4 -v \ + -lf /var/run/uvpn/$USER/dhclient.leases \ + -pf /var/run/uvpn/$USER/dhclient.pid \ + -sf /var/run/uvpn/$USER/dhclient-script \ + uvpn.$USER.1 + exit +} + +cmd_start_as_root() { + test $# -eq 0 || die_usage + + test $(id -u) -eq 0 || die "must be root" + user="$SUDO_USER" + test -n "$user" || die "must be called via sudo" + uid=$(id -u "$user") 2>/dev/null || die "$user: no such user" + umask 022 + have_interface vlan.guest0 || die "vlan.guest0 not available. This system is not prepared to run $0. Please contact helpdesk@molgen.mpg.de" + + findmnt "/run/uvpn/$user/ns" >/dev/null 2>&1 && die "container already started" + + if ! have_interface "uvpn.$user.0"; then + ip link add "uvpn.$user.0" type veth peer name "uvpn.$user.1" + fi + if ! have_interface br.guest0; then + brctl addbr br.guest0 + brctl addif br.guest0 vlan.guest0 + fi + brctl addif br.guest0 "uvpn.$user.0" + ip link set "uvpn.$user.0" up + ip link set vlan.guest0 up + ip link set br.guest0 up + + mkdir -p "/run/uvpn/$user/ns" + chown "$user" "/run/uvpn/$user" + for ns in user net mnt;do + touch "/run/uvpn/$user/ns/$ns" + done + mount --bind "/run/uvpn/$user/ns" "/run/uvpn/$user/ns" + mount --make-private "/run/uvpn/$user/ns" + + pid=$(setuid $uid unshare --mount --user --net bash -c 'sleep 30 > /dev/null&echo $!') + for ns in user net mnt;do + mount --bind /proc/$pid/ns/$ns "/run/uvpn/$user/ns/$ns" + done + echo "0 $uid 1" > /proc/$pid/uid_map + echo "0 $(id -g "$user") 1" > /proc/$pid/gid_map + ip link set "uvpn.$user.1" netns $pid + kill $pid +} + +cmd_stop() { + test $# -eq 0 || die_usage + user=$USER + uid=$(id -u "$user") + if findmnt "/run/uvpn/$user/ns/net" > /dev/null; then + inode_net=$(stat --format %i "/run/uvpn/$user/ns/net") + for pid in $(cd /proc;ls -1d [0-9]*|sort -n); do + inode="$(stat -L --format %i /proc/$pid/ns/net 2>/dev/null)" || continue + test $inode == $inode_net || continue + cmd=$(cat /proc/$pid/cmdline|sed 's/\x0/ /g') + echo "kill --> $pid $cmd" + kill -9 $pid + found_processes=1 + done + test -n "$found_processes" && sleep 1 + fi + sudo $0 stop_as_root +} + +cmd_stop_as_root() { + test $# -eq 0 || die_usage + test $(id -u) -eq 0 || die "must be root" + user="$SUDO_USER" + test -n "$user" || die "must be called via sudo" + uid=$(id -u "$user") 2>/dev/null || die "$user: no such user" + + for ns in user net mnt;do + while umount "/run/uvpn/$user/ns/$ns" 2>/dev/null; do true; done + done + while umount "/run/uvpn/$user/ns" 2>/dev/null; do true; done + ip link del "uvpn.$user.0" 2>/dev/null +} + +cmd_exec() { + findmnt "/run/uvpn/$USER/ns" >/dev/null 2>&1 || die "container not started" + nsenter \ + --wd=$(pwd) \ + --net="/run/uvpn/$USER/ns/net" \ + --user="/run/uvpn/$USER/ns/user" \ + --mount="/run/uvpn/$USER/ns/mnt" \ + "$@" +} + +cmd_show() { + user="$1";shift + test $# -eq 0 || die_usage + test -z "$user" && user=$USER + uid=$(id -u "$user") 2>/dev/null || die "$user: no such user" + findmnt "/run/uvpn/$user/ns/net" >/dev/null 2>/dev/null || { echo "Container not started"; exit; } + inode_net=$(stat --format %i "/run/uvpn/$user/ns/net") + echo "Processes running in this container:" + for pid in $(cd /proc;ls -1d [0-9]*|sort -n); do + inode="$(stat -L --format %i /proc/$pid/ns/net 2>/dev/null)" || continue + test $inode == $inode_net || continue + cmd=$(cat /proc/$pid/cmdline|sed 's/\x0/ /g') + echo " $pid $cmd" + found_processes=1 + done + test -n "$found_processes" || echo " (none)" +} + +cmd="$1";shift +case "$cmd" in + start) + cmd_start "$@" + ;; + start_as_root) + cmd_start_as_root "$@" + ;; + stop) + cmd_stop "$@" + ;; + stop_as_root) + cmd_stop_as_root "$@" + ;; + exec) + cmd_exec "$@" + ;; + show) + cmd_show "$@" + ;; + *) + die_usage + ;; +esac