Skip to content

Commit

Permalink
libreswan: uci configuration support
Browse files Browse the repository at this point in the history
- add patch to call hotplug script
- handle uci config with reload in init script

Signed-off-by: Jaymin Patel <[email protected]>
  • Loading branch information
jempatel committed Jul 31, 2022
1 parent f69a65e commit 946bdb0
Show file tree
Hide file tree
Showing 5 changed files with 275 additions and 15 deletions.
12 changes: 8 additions & 4 deletions net/libreswan/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk

PKG_NAME:=libreswan
PKG_VERSION:=4.7
PKG_RELEASE:=1
PKG_RELEASE:=$(AUTO_RELEASE)

PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://download.libreswan.org/
Expand Down Expand Up @@ -60,10 +60,10 @@ $(call Package/libreswan/Default/description)
endef

define Package/libreswan/conffiles
/etc/ipsec.d
/etc/ipsec.conf
/etc/ipsec.secrets
/etc/config/libreswan
/etc/ipsec.user
endef

TARGET_LDFLAGS += -Wl,--gc-sections,--as-needed
TARGET_CFLAGS += -flto

Expand Down Expand Up @@ -115,6 +115,10 @@ define Package/libreswan/install
$(1)/etc/ipsec.d/policies/
$(CP) $(PKG_INSTALL_DIR)/usr/libexec/ipsec/* \
$(1)/usr/libexec/ipsec/
$(INSTALL_DIR) $(1)/etc/hotplug.d/ipsec
$(CP) ./files/etc/hotplug.d/ipsec/01-user $(1)/etc/hotplug.d/ipsec/01-user
$(INSTALL_DIR) $(1)/etc/config
$(CP) ./files/etc/config/libreswan $(1)/etc/config/libreswan
endef

$(eval $(call BuildPackage,libreswan))
37 changes: 37 additions & 0 deletions net/libreswan/files/etc/config/libreswan
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
config libreswan 'globals'
option debug '0' # set debug mode none/all
list virtual_private '10.0.0.0/8'
list virtual_private '192.168.0.0/16'
list virtual_private '172.16.0.0/12'
list virtual_private '25.0.0.0/8'
list virtual_private '100.64.0.0/10'
list virtual_private '!100.64.0.0/24' # the address ranges that may live behind a NAT router through which a client connects
# option listen '192.168.2.100' # listening address, if set listen_interface would not be used
# option listen_interface 'wan' # listening interface
# option uniqueids 'yes' # yes/no

# config crypto_proposal 'p1'
# option encryption_algorithm '3des' # possible values: 3des, aes, aes_ctr, aes_cbc, aes128, aes192, aes256, camellia_cbc
# option hash_algorithm 'md5' # possible values: md5, sha1, sha256, sha384, sha512
# list dh_group 'modp1536' # possible values: modp1536, modp2048, modp3072, modp4096, modp6144, modp8192, dh19, dh20, dh21, dh22, dh31

# config tunnel 'vti2_1_5'
# option left '%wan' # left can be interface of ipaddress
# option leftid '@left' # local id
# option right '192.168.2.201' # remote endpoint public ip
# option rightid '@62dd3e3f82339b002405245b' # rightid
# option auto 'start' # what operation, should be done automatically at IPsec startup
# option authby 'secret' # how the two security gateways should authenticate each other
# option psk 'AyG9RlTtQJIUxgxG' # preshare key
# option ikev2 '1' # ike version
# option ikelifetime '10800'
# option rekey '1'
# option rekeymargin '540'
# option dpdaction 'restart'
# option dpddelay '30'
# option dpdtimeout '150'
# option vti_interface 'vti2_1_5' # only for route based tunnels
# option leftvti '172.16.31.2/30' # only for route based tunnels
# option mark '0x5' # only if vti interface is set
# list leftsubnets '0.0.0.0/0'
# list rightsubnets '0.0.0.0/0'
7 changes: 7 additions & 0 deletions net/libreswan/files/etc/hotplug.d/ipsec/01-user
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/sh

[ -e "/etc/ipsec.user" ] && {
. /etc/ipsec.user
}

exit 0
226 changes: 215 additions & 11 deletions net/libreswan/files/ipsec.init
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,36 +1,240 @@
#!/bin/sh /etc/rc.common

. /lib/functions/network.sh

START=90
STOP=10

USE_PROCD=1

PROG="/usr/libexec/ipsec/pluto"
IPSEC_SECRETS=/etc/ipsec.secrets
IPSEC_CONF=/etc/ipsec.conf
IPSEC_BIN=/usr/sbin/ipsec
IPSEC_BIN="/usr/sbin/ipsec"

IPSEC_DIR="/var/run/ipsec"
IPSEC_CONF="$IPSEC_DIR/ipsec.conf"
IPSEC_CONF_DIR="$IPSEC_DIR/conf.d"

checkconfig() {
${IPSEC_BIN} addconn --checkconfig || return 1
mkdir -p /var/run/pluto
${IPSEC_BIN} addconn --checkconfig || return 1
mkdir -p /var/run/pluto
}

expand_ike() {
local id="$1"
local encryption_algorithm hash_algorithm dh_group proposal

config_get encryption_algorithm "${id}" encryption_algorithm
config_get hash_algorithm "${id}" hash_algorithm
config_get dh_group "${id}" dh_group

proposal="${encryption_algorithm:+${encryption_algorithm}${hash_algorithm:+-${hash_algorithm}${dh_group:+;${dh_group%% *}}}}"
append ike_proposal "$proposal" ","
}

expand_phase2alg() {
local id="$1"
local encryption_algorithm hash_algorithm dh_group

config_get encryption_algorithm "${id}" encryption_algorithm
config_get hash_algorithm "${id}" hash_algorithm
config_get dh_group "${id}" dh_group

phase2alg_proposal="${encryption_algorithm:+${encryption_algorithm// /+}${hash_algorithm:+-${hash_algorithm// /+}${dh_group:+-${dh_group// /+}}}}"
}

generate_tunnel_config() {
local id=$1
local config_file="$IPSEC_CONF_DIR/$id.conf"
local secret_file="$IPSEC_CONF_DIR/$id.secret"

config_get auto "$id" auto
config_get left "$id" left
config_get right "$id" right
config_get leftid "$id" leftid "$left"
config_get rightid "$id" rightid "$right"
config_get leftsourceip "$id" leftsourceip
config_get rightsourceip "$id" rightsourceip
config_get leftsubnets "$id" leftsubnets
config_get rightsubnets "$id" rightsubnets
config_get_bool ikev2 "$id" ikev2
[ "$ikev2" = "1" ] && ikev2=yes || ikev2=no
config_get_bool rekey "$id" rekey
[ "$rekey" = "1" ] && rekey=yes || rekey=no
config_get ikelifetime "$id" ikelifetime
config_get rekeymargin "$id" rekeymargin
config_get dpdaction "$id" dpdaction
config_get dpdtimeout "$id" dpdtimeout
config_get dpddelay "$id" dpddelay
config_get phase2 "$id" phase2
config_get phase2alg "$id" phase2alg
config_get vti_interface "$id" vti_interface

if [ -n "$vti_interface" ]; then
config_get leftvti "$id" leftvti
config_get mark "$id" mark
fi

config_list_foreach "$id" ike expand_ike
config_list_foreach "$id" phase2alg expand_phase2alg

config_get authby "$id" authby
config_get psk "$id" psk

if [ -n "$leftsubnets" ]; then
[[ "$leftsubnets" =~ 0.0.0.0* ]] && leftsubnets="0.0.0.0/0"
leftsubnets="{${leftsubnets// /,}}"
fi

if [ -n "$rightsubnets" ]; then
[[ "$rightsubnets" =~ 0.0.0.0* ]] && rightsubnets="0.0.0.0/0"
rightsubnets="{${rightsubnets// /,}}"
fi

cat << EOF > "$config_file"
conn $id
auto=${auto}
authby=${authby}
ikev2=${ikev2}
left=${left%% *}
${leftid:+leftid=${leftid}}
${leftsourceip:+leftsourceip=${leftsourceip}}
${leftsubnets:+leftsubnets=${leftsubnets}}
right=${right%% *}
${rightid:+rightid=${rightid}}
${rightsourceip:+rightsourceip=${rightsourceip}}
${rightsubnets:+rightsubnets=${rightsubnets}}
${dpdaction:+dpdaction=${dpdaction}}
${dpdtimeout:+dpdtimeout=${dpdtimeout}}
${dpddelay:+dpddelay=${dpddelay}}
${ikelifetime:+ikelifetime=${ikelifetime}s}
${rekey:+rekey=${rekey}}
${rekeymargin:+rekeymargin=${rekeymargin}s}
${rekeyfuzz:+rekeyfuzz=${rekeyfuzz}}
${phase2:+phase2=${phase2}}
${ike_proposal:+ike=${ike_proposal}}
${phase2alg_proposal:+phase2alg=${phase2alg_proposal}}
${vti_interface:+vti-interface=${vti_interface}}
${leftvti:+leftvti=${leftvti}}
${mark:+mark=${mark}}
EOF

cat << EOF > "$secret_file"
$leftid $rightid : PSK "$psk"
EOF

unset ike_proposal phase2alg_proposal
}

generate_daemon_config() {
config_get_bool debug globals debug 0
[ "$debug" = "0" ] && debug=none || debug=all
config_get_bool uniqueids globals uniqueids 0
[ "$uniqueids" = "0" ] && uniqueids=no || uniqueids=yes
config_get listen globals listen
config_get listen_interface globals listen_interface
[ -n "$listen_interface" ] && network_get_ipaddr listen "$listen_interface"
config_get virtual_private globals virtual_private
[ -z "$virtual_private" ] && virtual_private='10.0.0.0/8 192.168.0.0/16 172.16.0.0/12 25.0.0.0/8 100.64.0.0/10 !100.64.0.0/24'

[ ! -d $IPSEC_DIR ] && mkdir -p $IPSEC_DIR
[ ! -d $IPSEC_CONF_DIR ] && mkdir -p $IPSEC_CONF_DIR

cat << EOF > "$IPSEC_CONF"
config setup
${debug:+plutodebug=${debug}}
${uniqueids:+uniqueids=${uniqueids}}
${listen:+listen=${listen}}
${virtual_private:+virtual-private=%v4:${virtual_private// /,%v4:}}
include $IPSEC_CONF_DIR/*.conf
EOF
}

clean_config() {
rm -f $IPSEC_CONF_DIR/*.conf $IPSEC_CONF_DIR/*.secret
}

config_cb() {
local var="CONFIG_${1}_SECTIONS"
export $var
append "$var" "$2"
}

generate_config() {
config_load libreswan
generate_daemon_config
config_foreach generate_tunnel_config tunnel
}

regenerate_config() {
clean_config
generate_config
}

active_conns() {
local active_conns file _file

active_conns=$(${IPSEC_BIN} --trafficstatus | awk -F'[":/]' '{print $3}' | sort -u)

for file in $IPSEC_CONF_DIR/*.conf; do
_file="${file##*/}"
list_contains active_conns "$_file" || append active_conns "${_file%%.*}"
done

