#!/bin/bash # postinst script for #PACKAGE# # # see: dh_installdeb(1) set -xe # summary of how this script can be called: # * `configure' # * `abort-upgrade' # * `abort-remove' `in-favour' # # * `abort-remove' # * `abort-deconfigure' `in-favour' # `removing' # # for details, see https://www.debian.org/doc/debian-policy/ or # the debian-policy package case "$1" in configure) ## START gather all the info from the box and generate the variabels IFCONFIG="etc/network/interfaces" UDEVCONFIG="etc/udev/rules.d/70-persistent-net.rules" FRRCONFIG="etc/frr/frr.conf.wit" IPSECCONFIG="etc/ipsec.conf.wit" IPSECSECRETS="etc/ipsec.secrets" SWANCTLCONFIG="etc/swanctl/conf.d/wit-swanctl.conf" SYSCTLTWEAKS="etc/sysctl.d/10-frr.conf" DOMAINNAME=$(hostname -d) dig_txt() { TMPDIG=$(dig txt +short $1) [ -z ${TMPDIG} ] && exit 2 TMPDIG=${TMPDIG//\//\\\/} TMPDIG=${TMPDIG//\"/} #" fix the god damn syntax highlighter echo ${TMPDIG} } dig_a() { TMPDIG=$(dig a +short $1) [ -z ${TMPDIG} ] && exit 2 echo ${TMPDIG} } dig_aaaa() { TMPDIG=$(dig aaaa +short $1) [ -z ${TMPDIG} ] && exit 2 echo ${TMPDIG} } LOOPBACKv4=$(dig_a ${HOSTNAME}) LOOPBACKv6=$(dig_aaaa ${HOSTNAME}) NODEASN=$(dig_txt asn.${HOSTNAME}) ## END variables ## START nic config compile # write loopback config cat <<-EOF >>$IFCONFIG auto lo iface lo inet loopback iface lo inet static address ${LOOPBACKv4}/32 iface lo inet6 static address ${LOOPBACKv6}/128 EOF BASTIONPUBLICIP=$(dig_a public.${HOSTNAME}) || true if [[ ! -z $BASTIONPUBLICIP ]]; then cat <<-EOF >>$IFCONFIG iface lo inet static address ${BASTIONPUBLICIP}/32 EOF fi # gathering defined interfaces for if in mgmt mgmtgw ipmigw feth up ibgp gre customer; do for i in {1..4}; do #### for now we support/count only to 4 interfaces of each type, we can just raise this to whatever number we want (exeption mgmt) ifname=${if}${i} ifalias=$(dig_txt name.${ifname}.${HOSTNAME}) || true ## still thinking how to do this cleaner if [[ $ifname = gre? ]] && [[ ! -z $ifalias ]]; then ifmtu=$(dig_txt mtu.${ifname}.${HOSTNAME}) local=$(dig_txt local.${ifname}.${HOSTNAME}) localasn=$(dig_txt localasn.${ifname}.${HOSTNAME}) remote=$(dig_txt remote.${ifname}.${HOSTNAME}) ## for the GRE tunnel to not have to deal with ibgp/full-mesh or reflectors prepending a private AS FRR_GRE_ASN="$localasn" ## build FRR interface config to enable ND adv for ipv6 unmanaged FRR_IFS="${FRR_IFS}interface $ifname\n" FRR_IFS="${FRR_IFS} description $ifalias\n" FRR_IFS="${FRR_IFS} ipv6 nd ra-interval 10\n" FRR_IFS="${FRR_IFS} no ipv6 nd suppress-ra\n!\n" ## build FRR neightbor interfaces FRR_EDGE_NEIGH=" !!! neighbor $ifname interface peer-group GRE\n$FRR_EDGE_NEIGH" ## build regular linux network interface config cat <<-EOF >>$IFCONFIG auto $ifname iface $ifname inet manual ## $ifalias pre-up ip tunnel add $ifname mode gre local $local remote $remote down ip tunnel del $ifname mtu $ifmtu EOF fi ## blow we deal with real physical interfaces ## it is crucial that this `ifmac` block is above the rest, since if no mac is returned it will skip the loop and prevent the package install to fail if [[ $ifname = mgmt1 ]] || [[ $ifname = mgmtgw1 ]] || [[ $ifname = ipmigw1 ]] ## we only support a single interface of these types and they are handled slightly differently in DNS then ifmac=$(dig_txt mac.${if}.${HOSTNAME}) || continue ## at this point skip the rest of the loop for interfaces that do not have a mac defined (those are basically not configured) else ifmac=$(dig_txt mac.${ifname}.${HOSTNAME}) || continue ## at this point skip the rest of the loop for interfaces that do not have a mac defined fi echo 'SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="'${ifmac}'", ATTR{type}=="1", NAME="'${ifname}'"' >>$UDEVCONFIG if [[ $ifname = up? ]] || [[ $ifname = customer? ]]; then ipv4=$(dig_txt ipv4.$ifname.${HOSTNAME}) ipv6=$(dig_txt ipv6.$ifname.${HOSTNAME}) peerv4=$(dig_txt peerv4.$ifname.${HOSTNAME}) || true ## we dont know if we will always have both available peerv6=$(dig_txt peerv6.$ifname.${HOSTNAME}) || true ## we dont know if we will always have both available if [[ $ifname = up? ]]; then [ -z $peerv4 ] || FRR_EDGE_NEIGH=" !!! neighbor $peerv4 peer-group eBGPv4\n$FRR_EDGE_NEIGH" [ -z $peerv6 ] || FRR_EDGE_NEIGH=" !!! neighbor $peerv6 peer-group eBGPv6\n$FRR_EDGE_NEIGH" elif [[ $ifname = customer? ]]; then [ -z $peerv4 ] || FRR_EDGE_NEIGH=" !!! neighbor $peerv4 peer-group CUSTOMERv4\n$FRR_EDGE_NEIGH" [ -z $peerv6 ] || FRR_EDGE_NEIGH=" !!! neighbor $peerv6 peer-group CUSTOMERv6\n$FRR_EDGE_NEIGH" fi cat <<-EOF >>$IFCONFIG auto $ifname iface $ifname inet static address ${ipv4/\\/} mtu 9000 iface $ifname inet6 static address ${ipv6/\\/} dad-attempts 0 EOF fi if [[ $ifname = ibgp? ]]; then ## build FRR interface config to enable ND adv for ipv6 unmanaged FRR_IFS="${FRR_IFS}interface $ifname\n" FRR_IFS="${FRR_IFS} ipv6 nd ra-interval 10\n" FRR_IFS="${FRR_IFS} no ipv6 nd suppress-ra\n!\n" ## build FRR neightbor interfaces FRR_EDGE_NEIGH=" !!! neighbor $ifname interface peer-group iBGP\n$FRR_EDGE_NEIGH" cat <<-EOF >>$IFCONFIG auto $ifname iface $ifname inet manual mtu 9000 EOF fi if [[ $ifname = feth? ]]; then cat <<-EOF >>$IFCONFIG auto $ifname iface $ifname inet manual mtu 9000 EOF fi if [[ $ifname = mgmt1 ]]; then ## only 1 mgmt interface supported for now cat <<-EOF >>$IFCONFIG auto $ifname iface $ifname inet6 auto iface $ifname inet dhcp pre-up /bin/ip link add mgmt type vrf table mgmt pre-up /bin/ip link set up dev mgmt pre-up /bin/ip link set master mgmt dev $ifname post-down /bin/ip link del dev mgmt EOF fi if [[ $ifname = mgmtgw1 ]] || [[ $ifname = ipmigw1 ]]; then ## only 1 mgmt interface supported for now ipv4=$(dig_txt ipv4.$if.${HOSTNAME}) ipv6=$(dig_txt ipv6.$if.${HOSTNAME}) cat <<-EOF >>$IFCONFIG auto ${ifname} iface ${ifname} inet static address ${ipv4/\\/} iface ${ifname} inet6 static address ${ipv6/\\/} EOF FRR_IFS="${FRR_IFS}interface ${ifname}\n" FRR_IFS="${FRR_IFS} description $ifalias\n" FRR_IFS="${FRR_IFS} ipv6 nd other-config-flag\n" FRR_IFS="${FRR_IFS} ipv6 nd prefix ${ipv6}\n" FRR_IFS="${FRR_IFS} ipv6 nd ra-interval 10\n" FRR_IFS="${FRR_IFS} no ipv6 nd suppress-ra\n!\n\n" [[ $ifname = mgmtgw1 ]] && listnum=10 [[ $ifname = ipmigw1 ]] && listnum=20 FRR_IFS="${FRR_IFS}ipv6 prefix-list MGMT seq $listnum permit ${ipv6}\n" fi done done ## STOP nic config compile ## START compiling frr and ipsec dynamic config blocks ## compile public IP space prefix lists, this is what's going to be advertised out the upstream provider i=1 while true; do TEMP="$(dig_txt $i.ipv4.public.prefixlist.$DOMAINNAME)" || break TEMPAGGS=" !!! aggregate-address ${TEMP}\n" FRR_IPV4_EDGE_SUMMARIES_AGGREGATS="${FRR_IPV4_EDGE_SUMMARIES_AGGREGATS}${TEMPAGGS}" TEMPSUM="!!! ip prefix-list WITv4-SUMMARIES seq $((i*5)) permit ${TEMP}\n" FRR_IPV4_EDGE_SUMMARIES_PFLIST="${FRR_IPV4_EDGE_SUMMARIES_PFLIST}${TEMPSUM}" let i+=1 done i=1 while true; do TEMP="$(dig_txt $i.ipv6.public.prefixlist.$DOMAINNAME)" || break TEMPAGGS=" !!! aggregate-address ${TEMP}\n" FRR_IPV6_EDGE_SUMMARIES_AGGREGATS="${FRR_IPV6_EDGE_SUMMARIES_AGGREGATS}${TEMPAGGS}" TEMPSUM="!!! ipv6 prefix-list WITv6-SUMMARIES seq $((i*5)) permit ${TEMP}\n" FRR_IPV6_EDGE_SUMMARIES_PFLIST="${FRR_IPV6_EDGE_SUMMARIES_PFLIST}${TEMPSUM}" let i+=1 done ## compile customer IP blocks that we accept. this in theory should be a combination of *all* public blocks used accross regions while limiting it a smaller subnet size i=1 while true; do TEMP="$(dig_txt $i.ipv4.customers.prefixlist.$DOMAINNAME)" || break TEMPSUM="ip prefix-list WITv4-CUSTOMERS seq $((i*5)) permit ${TEMP} ge 25\n" FRR_IPV4_CUSTOMERS_PFLIST="${FRR_IPV4_CUSTOMERS_PFLIST}${TEMPSUM}" let i+=1 done i=1 while true; do TEMP="$(dig_txt $i.ipv6.customers.prefixlist.$DOMAINNAME)" || break TEMPSUM="ipv6 prefix-list WITv6-CUSTOMERS seq $((i*5)) permit ${TEMP} ge 64\n" FRR_IPV6_CUSTOMERS_PFLIST="${FRR_IPV6_CUSTOMERS_PFLIST}${TEMPSUM}" let i+=1 done ## compile loopback IP blocks that we wanna accept to be injected into the bgp i=1 while true; do TEMP="$(dig_txt $i.ipv4.loopback.prefixlist.$DOMAINNAME)" || break TEMPSUM="ip prefix-list LOOPBACKv4 seq $((i*5)) permit ${TEMP} ge 32\n" FRR_IPV4_LOOPBACK_PFLIST="${FRR_IPV4_LOOPBACK_PFLIST}${TEMPSUM}" [ -z $IPSEC_IPV4_SUBNETS ] || IPSEC_IPV4_SUBNETS="${IPSEC_IPV4_SUBNETS}," IPSEC_IPV4_SUBNETS="${IPSEC_IPV4_SUBNETS}${TEMP}" let i+=1 done i=1 while true; do TEMP="$(dig_txt $i.ipv6.loopback.prefixlist.$DOMAINNAME)" || break TEMPSUM="ipv6 prefix-list LOOPBACKv6 seq $((i*5)) permit ${TEMP} ge 128\n" FRR_IPV6_LOOPBACK_PFLIST="${FRR_IPV6_LOOPBACK_PFLIST}${TEMPSUM}" [ -z $IPSEC_IPV6_SUBNETS ] || IPSEC_IPV6_SUBNETS="${IPSEC_IPV6_SUBNETS}," IPSEC_IPV6_SUBNETS="${IPSEC_IPV6_SUBNETS}${TEMP}" let i+=1 done [ -z $IPSEC_IPV4_SUBNETS ] && exit 2 [ -z $IPSEC_IPV6_SUBNETS ] && exit 2 ## STOP compiling frr config ## START writing config files # set frr config sed -i \ -e "s/^!!! FRR_IFS/$FRR_IFS/" \ -e "s/^ !!! FRR_EDGE_NEIGH/$FRR_EDGE_NEIGH/" \ -e "s/^ !!! FRR_IPV4_EDGE_SUMMARIES_AGGREGATS/$FRR_IPV4_EDGE_SUMMARIES_AGGREGATS/" \ -e "s/^ !!! FRR_IPV6_EDGE_SUMMARIES_AGGREGATS/$FRR_IPV6_EDGE_SUMMARIES_AGGREGATS/" \ -e "s/^!!! FRR_IPV4_EDGE_SUMMARIES_PFLIST/$FRR_IPV4_EDGE_SUMMARIES_PFLIST/" \ -e "s/^!!! FRR_IPV6_EDGE_SUMMARIES_PFLIST/$FRR_IPV6_EDGE_SUMMARIES_PFLIST/" \ -e "s/^!!! FRR_IPV4_CUSTOMERS_PFLIST/$FRR_IPV4_CUSTOMERS_PFLIST/" \ -e "s/^!!! FRR_IPV6_CUSTOMERS_PFLIST/$FRR_IPV6_CUSTOMERS_PFLIST/" \ -e "s/^!!! FRR_IPV4_LOOPBACK_PFLIST/$FRR_IPV4_LOOPBACK_PFLIST/" \ -e "s/^!!! FRR_IPV6_LOOPBACK_PFLIST/$FRR_IPV6_LOOPBACK_PFLIST/" \ -e "s/BASTION-PUBLIC-IP/$BASTIONPUBLICIP/" \ -e "s/FRR_GRE_ASN/${FRR_GRE_ASN:=$NODEASN}/" \ -e "s/FRRROUTERID/${LOOPBACKv4}/" \ -e "s/LOOPBACK-IPV6/${LOOPBACKv6}/" \ -e "s/NODEASN/${NODEASN}/" \ $FRRCONFIG [ -z $FRR_EDGE_NEIGH ] || sed -i -e 's/!!! //' $FRRCONFIG [ -z $BASTIONPUBLICIP ] || sed -i -e 's/!!BASTION //' $FRRCONFIG # set ipsec config for IPSECCONFIGFILE in $IPSECCONFIG $SWANCTLCONFIG do sed -i \ -e "s/FQHOSTNAME/${HOSTNAME}/" \ -e "s/LOOPBACKv4/${LOOPBACKv4}\/32/" \ -e "s/LOOPBACKv6/${LOOPBACKv6}\/128/" \ -e "s/IPSEC_IPV4_SUBNETS/$IPSEC_IPV4_SUBNETS/" \ -e "s/IPSEC_IPV6_SUBNETS/$IPSEC_IPV6_SUBNETS/" \ $IPSECCONFIGFILE done cat <<-EOF >$IPSECSECRETS # dynamic file, content is overwritten by wit-network-config. I'm sorry but divertion is not working due to apparmor blocking it to this place and didn't wanna deal with that : RSA ${HOSTNAME}.key EOF ## END config file section ## START configuring services as we need it systemctl enable firewall systemctl restart firewall systemctl restart ssh systemctl reload strongswan || true ## in case we kick-start or done have it enabled for some reason sysctl -p $SYSCTLTWEAKS ## END services section ;; abort-upgrade|abort-remove|abort-deconfigure) ;; *) echo "postinst called with unknown argument \`$1'" >&2 exit 1 ;; esac # dh_installdeb will replace this with shell code automatically # generated by other debhelper scripts. #DEBHELPER# exit 0