#!/bin/sh # # default updown script for use with NETKEY(XFRM) # # Copyright (C) 2003-2004 Nigel Metheringham # Copyright (C) 2002-2007 Michael Richardson # Copyright (C) 2007-2008 Paul Wouters # Copyright (C) 2003-2020 Tuomo Soini # Copyright (C) 2011-2016 Paul Wouters # Copyright (C) 2016 Antony Antony # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program 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 General Public License # for more details. # CAUTION: Installing a new version of Libreswan will install a new # copy of this script, wiping out any custom changes you make. If # you need changes, make a copy of this under another name, and customize # that, and use the (left/right)updown= parameters in ipsec.conf to make # Libreswan use your modified updown script instead of this default one. test ${IPSEC_INIT_SCRIPT_DEBUG} && set -v -x LC_ALL=C export LC_ALL # Things that this script gets (from ipsec_pluto(8) man page) # # # PLUTO_VERSION # indicates what version of this interface is being # used. This document describes version 1.1. This # is upwardly compatible with version 1.0. # # PLUTO_VERB # specifies the name of the operation to be performed # (prepare-host, prepare-client, up-host, up-client, # down-host, or down-client). If the address family # for security gateway to security gateway # communications is IPv6, then a suffix of -v6 is added # to the verb. # # PLUTO_CONNECTION # is the name of the connection for which we are # routing. # # PLUTO_CONN_POLICY # the policy of the connection, as in: # RSASIG+ENCRYPT+TUNNEL+PFS+DONTREKEY+OPPORTUNISTIC # +failureDROP+lKOD+rKOD # # PLUTO_NEXT_HOP # is the next hop to which packets bound for the peer # must be sent. # # PLUTO_INTERFACE # is the name of the real interface used by encrypted traffic and IKE traffic # # PLUTO_ME # is the IP address of our host. # # PLUTO_METRIC # is the metric to set for the route # # PLUTO_MTU # is the mtu to set for the route # # PLUTO_MY_CLIENT # is the IP address / count of our client subnet. If # the client is just the host, this will be the # host's own IP address / mask (where max is 32 for # IPv4 and 128 for IPv6). # # PLUTO_MY_CLIENT_NET # is the IP address of our client net. If the client # is just the host, this will be the host's own IP # address. # # PLUTO_MY_CLIENT_MASK # is the mask for our client net. If the client is # just the host, this will be 255.255.255.255. # # PLUTO_MY_SOURCEIP # if non-empty, then the source address for the route will be # set to this IP address. # # PLUTO_MY_PROTOCOL # is the protocol for this connection. Useful for # firewalling. # # PLUTO_MY_PORT # is the port. Useful for firewalling. # # PLUTO_PEER # is the IP address of our peer. # # PLUTO_PEER_CLIENT # is the IP address / count of the peer's client subnet. # If the client is just the peer, this will be # the peer's own IP address / mask (where max is 32 # for IPv4 and 128 for IPv6). # # PLUTO_PEER_CLIENT_NET # is the IP address of the peer's client net. If the # client is just the peer, this will be the peer's # own IP address. # # PLUTO_PEER_CLIENT_MASK # is the mask for the peer's client net. If the # client is just the peer, this will be # 255.255.255.255. # # PLUTO_PEER_PROTOCOL # is the protocol set for remote end with port # selector. # # PLUTO_PEER_PORT # is the peer's port. Useful for firewalling. # # PLUTO_CFG_CLIENT=0|1 # is MODECFG or IKEv2 Config client. # # PLUTO_CFG_SERVER=0|1 # is MODECFG or IKEv2 Config server. # # PLUTO_CONNECTION_TYPE # # PLUTO_CONN_ADDRFAMILY # is the family type, "ipv4" or "ipv6" # # PLUTO_PROTO_STACK # is the local IPsec kernel stack used, eg NETKEY, NOSTACK # # PLUTO_IS_PEER_CISCO=0|1 # remote server type is cisco. Add support for cisco extensions # when used with xauth. # # PLUTO_NM_CONFIGURED=0|1 # is NetworkManager used for resolv.conf update # # PLUTO_SA_REQID # When using KAME or XFRM/NETKEY, the IPsec SA reqid base value. # ESP/AH out is base, ESP/AH in = base + 1 # IPCOMP is base + 2 plus for inbound + 1 # # PLUTO_SA_TYPE # The type of IPsec SA (ESP or AH) # # PLUTO_USERNAME # The username (XAUTH or GSSAPI) that was authenticated (if any) # for this SA # # PLUTO_VIRT_INTERFACE # is the name of ipsec interface used by clear traffic in/out # # # XAUTH_FAILED # If xauthfail=soft this will be set to 1 if XAUTH authentication # failed. If xauthfail=hard, the updown scripts never run. # # CONNMARK # If mark= is set on the connection, this variable will be # set with the value. It can be used for iptables or VTI. # # VTI_IFAC=iface # Name of VTI interface to create # # VTI_ROUTING=yes|no # Whether or not to perform ip rule and ip route commands # covering the IPsec SA address ranges to route those packets # into the VTI_IFACE interface. This should be enabled unless # the IPsec SA covers 0.0.0.0/0 <-> 0.0.0.0/0 # # VTI_SHARED=yes|no # Whether or not more conns (or instances) share a VTI device. # If not shared, the VTI device is deleted when tunnel goes down. # # SPI_IN / SPI_OUT # The inbound and outbound SPI's of the connection. # rpm based systems if [ -f /etc/sysconfig/pluto_updown ]; then . /etc/sysconfig/pluto_updown # deb based systems elif [ -f /etc/default/pluto_updown ]; then . /etc/default/pluto_updown fi BACKUP_RESOLV_CONF=/run/pluto/libreswan-resolv-conf-backup ETC_RESOLV_CONF=/etc/resolv.conf case "${PLUTO_CONN_ADDRFAMILY}" in ipv4) FAMILY=4 MAX_CIDR=32 SCOPE=50 # Use scope 50 to verify ip was added by addsource() ;; ipv6) FAMILY=6 MAX_CIDR=128 SCOPE=global ;; *) echo "unknown address family \"${PLUTO_CONN_ADDRFAMILY}\"" >&2 exit 1 ;; esac export FAMILY MAX_CIDR SCOPE # 2022-09-03 - mbaudier : Hack when having an IPv6 subnet export CLIENT_FAMILY=6 export CLIENT_MAX_CIDR=128 # Ignore parameter custom if [ "${1}" = "custom" ]; then shift fi while [ $# -gt 0 ]; do case ${1} in --route) case ${2} in [Yy]*) ROUTE=yes PROXY_ARP_ROUTE=no ;; *) ROUTE= PROXY_ARP_ROUTE= ;; esac shift; shift ;; --iproute) IPRARGS="${2}" shift; shift ;; *) echo "$0: Unknown argument \"${1}\"" >&2 exit 1 ;; esac done # utility functions for route manipulation # Meddling with this stuff should not be necessary and requires great care. uproute() { doproxyarp add doroute replace } downroute() { doroute del doproxyarp delete } downrule() { if [ -n "${PLUTO_MY_SOURCEIP}" -a 0${PLUTO_IS_PEER_CISCO} -eq 1 ]; then doroute del fi } updateresolvconf() { local domain local nameserver local new_nameserver local new_resolv_conf local new_search local orig_domain local orig_nameserver local rc rc=0 if [ 0${PLUTO_CFG_CLIENT} -eq 0 ]; then return ${rc} fi if [ -n "$(pidof unbound)" -a \ -n "${PLUTO_PEER_DNS_INFO}" -a \ -n "${PLUTO_PEER_DOMAIN_INFO}" ] then for domain in ${PLUTO_PEER_DOMAIN_INFO}; do echo "updating local nameserver for ${domain} with ${PLUTO_PEER_DNS_INFO}" unbound-control forward_add ${domain} \ ${PLUTO_PEER_DNS_INFO} unbound-control flush_zone ${domain} unbound-control flush_requestlist done rc=$? elif [ 0${PLUTO_NM_CONFIGURED} -eq 0 -a \ -n "${PLUTO_PEER_DNS_INFO}" ] then echo "updating resolvconf" if [ ! -e "${ETC_RESOLV_CONF}" ]; then echo "resolv.conf does not exist, so doing nothing" return 0 fi if [ -e "${BACKUP_RESOLV_CONF}" ]; then if grep -q Libreswan "${ETC_RESOLV_CONF}"; then echo "Current resolv.conf is generated by Libreswan, and backup resolv.conf already exists, so doing nothing" return 0 else echo "backup resolv.conf exists, but current resolv.conf is not generated by Libreswan" fi fi rm -f -- "${BACKUP_RESOLV_CONF}" cp -- "${ETC_RESOLV_CONF}" "${BACKUP_RESOLV_CONF}" new_resolv_conf="# Generated by Libreswan (IPsec)" orig_domain="$(grep ^domain "${ETC_RESOLV_CONF}" 2>/dev/null | \ awk '{ print $2 }')" orig_search=$(grep ^search "${ETC_RESOLV_CONF}" 2>/dev/null | \ sed 's/^search[[:space:]]\+//;s/[[:space:]]*\#.*//') if [ -n "${orig_domain}" ]; then new_resolv_conf="${new_resolv_conf} domain ${orig_domain}" fi if [ -n "${orig_search}" ]; then new_search="${orig_search}" elif [ -n "${orig_domain}" ]; then new_search="${orig_domain}" fi if [ -n "${PLUTO_PEER_DOMAIN_INFO}" ]; then if [ -n "${new_search}" ]; then new_search=$(echo $(echo "${new_search} ${PLUTO_PEER_DOMAIN_INFO}" | tr [:space:] '\n' | awk '!a[$0]++')) else new_search="${PLUTO_PEER_DOMAIN_INFO}" fi fi if [ -n "${new_search}" ]; then new_resolv_conf="${new_resolv_conf} search ${new_search}" fi orig_nameserver=$(grep -m 1 ^nameserver "${ETC_RESOLV_CONF}" | \ sed 's/^nameserver[[:space:]]\+//;s/[[:space:]]*\#.*//') if [ -n "${orig_nameserver}" ]; then new_nameserver=$(echo $(echo "${PLUTO_PEER_DNS_INFO} ${orig_nameserver}" | tr [:space:] '\n' | awk '!a[$0]++')) else new_nameserver="${PLUTO_PEER_DNS_INFO}" fi for nameserver in ${new_nameserver}; do new_resolv_conf="${new_resolv_conf} nameserver ${nameserver}" done echo "${new_resolv_conf}" > "${ETC_RESOLV_CONF}" rc=$? fi return ${rc} } restoreresolvconf() { local domain local rc rc=0 if [ 0${PLUTO_CFG_CLIENT} -eq 0 ]; then return ${rc} fi if [ -n "$(pidof unbound)" -a \ -n "${PLUTO_PEER_DNS_INFO}" -a \ -n "${PLUTO_PEER_DOMAIN_INFO}" ] then for domain in ${PLUTO_PEER_DOMAIN_INFO}; do echo "flushing local nameserver of ${domain}" unbound-control forward_remove ${domain} unbound-control flush_zone ${domain} unbound-control flush_requestlist done rc=$? elif [ 0${PLUTO_NM_CONFIGURED} -eq 0 ]; then # We only restore if current resolv.conf is made by us. if grep -q Libreswan "${ETC_RESOLV_CONF}" 2>/dev/null; then # And if there is a backup... if [ -e "${BACKUP_RESOLV_CONF}" ]; then echo "restoring resolvconf" else return 0 fi cp -- "${BACKUP_RESOLV_CONF}" "${ETC_RESOLV_CONF}" fi rm -f -- "${BACKUP_RESOLV_CONF}" rc=0 fi return ${rc} } notifyNM() { # This will be called whenever a connection is established or # fails to establish (either phase 1, xauth phase, or phase 2) # or whenever an already established connection is being terminated. # This will send a signal to NetworkManager over dbus so that NM # can keep track of the coonnections. if [ 0${PLUTO_NM_CONFIGURED} -eq 1 ]; then echo "sending $1 signal to NetworkManager" libreswan_reason=$1 export libreswan_reason export PLUTO_PEER_DOMAIN_INFO export PLUTO_PEER_DNS_INFO export PLUTO_PEER_BANNER export PLUTO_MY_SOURCEIP export PLUTO_PEER [ -x /usr/libexec/nm-libreswan-service-helper ] && \ /usr/libexec/nm-libreswan-service-helper fi return 0 } addsource() { local interface local st interface=lo st=0 if [ -z "${PLUTO_MY_SOURCEIP}" ]; then return ${st} fi # check if given sourceip is local and add as alias if not if ! ip -${CLIENT_FAMILY} -o route get ${PLUTO_MY_SOURCEIP} | grep -q ^local; then if [ -n "${VTI_IFACE}" -a "${VTI_ROUTING}" = yes ]; then interface="${VTI_IFACE}" elif [ -n "${PLUTO_XFRMI_ROUTE}" ]; then interface=${PLUTO_VIRT_INTERFACE} fi it="ip addr add ${PLUTO_MY_SOURCEIP}/${CLIENT_MAX_CIDR} dev ${interface} scope ${SCOPE}" oops="$(eval ${it} 2>&1)" st=$? if [ -z "${oops}" -a ${st} -ne 0 ]; then oops="silent error, exit status ${st}" fi case "${oops}" in 'RTNETLINK answers: File exists'*) # should not happen, but ... ignore if the # address was already assigned on interface oops="" st=0 ;; esac if [ -n "${oops}" -o ${st} -ne 0 ]; then echo "$0: addsource \"${it}\" failed (${oops})" >&2 fi fi return ${st} } delsource() { local interface local oops local st interface=lo st=0 if [ -z "${PLUTO_MY_SOURCEIP}" ]; then return ${st} fi # Remove source ip if it's not used any more. if [ -z "$(ip -${CLIENT_FAMILY} -o route list src ${PLUTO_MY_SOURCEIP})" ]; then if [ -n "${VTI_IFACE}" -a "${VTI_ROUTING}" = yes ]; then interface="${VTI_IFACE}" elif [ -n "${PLUTO_XFRMI_ROUTE}" ]; then interface=${PLUTO_VIRT_INTERFACE} fi # If there is no ip we just return if ! ip -${FAMILY} -o addr list dev ${interface} scope ${SCOPE} | \ grep -q ${PLUTO_MY_SOURCEIP}/${CLIENT_MAX_CIDR} then return ${st} fi if [ -n "${PLUTO_MOBIKE_EVENT}" ] ; then return ${st} fi it="ip -${CLIENT_FAMILY} addr del ${PLUTO_MY_SOURCEIP}/${CLIENT_MAX_CIDR} dev ${interface}" oops="$(eval ${it} 2>&1)" st=$? if [ -z "${oops}" -a ${st} -ne 0 ]; then oops="silent error, exit status ${st}" fi case "${oops}" in 'RTNETLINK answers: File exists'*) # should not happen, but ... ignore if the # address was already assigned on interface oops="" st=0 ;; 'RTNETLINK answers: Cannot assign'*) # Address is not there to remove or is there with different # netmask and in that case we must not remove it so we ignore # the error. oops="" st=0 ;; esac if [ -n "${oops}" -o ${st} -ne 0 ]; then echo "$0: delsource \"${it}\" failed (${oops})" >&2 fi fi return ${st} } doproxyarp() { local cmd local iface cmd=${1} # Check if client has a single ip only client net if [ ${PLUTO_PEER_CLIENT#*/} = ${MAX_CIDR} ]; then # Skip OE special connections and direct host-host connections if [ "${PLUTO_PEER_CLIENT_NET}" = "0.0.0.0" -o \ "${PLUTO_PEER_CLIENT_NET}" = "::" -o \ "${PLUTO_PEER_CLIENT_NET}" = "${PLUTO_PEER}" -o \ "${PLUTO_MY_CLIENT_NET}" = "${PLUTO_ME}" ] then return 0 fi # check if client is routeable if ip -${FAMILY} -o route get ${PLUTO_PEER_CLIENT_NET} 2>/dev/null | \ grep -E -q -s -v " via |^local" then iface=$(ip -${FAMILY} -o route get ${PLUTO_PEER_CLIENT_NET} 2>/dev/null | \ awk '{print $3}') if [ -r /sys/class/net/${iface}/address ]; then macaddr=$(cat /sys/class/net/${iface}/address) fi # add/remove arp entry for the client on ethernet devices only if [ -n "${macaddr}" ]; then if [ "${cmd}" = "add" ]; then ip -${FAMILY} neigh add proxy ${PLUTO_PEER_CLIENT_NET} dev ${iface} \ lladdr ${macaddr} nud permanent # Force routing, required for proxyarp to work PROXY_ARP_ROUTE=yes export PROXY_ARP_ROUTE else ip -${FAMILY} neigh del proxy ${PLUTO_PEER_CLIENT_NET} dev ${iface} fi fi fi fi } do_ip() { local cmd="$1" oops="$(eval ${cmd} 2>&1)" st=$? if [ -z "${oops}" -a ${st} -ne 0 ]; then oops="silent error, exit status ${st}" fi case "${oops}" in 'RTNETLINK answers: No such process'*) # should not happen, but ... ignore if the # route was already removed oops="" st=0 ;; esac if [ -n "${oops}" -a ${st} -ne 0 ]; then echo "$0: doroute \"${cmd}\" failed (${oops})" >&2 fi return ${st} } doroute() { local cmd local esp_nexthop local esp_peer_interface local espipro local ipru local route_table local oops local parms local parms2 local st local xfrmi_route local xfrmi_rule cmd=${1} route_table=50 st=0 xfrmi_route="${PLUTO_XFRMI_ROUTE}" if [ ${cmd} != del ]; then oops="$(ip -${FAMILY} route get ${PLUTO_PEER_CLIENT_NET} 2>&1)" case "${oops}" in 'RTNETLINK answers: No route to host'*) if [ -z "${PLUTO_XFRMI_ROUTE}" ]; then ROUTE=yes # Routing is mandatory for IPsec fi ;; esac fi if [ -n "${PLUTO_XFRMI_FWMARK}" ]; then xfrmi_rule=yes # we have to add "ip rules" and "ip route table" ROUTE=no # xfrmi_route will add the route fi # skip routing if it's not enabled or necessary if [ -z "${PLUTO_MY_SOURCEIP}" -a \ -z "${PLUTO_MTU}" -a \ "${PROXY_ARP_ROUTE}" != yes -a \ "${cmd}" != "del" ] then PROXY_ARP_ROUTE=no fi if [ -n "${PLUTO_MY_SOURCEIP}" -o -n "${PLUTO_MTU}" ]; then ROUTE=yes fi if [ "${PLUTO_PEER_CLIENT}" = "${PLUTO_MY_CLIENT}" -a \ "${PLUTO_XFRMI_ROUTE}" = yes ] then xfrmi_route="samesubnets"; echo "leftsubet == rightsubnet = ${PLUTO_PEER_CLIENT} cannot add route" fi parms="${PLUTO_PEER_CLIENT}" parms2=${IPRARGS} # nexthop is not needed on ppp interfaces. unset it to make cases # work, where left is set but no leftnexthop (e.g. left=%defaultroute) if ip link show "${PLUTO_INTERFACE%:*}" | grep -q POINTOPOINT; then POINTPOINT=yes fi # use nexthop if nexthop is not %direct and POINTPOINT is not set if [ "${PLUTO_NEXT_HOP}" != "${PLUTO_PEER}" -a -z "${POINTPOINT}" ]; then # XFRM interface needs no nexthop if [ -z "${PLUTO_XFRMI_ROUTE}" ]; then parms2="via ${PLUTO_NEXT_HOP}" fi esp_nexthop="via ${PLUTO_NEXT_HOP} " fi # route via proper interface according to routing table if [ "${cmd}" = "del" ]; then case "${PLUTO_PEER_CLIENT}" in "0.0.0.0/0") # in case of default route we use half routes peer_interface=$(ip -${FAMILY} -o route list exact 0.0.0.0/1 | \ sed "s/^.*dev \([^ ]*\) .*/\1/") ;; "::/0") # in case of default route we use half routes peer_interface=$(ip -${FAMILY} -o route list exact 2000::/3 | \ sed "s/^.*dev \([^ ]*\) .*/\1/") ;; *) peer_interface=$(ip -${CLIENT_FAMILY} -o route get ${PLUTO_PEER_CLIENT_NET} | \ sed "s/^.*dev \([^ ]*\) .*/\1/") ;; esac else peer_interface=$(ip -o route get ${PLUTO_NEXT_HOP} | \ sed "s/^.*dev \([^ ]*\) .*/\1/") fi esp_peer_interface=$(ip -${FAMILY} -o route get ${PLUTO_NEXT_HOP} \ from ${PLUTO_ME} | sed "s/^.*\(dev [^ ]*\) .*/\1/") if [ -z "${esp_peer_interface}" ]; then esp_peer_interface="dev ${PLUTO_INTERFACE}" fi if [ -z "${peer_interface}" ]; then peer_interface=${PLUTO_INTERFACE} fi if [ "${PLUTO_XFRMI_ROUTE}" = "yes" ]; then peer_interface=${PLUTO_VIRT_INTERFACE} fi if [ -n "${VTI_IFACE}" ]; then addsource peer_interface="${VTI_IFACE}" fi parms2="${parms2}${PLUTO_MTU:+ mtu ${PLUTO_MTU}}" parms2="${parms2}${PLUTO_METRIC:+ metric ${PLUTO_METRIC}} ${IPROUTEARGS}" parms2="${parms2} dev ${peer_interface%:*}" # make sure we have sourceip locally in this machine if [ "${cmd}" = "replace" -a -n "${PLUTO_MY_SOURCEIP}" ]; then addsource # use sourceip as route default source parms2="${parms2} src ${PLUTO_MY_SOURCEIP}" fi case "${PLUTO_PEER_CLIENT}" in "0.0.0.0/0") # need to provide route that eclipses default, without # replacing it. it="ip -${FAMILY} route ${cmd} 0.0.0.0/1 ${parms2} && \ ip -${FAMILY} route ${cmd} 128.0.0.0/1 ${parms2}" ;; "::/0") # need to provide route that eclipses default, without # replacing it. it="ip -${FAMILY} route ${cmd} 2000::/3 ${parms2}" ;; *) it="ip -${CLIENT_FAMILY} route ${cmd} ${parms} ${parms2}" ;; esac if [ "${ROUTE}" = yes -o \ "${xfrmi_route}" = yes -o \ "${PROXY_ARP_ROUTE}" = yes ] then do_ip "${it}" st=$? if [ ${st} -ne 0 ]; then return ${st} fi fi if [ "${xfrmi_rule}" = "yes" ]; then espipro="ip -${FAMILY} route ${cmd} ${PLUTO_PEER}/${MAX_CIDR} ${esp_nexthop} ${esp_peer_interface%:*} table ${route_table}" do_ip "${espipro}" st=$? if [ ${st} -ne 0 ]; then return ${st} fi iprulecmd="${cmd}" if [ "${cmd}" = "replace" ]; then iprulecmd="add" fi ipru="ip -${FAMILY} rule ${iprulecmd} prio 100 to ${parms}" ipru="${ipru} fwmark ${PLUTO_XFRMI_FWMARK} lookup ${route_table}" do_ip "${ipru}" st=$? if [ ${st} -ne 0 ]; then return ${st} fi fi return 0 } # TODO: We need to specify CIDR mask but our _MASK variables are in old school format # TODO: Exclude udp 4500 traffic addnflog() { if [ -n "${NFLOG}" ]; then iptables -I OUTPUT -m policy --dir out --pol ipsec \ -s ${PLUTO_MY_CLIENT} -d ${PLUTO_PEER_CLIENT} \ -j NFLOG --nflog-group ${NFLOG} --nflog-prefix ${PLUTO_CONNECTION} iptables -I INPUT -m policy --dir in --pol ipsec \ -s ${PLUTO_PEER_CLIENT} -d ${PLUTO_MY_CLIENT} \ -j NFLOG --nflog-group ${NFLOG} --nflog-prefix ${PLUTO_CONNECTION} fi } delnflog() { if [ -n "${NFLOG}" ]; then iptables -D OUTPUT -m policy --dir out --pol ipsec \ -s ${PLUTO_MY_CLIENT} -d ${PLUTO_PEER_CLIENT} \ -j NFLOG --nflog-group ${NFLOG} --nflog-prefix ${PLUTO_CONNECTION} iptables -D INPUT -m policy --dir in --pol ipsec \ -s ${PLUTO_PEER_CLIENT} -d ${PLUTO_MY_CLIENT} \ -j NFLOG --nflog-group ${NFLOG} --nflog-prefix ${PLUTO_CONNECTION} fi } addvtiiface() { if [ -n "${VTI_IFACE}" ]; then if [ -z "${CONNMARK_IN}" -o -z "${CONNMARK_OUT}" ]; then echo "vti-interface option ignored because no mark was configured" else if [ ! -d "/proc/sys/net/ipv4/conf/${VTI_IFACE}" ]; then # echo "creating vti interface" vtipeer="${PLUTO_PEER}" if [ "${PLUTO_CONN_KIND}" = CK_INSTANCE -o "${VTI_SHARED}" = "yes" ]; then vtipeer="0.0.0.0" fi ip tunnel add ${VTI_IFACE} mode vti local ${PLUTO_ME} \ remote ${vtipeer} okey ${CONNMARK_OUT%/*} \ ikey ${CONNMARK_IN%/*} sysctl -w net.ipv4.conf.${VTI_IFACE}.disable_policy=1 sysctl -w net.ipv4.conf.${VTI_IFACE}.rp_filter=0 sysctl -w net.ipv4.conf.${VTI_IFACE}.forwarding=1 if [ -n "${VTI_IP}" ]; then ip addr add ${VTI_IP} dev ${VTI_IFACE} fi ip link set ${VTI_IFACE} up else # check there was no conflict if we are sharing - might be sensitive to /sbin/ip differences if [ "${VTI_SHARED}" = yes ]; then #test: ip/ip remote 3.4.5.6 local 1.2.3.4 ttl inherit key 5 cur="$(ip tun show ${VTI_IFACE})" new="${VTI_IFACE}: ip/ip remote any local ${PLUTO_ME} ttl inherit key ${CONNMARK_OUT%/*}" if [ "${cur}" != "${new}" ]; then echo "vti interface \"${VTI_IFACE}\" already exists with conflicting setting" echo "existing: ${cur}" echo "wanted : ${new}" else # temp debug echo "vti interface already exists with identical parameters, OK" fi else echo "vti interface \"${VTI_IFACE}\" already exists with conflicting setting (perhaps need vti-sharing=yes ?" fi fi fi fi } addvti() { if [ -n "${VTI_IFACE}" ]; then if [ -z "${CONNMARK_IN}" -o -z "${CONNMARK_OUT}" ]; then echo "vti-interface option ignored because no mark was configured" else if [ "${VTI_ROUTING}" = yes ]; then # Tuomo should improve this with using ${PLUTO_MY_CLIENT_NET} # echo "setting up vti routing" r=add ip route list | grep -q "${PLUTO_PEER_CLIENT%/*}" && r=change if [ "${r}" = change ]; then # resolve LAN conflict by forcing host route for default gw gw="$(ip ro li | grep ^default | awk '{ print $3;}')" gwdev="$(ip ro li | grep ^default | awk '{ print $5;}')" # echo "ip route add ${gw} dev ${gwdev}" ip route add ${gw} dev ${gwdev} >/dev/null ||: fi srcip="" if [ -n "${PLUTO_MY_SOURCEIP}" ]; then srcip=" src ${PLUTO_MY_SOURCEIP}" fi # echo "ip route ${r} ${PLUTO_PEER_CLIENT} dev ${VTI_IFACE} ${srcip}" ip route ${r} ${PLUTO_PEER_CLIENT} dev ${VTI_IFACE} ${srcip} echo "done ip route" fi fi fi } delvti() { if [ -n "${VTI_IFACE}" -a -d /proc/sys/net/ipv4/conf/${VTI_IFACE} ]; then if [ "${VTI_ROUTING}" = yes ]; then ip route del ${PLUTO_PEER_CLIENT} dev ${VTI_IFACE} \ src ${PLUTO_MY_SOURCEIP} ||: fi # TODO: we can't delete vti interface because we don't have proper reference # counting. #if [ "${VTI_SHARED}" = no -a "${PLUTO_CONN_KIND}" != CK_INSTANCE ]; then # ip tun del ${VTI_IFACE} ||: #fi fi } # Client Address Translation CAT addcat() { if [ -n "${CAT}" ] && [ "${PLUTO_MY_CLIENT_NET}" != "0.0.0.0" ] ; then iptables -t nat -I POSTROUTING -m policy --dir out --pol ipsec \ -d ${PLUTO_PEER_CLIENT} -j SNAT --to-source ${PLUTO_MY_CLIENT_NET} iptables -t nat -I PREROUTING -m policy --dir in --pol ipsec \ -d ${PLUTO_MY_CLIENT_NET} -s ${PLUTO_PEER_CLIENT} \ -j DNAT --to-destination ${PLUTO_ME} fi } delcat() { if [ -n "${CAT}" ]; then iptables -t nat -D PREROUTING -m policy --dir in --pol ipsec \ -d ${PLUTO_MY_CLIENT_NET} -s ${PLUTO_PEER_CLIENT} \ -j DNAT --to-destination ${PLUTO_ME} iptables -t nat -D POSTROUTING -m policy --dir out --pol ipsec \ -d ${PLUTO_PEER_CLIENT} -j SNAT --to-source ${PLUTO_MY_CLIENT_NET} fi } # the big choice case "${PLUTO_VERB}" in prepare-host|prepare-client) addvtiiface ;; route-host|route-client) # connection to me or my client subnet being routed addvti uproute addnflog ;; unroute-host|unroute-client) # connection to me or my client subnet being unrouted downroute delsource ;; up-host) # connection to me coming up # If you are doing a custom version, firewall commands go here. ;; down-host) # connection to me going down downrule delnflog delcat delvti # If you are doing a custom version, firewall commands go here. ;; up-client) # connection to my client subnet coming up addvtiiface updateresolvconf addcat addsource notifyNM connect addvti # If you are doing a custom version, firewall commands go here. ;; down-client) # connection to my client subnet going down downrule delnflog delcat delvti restoreresolvconf notifyNM disconnect # If you are doing a custom version, firewall commands go here. ;; # # IPv6 # prepare-host-v6|prepare-client-v6) # prepare client for connection ;; route-host-v6|route-client-v6) # connection to me or my client subnet being routed uproute ;; unroute-host-v6|unroute-client-v6) # connection to me or my client subnet being unrouted downroute delsource ;; up-host-v6) # connection to me coming up # If you are doing a custom version, firewall commands go here. ;; down-host-v6) # connection to me going down # If you are doing a custom version, firewall commands go here. ;; up-client-v6) # connection to my client subnet coming up addsource updateresolvconf notifyNM connect # If you are doing a custom version, firewall commands go here. ;; down-client-v6) # connection to my client subnet going down restoreresolvconf notifyNM disconnect # If you are doing a custom version, firewall commands go here. ;; *) echo "$0: unknown verb \"${PLUTO_VERB}\" or parameter \"${1}\"" >&2 exit 1 ;; esac