echo "$active_conns"
}

start_service() {
generate_config
checkconfig || return 1

ipsec _stackmanager start
${IPSEC_BIN} _stackmanager start
# Enable nflog if configured
ipsec --checknflog > /dev/null
${IPSEC_BIN} --checknflog > /dev/null

procd_open_instance
procd_set_param command $PROG --config ${IPSEC_CONF} --nofork --secretsfile ${IPSEC_SECRETS}
procd_set_param command $PROG --config ${IPSEC_CONF} --nofork
procd_set_param respawn
procd_close_instance
}

stop_service() {
ipsec whack --shutdown
ipsec _stackmanager stop
ipsec --stopnflog > /dev/null
${IPSEC_BIN} whack --shutdown
${IPSEC_BIN} _stackmanager stop
${IPSEC_BIN} --stopnflog > /dev/null
}

delete_tunnel() {
${IPSEC_BIN} auto --delete "$1" > /dev/null 2>&1
rm -f ${IPSEC_CONF_DIR}/$1.*
}

add_tunnel() {
generate_tunnel_config "$1"
${IPSEC_BIN} auto --add "$1" > /dev/null 2>&1
${IPSEC_BIN} auto --rereadsecrets
${IPSEC_BIN} auto --up "$1" > /dev/null 2>&1 &
}

reload_service() {
local active_tunnels uci_tunnels

config_load libreswan
config_get uci_tunnels tunnel SECTIONS

active_tunnels="$(active_conns)"

for tunnel in $active_tunnels; do
list_contains uci_tunnels "$tunnel" || delete_tunnel "$tunnel"
done

for tunnel in $uci_tunnels; do
list_contains active_tunnels "$tunnel" || add_tunnel "$tunnel"
done

${IPSEC_BIN} auto --rereadall
}

service_triggers() {
procd_add_reload_trigger 'libreswan'
}
8 changes: 8 additions & 0 deletions net/libreswan/patches/050-updown-hotplug.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
--- a/programs/_updown.xfrm/_updown.xfrm.in
+++ b/programs/_updown.xfrm/_updown.xfrm.in
@@ -1025,3 +1025,5 @@ case "${PLUTO_VERB}" in
exit 1
;;
esac
+
+/sbin/hotplug-call ipsec

0 comments on commit 946bdb0

Please sign in to comment.