diff --git a/net/libreswan/Makefile b/net/libreswan/Makefile index 4ecc00a442..eb407e432c 100644 --- a/net/libreswan/Makefile +++ b/net/libreswan/Makefile @@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=libreswan PKG_VERSION:=4.12 -PKG_RELEASE:=1 +PKG_RELEASE:=2 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://download.libreswan.org/ @@ -25,46 +25,65 @@ PKG_BUILD_FLAGS:=lto include $(INCLUDE_DIR)/package.mk -define Package/libreswan/Default - TITLE:=Libreswan - URL:=https://libreswan.org/ -endef - -define Package/libreswan/Default/description - Libreswan is a free software implementation of the most widely supported and - standardized VPN protocol based on ("IPsec") and the Internet Key Exchange - ("IKE"). These standards are produced and maintained by the Internet - Engineering Task Force ("IETF"). -endef - -define Package/libreswan -$(call Package/libreswan/Default) +define Package/libreswan/default SUBMENU:=VPN SECTION:=net CATEGORY:=Network - DEPENDS:= +IPV6:kmod-ip6-vti +IPV6:kmod-ipsec6 +ip-full +iptables-mod-ipsec \ - +kmod-crypto-aead +kmod-crypto-authenc +kmod-crypto-gcm \ - +kmod-crypto-hash +kmod-crypto-rng +kmod-ip-vti +kmod-ipsec \ - +kmod-ipsec4 +kmod-ipt-ipsec +kmod-xfrm-interface +libevent2 +libevent2-pthreads \ - +libldns +librt +libunbound +nss-utils +nspr +libcap-ng + TITLE:=Libreswan + URL:=https://libreswan.org/ PROVIDES:=openswan CONFLICTS:=strongswan - TITLE+= IPsec Server +endef + +define Package/libreswan + $(Package/libreswan/default) + DEPENDS:= \ + +kmod-ip-vti +IPV6:kmod-ip6-vti \ + +kmod-ipsec +kmod-ipsec4 +IPV6:kmod-ipsec6 \ + +ip-full +kmod-xfrm-interface \ + +libevent2 +libevent2-pthreads \ + +libldns +librt +libunbound +nss-utils +nspr +libcap-ng \ + +kmod-crypto-acompress \ + +kmod-crypto-aead \ + +kmod-crypto-authenc \ + +kmod-crypto-arc4 \ + +kmod-crypto-cbc \ + +kmod-crypto-ccm \ + +kmod-crypto-chacha20poly1305 \ + +kmod-crypto-cmac \ + +kmod-crypto-ctr \ + +kmod-crypto-cts \ + +kmod-crypto-des \ + +kmod-crypto-ecb \ + +kmod-crypto-ecdh \ + +kmod-crypto-gcm \ + +kmod-crypto-ghash \ + +kmod-crypto-hash \ + +kmod-crypto-hmac \ + +kmod-crypto-md4 \ + +kmod-crypto-md5 \ + +kmod-crypto-null \ + +kmod-crypto-pcbc \ + +kmod-crypto-sha1 \ + +kmod-crypto-sha256 \ + +kmod-crypto-sha512 \ + +kmod-crypto-xcbc \ + +kmod-crypto-rng endef define Package/libreswan/description -$(call Package/libreswan/Default/description) - Libreswan is a free software implementation of the most widely supported and - standardized VPN protocol based on ("IPsec") and the Internet Key Exchange - ("IKE"). These standards are produced and maintained by the Internet - Engineering Task Force ("IETF"). + Libreswan is a free software implementation of the most widely supported and + standardized VPN protocol based on ("IPsec") and the Internet Key Exchange + ("IKE"). These standards are produced and maintained by the Internet + Engineering Task Force ("IETF"). 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 MAKE_FLAGS+= \ @@ -103,20 +122,82 @@ endef define Package/libreswan/install $(INSTALL_DIR) \ - $(1)/etc/init.d \ $(1)/etc/ipsec.d/policies \ $(1)/usr/libexec/ipsec \ - $(1)/usr/sbin + $(1)/usr/sbin \ + $(1)/etc/config \ + $(1)/etc/init.d \ + $(1)/etc/hotplug.d/libreswan \ + $(1)/etc/hotplug.d/iface \ + $(1)/usr/libexec/rpcd \ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/ipsec \ $(1)/usr/sbin/ipsec - $(INSTALL_BIN) ./files/ipsec.init $(1)/etc/init.d/ipsec - $(INSTALL_DATA) ./files/ipsec.conf $(1)/etc/ipsec.conf - $(INSTALL_DATA) ./files/ipsec.secrets $(1)/etc/ipsec.secrets $(INSTALL_DATA) $(PKG_INSTALL_DIR)/etc/ipsec.d/policies/* \ $(1)/etc/ipsec.d/policies/ $(CP) $(PKG_INSTALL_DIR)/usr/libexec/ipsec/* \ $(1)/usr/libexec/ipsec/ + + $(INSTALL_BIN) ./files/usr/libexec/ipsec/_updown.xfrm $(1)/usr/libexec/ipsec/_updown.xfrm + $(INSTALL_BIN) ./files/etc/init.d/ipsec $(1)/etc/init.d/ipsec + $(INSTALL_BIN) ./files/usr/libexec/rpcd/libreswan $(1)/usr/libexec/rpcd/libreswan + $(INSTALL_DATA) ./files/etc/ipsec.conf $(1)/etc/ipsec.conf + $(INSTALL_DATA) ./files/etc/ipsec.secrets $(1)/etc/ipsec.secrets + $(INSTALL_DATA) ./files/etc/config/libreswan $(1)/etc/config/libreswan + $(INSTALL_DATA) ./files/etc/hotplug.d/libreswan/01-user $(1)/etc/hotplug.d/libreswan/01-user + $(INSTALL_DATA) ./files/etc/hotplug.d/libreswan/02-vti $(1)/etc/hotplug.d/libreswan/02-vti + $(INSTALL_DATA) ./files/etc/hotplug.d/iface/89-libreswan $(1)/etc/hotplug.d/iface/89-libreswan +endef + +define Package/libreswan-nftables + $(Package/libreswan/default) + TITLE+= nftables plugin) + DEPENDS+=firewall4 +libreswan +kmod-nft-xfrm +nftables \ + +kmod-nfnetlink-log +endef + +define Package/libreswan-nftables/description + Provides Libreswan nftables plugin for adding firewall rules +endef + +define Package/libreswan-nftables/install + $(INSTALL_DIR) $(1)/etc/hotplug.d/libreswan \ + $(1)/usr/share/nftables.d/ruleset-post + + $(CP) ./files/usr/share/nftables.d/* $(1)/usr/share/nftables.d + $(CP) ./files/etc/hotplug.d/libreswan/62-nftables $(1)/etc/hotplug.d/libreswan/62-nftables + $(LN) /tmp/libreswan/firewall.d/libreswan.rules $(1)/usr/share/nftables.d/ruleset-post/10_libreswan.nft +endef + +define Package/libreswan-iptables + $(Package/libreswan/default) + TITLE+= iptables plugin) + DEPENDS+=firewall +libreswan +iptables-mod-ipsec +kmod-ipt-ipsec \ + +iptables-zz-legacy +IPV6:ip6tables-zz-legacy \ + +kmod-ipt-nflog +iptables-mod-nflog +endef + +define Package/libreswan-iptables/description + Provides Libreswan iptables plugin for adding firewall rules +endef + +define Package/libreswan-iptables/install + $(INSTALL_DIR) $(1)/etc \ + $(1)/etc/uci-defaults \ + $(1)/etc/hotplug.d/libreswan + + $(CP) ./files/etc/hotplug.d/libreswan/61-iptables $(1)/etc/hotplug.d/libreswan/61-iptables + $(CP) ./files/etc/uci-defaults/091-libreswan $(1)/etc/uci-defaults/091-libreswan + $(INSTALL_BIN) ./files/etc/libreswan_firewall.sh $(1)/etc/libreswan_firewall.sh +endef + +define Package/libreswan-iptables/postinst +#!/bin/sh +[ -n "$$IPKG_INSTROOT" ] || { + /etc/init.d/firewall reload +} endef $(eval $(call BuildPackage,libreswan)) +$(eval $(call BuildPackage,libreswan-nftables)) +$(eval $(call BuildPackage,libreswan-iptables)) diff --git a/net/libreswan/files/etc/config/libreswan b/net/libreswan/files/etc/config/libreswan new file mode 100644 index 0000000000..140c8f693b --- /dev/null +++ b/net/libreswan/files/etc/config/libreswan @@ -0,0 +1,41 @@ +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' +# list encryption_algorithm '3des' # possible values: 3des, aes, aes_ctr, aes_cbc, aes128, aes192, aes256, camellia_cbc +# list 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 '192.168.1.1' +# option left_interface 'wan' # interface ipaddr to be used as left +# 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 '8h' +# option rekey '1' +# option rekeymargin '9m' +# option dpdaction 'restart' +# option dpddelay '30' +# option dpdtimeout '150' +# option interface 'vti2_1_5' # only for route based tunnels +# list leftsubnets '0.0.0.0/0' +# list rightsubnets '0.0.0.0/0' +# option phase2 'esp' # phase2 protocol +# list ike 'p1' # list of crypto_proposal (phase1 proposals) +# list phase2ag 'p1' # list of crypto_proposal (phase2 proposals') +# option nflog '0' # enable nflog +# option update_peeraddr '1' # auto update vti interface ppeeradd in /etc/config/network diff --git a/net/libreswan/files/etc/hotplug.d/iface/89-libreswan b/net/libreswan/files/etc/hotplug.d/iface/89-libreswan new file mode 100644 index 0000000000..9ebc618150 --- /dev/null +++ b/net/libreswan/files/etc/hotplug.d/iface/89-libreswan @@ -0,0 +1,11 @@ +#!/bin/sh + +[ "$ACTION" = ifup -o "$ACTION" = ifupdate ] || exit 0 +[ "$ACTION" = ifupdate -a -z "$IFUPDATE_ADDRESSES" -a -z "$IFUPDATE_DATA" ] && exit 0 + +/etc/init.d/ipsec running || exit 0 +uci show libreswan | grep -i "='$INTERFACE'$" || exit 0 + +logger -t libreswan "Restart libreswan due to $ACTION of $INTERFACE ($DEVICE)" + +/etc/init.d/ipsec restart diff --git a/net/libreswan/files/etc/hotplug.d/libreswan/00-default b/net/libreswan/files/etc/hotplug.d/libreswan/00-default new file mode 100644 index 0000000000..940c49520c --- /dev/null +++ b/net/libreswan/files/etc/hotplug.d/libreswan/00-default @@ -0,0 +1,220 @@ +#!/bin/sh + +# Things that this script gets (from ipsec_pluto(8) man page) +# +# 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_CONNECTION_TYPE +# is type of the connection, "tunnel" or "transport". +# +# PLUTO_CONN_POLICY +# the policy of the connection, as in: +# RSASIG+ENCRYPT+TUNNEL+PFS+DONTREKEY+OPPORTUNISTIC +# +failureDROP+lKOD+rKOD +# +# CAT=YES| +# if client address translation inside IPsec stack is enabled +# +# 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_MY_ID +# is our ID. +# +# PLUTO_METRIC +# is the metric to set for the route +# +# PLUTO_MTU +# is the mtu to set for the route +# +# PLUTO_ADD_TIME +# Time the IPsec SA was added to the kernel +# +# PLUTO_MOBIKE_EVENT +# wether the connection is underdoing MOBIKE migration +# +# 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_ID +# is the ID 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_PEER_CA +# is the DN of the peer's CA that signed its certificate +# +# PLUTO_CFG_CLIENT=0|1 +# is MODECFG or IKEv2 Config client. +# +# PLUTO_CFG_SERVER=0|1 +# is MODECFG or IKEv2 Config server. +# +# PLUTO_PEER_DNS_INFO +# The peer's supplied DNS information (IKEv1 and IKEv2) +# +# PLUTO_PEER_DOMAIN_INFO +# The peer's supplied domain list for local resolving (IKEv2 only) +# +# PLUTO_PEER_BANNER +# is the peer's provided banner +# +# PLUTO_NM_CONFIGURED=0|1 +# is NetworkManager used for resolv.conf update +# +# PLUTO_CONN_ADDRFAMILY +# is the family type, "ipv4" or "ipv6" +# +# PLUTO_CONN_KIND +# is the "kind" of connection (CK_PERMANENT, CK_INSTANCE, etc) +# +# PLUTO_STACK +# is the local IPsec kernel stack used, eg XFRM, BSDKAME, NOSTACK +# +# PLUTO_IS_PEER_CISCO=0|1 +# remote server type is cisco. Add support for cisco extensions +# when used with xauth. +# +# PLUTO_SA_REQID +# When using KAME or XFRM, 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_XFRMI_FWMARK +# use outgoing mark +# +# 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 +# +# INTERFACE_IP +# The IP to configure / expect on the interface? Currently is never set +# +# PLUTO_XFRM_ROUTE +# if an XFRM (ipsec-device) has been specified, value will be "yes" +# +# 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. +# +# CONNMARK_IN +# the incoming mark to use +# +# CONNMARK_OUT +# the outgoing mark to use +# +# VTI_IFACE=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. +# +# VTI_IP +# The IP to configure on the VTI device +# +# SPI_IN / SPI_OUT +# The inbound and outbound SPI's of the connection. +# +# PLUTO_INBYTES +# total bytes received +# +# PLUTO_OUTBYTES +# total bytes sent +# +# NFLOG +# is the nflog group to use +# + +case "${PLUTO_VERB}" in + prepare-host|prepare-host-v6) ;; + prepare-client|prepare-client-v6) ;; + route-host|route-host-v6) ;; + unroute-host|unroute-host-v6) ;; + route-client|route-client-v6) ;; + unroute-client|unroute-client-v6) ;; + up-host|up-host-v6) ;; + down-host|down-host-v6) ;; + up-client|up-client-v6) ;; + down-client|down-client-v6) ;; +esac diff --git a/net/libreswan/files/etc/hotplug.d/libreswan/01-user b/net/libreswan/files/etc/hotplug.d/libreswan/01-user new file mode 100644 index 0000000000..120260957a --- /dev/null +++ b/net/libreswan/files/etc/hotplug.d/libreswan/01-user @@ -0,0 +1,7 @@ +#!/bin/sh + +[ -e "/etc/ipsec.user" ] && { + . /etc/ipsec.user +} + +exit 0 diff --git a/net/libreswan/files/etc/hotplug.d/libreswan/02-vti b/net/libreswan/files/etc/hotplug.d/libreswan/02-vti new file mode 100644 index 0000000000..719d60e9bd --- /dev/null +++ b/net/libreswan/files/etc/hotplug.d/libreswan/02-vti @@ -0,0 +1,24 @@ +#!/bin/sh + +. /lib/functions.sh + +[ "${PLUTO_VERB}" != "route-client" ] && [ "${PLUTO_VERB}" != "up-client" ] && exit 0 + +CONNECTION=${PLUTO_CONNECTION%/*} +[ -z "$CONNECTION" ] && exit 0 + +update_peeraddr=$(uci_get libreswan $CONNECTION update_peeraddr) +[ "$update_peeraddr" != "1" ] && exit 0 + +interface=$(uci_get libreswan $CONNECTION interface) +[ -z "$interface" ] && exit 0 + +proto=$(uci_get network "$interface" proto) +[ "$proto" != "vti" ] && exit 0 + +peeraddr=$(uci_get network "$interface" peeraddr) +[ "$peeraddr" == "$PLUTO_PEER" ] && exit 0 + +uci_set network "$interface" peeraddr "$PLUTO_PEER" +uci_commit network +ifup "$interface" diff --git a/net/libreswan/files/etc/hotplug.d/libreswan/61-iptables b/net/libreswan/files/etc/hotplug.d/libreswan/61-iptables new file mode 100644 index 0000000000..b795d3097b --- /dev/null +++ b/net/libreswan/files/etc/hotplug.d/libreswan/61-iptables @@ -0,0 +1,76 @@ +#!/bin/sh + +. /lib/functions.sh + +FW4="$(command -v fw4)" +[ -n "$FW4" ] && exit 0 + +CONNECTION="${PLUTO_CONNECTION//\//_}" +[ -z "$CONNECTION" ] && exit 0 + +IPT_LEGACY="$(command -v iptables-legacy)" +IPT="$(command -v iptables)" +BIN="${IPT_LEGACY:-$IPT}" +[ -z "$BIN" ] && exit 0 + +LIBRESWAN_INPUT="libreswan_input" +LIBRESWAN_FORWARD="libreswan_forward" +LIBRESWAN_OUTPUT="libreswan_output" +LIBRESWAN_NFLOG_INPUT="libreswan_nflog_input" +LIBRESWAN_NFLOG_OUTPUT="libreswan_nflog_output" +LIBRESWAN_POSTROUTING="libreswan_postrouting" + +FW_DIR="/tmp/libreswan/firewall.d" +LIBRESWAN_RULES_FILE="$FW_DIR/libreswan.rules" +RULES_DIR="$FW_DIR/rules" + +IPV4_RULES_FILE="$RULES_DIR/${CONNECTION}-ipv4.rules" +IPV6_RULES_FILE="$RULES_DIR/${CONNECTION}-ipv6.rules" + +reload_firewall() { + [ ! -d "$RULES_DIR" ] && return 0 + + cat $RULES_DIR/*.rules > "$LIBRESWAN_RULES_FILE" 2>/dev/null + /etc/init.d/firewall reload +} + +up_rules() { + [ -z "$PLUTO_PEER_CLIENT" ] && return 0 + + [ ! -d "$RULES_DIR" ] && mkdir -p "$RULES_DIR" + [ "$PLUTO_PEER_CLIENT" = "0.0.0.0/0" ] && [ "$PLUTO_MY_CLIENT" = "0.0.0.0/0" ] && return 0 + + cat << EOF > $IPV4_RULES_FILE +$BIN -t filter -A $LIBRESWAN_INPUT -m policy --dir in --pol ipsec -s $PLUTO_PEER_CLIENT -d $PLUTO_MY_CLIENT -m comment --comment "$PLUTO_CONNECTION" -j ACCEPT +$BIN -t filter -A $LIBRESWAN_FORWARD -s $PLUTO_PEER_CLIENT -d $PLUTO_MY_CLIENT -m comment --comment "$PLUTO_CONNECTION" -j ACCEPT +$BIN -t filter -A $LIBRESWAN_OUTPUT -m policy --dir out --pol ipsec -s $PLUTO_MY_CLIENT -d $PLUTO_PEER_CLIENT -m comment --comment "$PLUTO_CONNECTION" -j ACCEPT +$BIN -t nat -A $LIBRESWAN_POSTROUTING -m policy --dir out --pol ipsec -s $PLUTO_MY_CLIENT -d $PLUTO_PEER_CLIENT -m comment --comment "$PLUTO_CONNECTION" -j ACCEPT +EOF + if [ -n "$NFLOG" ]; then + cat << EOF > $IPV4_RULES_FILE +$BIN -t filter -A $LIBRESWAN_NFLOG_INPUT -m policy --dir in --pol ipsec -s $PLUTO_PEER_CLIENT -d $PLUTO_MY_CLIENT -j NFLOG --nflog-group $NFLOG --nflog-prefix $PLUTO_CONNECTION +$BIN -t filter -A $LIBRESWAN_NFLOG_OUTPUT -m policy --dir out --pol ipsec -s $PLUTO_MY_CLIENT -d $PLUTO_PEER_CLIENT -j NFLOG --nflog-group $NFLOG --nflog-prefix $PLUTO_CONNECTION +EOF + + fi + + reload_firewall + + return 0 +} + +down_rules() { + if [ -f "$IPV4_RULES_FILE" ]; then + rm -rf "$IPV4_RULES_FILE" + reload_firewall + fi + + return 0 +} + +case "${PLUTO_VERB}" in + up-host|up-client) up_rules ;; + down-host|down-client) down_rules ;; + up-host-v6|down-host-v6) ;; + up-client|down-client-v6) ;; +esac diff --git a/net/libreswan/files/etc/hotplug.d/libreswan/62-nftables b/net/libreswan/files/etc/hotplug.d/libreswan/62-nftables new file mode 100644 index 0000000000..fe88147696 --- /dev/null +++ b/net/libreswan/files/etc/hotplug.d/libreswan/62-nftables @@ -0,0 +1,87 @@ +#!/bin/sh + +. /lib/functions.sh + +FW4="$(command -v fw4)" +[ -z "$FW4" ] && exit 0 + +CONNECTION="${PLUTO_CONNECTION//\//_}" +[ -z "$CONNECTION" ] && exit 0 + +FW_DIR="/tmp/libreswan/firewall.d" +LIBRESWAN_RULES_FILE="$FW_DIR/libreswan.rules" +RULES_DIR="$FW_DIR/rules" + +IPV4_RULES_FILE="$RULES_DIR/${CONNECTION}-ipv4.rules" +IPV6_RULES_FILE="$RULES_DIR/${CONNECTION}-ipv6.rules" +NFLOG_ALL_RULES_FILE="$RULES_DIR/nflog_all.rules" + +reload_firewall() { + [ ! -d "$RULES_DIR" ] && return 0 + + cat $RULES_DIR/*.rules > "$LIBRESWAN_RULES_FILE" 2>/dev/null + /etc/init.d/firewall reload +} + +up_rules() { + [ -z "$PLUTO_PEER_CLIENT" ] && return 0 + + [ ! -d "$RULES_DIR" ] && mkdir -p "$RULES_DIR" + + eval $(ipsec addconn --configsetup) + + if [ -n "$nflog_all" ]; then + unset NFLOG + if [ ! -f "$NFLOG_ALL_RULES_FILE" ]; then + cat << EOF > "$NFLOG_ALL_RULES_FILE" +table inet fw4 { + chain libreswan_nflog_input { + meta ipsec exists log prefix "all-ipsec" group ${nflog_all} + } + chain libreswan_nflog_output { + rt ipsec exists log prefix "all-ipsec" group ${nflog_all} + } +} +EOF + fi + else + [ -f "$NFLOG_ALL_RULES_FILE" ] && rm -f "$NFLOG_ALL_RULES_FILE" + fi + + cat << EOF > $IPV4_RULES_FILE +table inet fw4 { + chain libreswan_input { + meta ipsec exists ipsec in ip saddr $PLUTO_PEER_CLIENT ip daddr $PLUTO_MY_CLIENT ${NFLOG:+log prefix \"${PLUTO_CONNECTION}\" group ${NFLOG}} accept comment "$PLUTO_CONNECTION" + } + chain libreswan_forward { + meta ipsec exists ipsec in ip saddr $PLUTO_PEER_CLIENT ip daddr $PLUTO_MY_CLIENT accept comment "$PLUTO_CONNECTION" + } + chain libreswan_output { + ipsec out ip saddr $PLUTO_MY_CLIENT ip daddr $PLUTO_PEER_CLIENT ${NFLOG:+log prefix \"${PLUTO_CONNECTION}\" group ${NFLOG}} accept comment "$PLUTO_CONNECTION" + } + chain libreswan_srcnat { + ip saddr $PLUTO_MY_CLIENT ip daddr $PLUTO_PEER_CLIENT accept comment "$PLUTO_CONNECTION" + } +} +EOF + + reload_firewall + + return 0 +} + +down_rules() { + if [ -f "$IPV4_RULES_FILE" ]; then + rm -rf "$IPV4_RULES_FILE" + reload_firewall + fi + + return 0 +} + +case "${PLUTO_VERB}" in + up-host|up-client) up_rules ;; + down-host|down-client) down_rules ;; + up-host-v6|down-host-v6) ;; + up-client|down-client-v6) ;; +esac diff --git a/net/libreswan/files/etc/init.d/ipsec b/net/libreswan/files/etc/init.d/ipsec new file mode 100644 index 0000000000..8a94785283 --- /dev/null +++ b/net/libreswan/files/etc/init.d/ipsec @@ -0,0 +1,337 @@ +#!/bin/sh /etc/rc.common + +. "${IPKG_INSTROOT}/lib/functions/network.sh" + +START=90 +STOP=10 + +USE_PROCD=1 + +PROG="/usr/libexec/ipsec/pluto" +IPSEC_BIN="/usr/sbin/ipsec" + +IPSEC_DIR="/var/run/ipsec" +IPSEC_CONF="$IPSEC_DIR/setup.conf" +IPSEC_CONF_DIR="$IPSEC_DIR/conf.d" + +IPSEC_AUTO="${IPSEC_BIN} auto" + +extra_command "start_tunnel" "Start ipsec tunnel" +extra_command "stop_tunnel" "Stop ipsec tunnel" +extra_command "reload_tunnel" "Reload/restart ipsec tunnel" + +set_var() { + export "$1=$2" +} + +get_var() { + local var + + var=$(eval echo "\"\${${1}}\"") + [ "$var" = "1" ] && return 0 + + return 1 +} + +set_restart_flag() { + set_var "RESTART_IPSEC" 1 +} + +restart_flag() { + get_var RESTART_IPSEC +} + +set_replace_flag() { + set_var "REPLACE_${1}" 1 +} + +replace_flag() { + get_var "REPLACE_${1}" +} + +checkconfig() { + ${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 + + encryption_algorithm="${encryption_algorithm% *}" + 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" + local tmp_config_file="/tmp/$id.conf" + local tmp_secret_file="/tmp/$id.secret" + local ikey mark_in okey mark_out ifid + + config_get auto "$id" auto + config_get left "$id" left + config_get left_interface "$id" left_interface + [ -n "$left_interface" ] && network_get_ipaddr left "$left_interface" + 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 nflog "$id" nflog 0 + [ "$nflog" = "0" ] && unset nflog + + 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 + + config_get interface "$id" interface + + cat << EOF > "$tmp_secret_file" +$leftid $rightid : PSK "$psk" +EOF + + cat << EOF > "$tmp_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}} + ${rekey:+rekey=${rekey}} + ${rekeymargin:+rekeymargin=${rekeymargin}} + ${rekeyfuzz:+rekeyfuzz=${rekeyfuzz}} + ${phase2:+phase2=${phase2}} + ${ike_proposal:+ike=${ike_proposal}} + ${phase2alg_proposal:+phase2alg=${phase2alg_proposal}} + ${nflog:+nflog=${nflog}} +EOF + + if [ -n "$interface" ]; then + proto=$(uci_get network "$interface" proto) + case "$proto" in + vti) + ikey=$(uci_get network "$interface" ikey) + okey=$(uci_get network "$interface" okey) + mark_in=$(printf "0x%x" $ikey) + mark_out=$(printf "0x%x" $okey) + echo -e "${mark_in:+\tmark-in=${mark_in}}" >> "$tmp_config_file" + echo -e "${mark_out:+\tmark-out=${mark_out}}" >> "$tmp_config_file" + echo -e "${interface:+\tvti-interface=${interface}}" >> "$tmp_config_file" + ;; + xfrm) + ifid=$(uci_get network "$interface" ifid) + echo -e "${ifid:+\tipsec-interface=${ifid}}" >> "$tmp_config_file" + ;; + esac + fi + + + [ -f "$config_file" ] && { + cmp "$config_file" "$tmp_config_file" 2>/dev/null && rm -f "$tmp_config_file" + } + + [ -f "$secret_file" ] && { + cmp "$secret_file" "$tmp_secret_file" 2>/dev/null && rm -f "$tmp_secret_file" + } + + [ -f "$tmp_config_file" ] && mv "$tmp_config_file" "$config_file" && set_replace_flag "$id" + [ -f "$tmp_secret_file" ] && mv "$tmp_secret_file" "$secret_file" && set_replace_flag "$id" + + unset ike_proposal phase2alg_proposal +} + +generate_daemon_config() { + local tmp_config_file="/tmp/setup.conf" + + 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' + config_get nflog_all globals nflog_all 0 + [ "$nflog_all" = "0" ] && unset nflog_all + + [ ! -d $IPSEC_DIR ] && mkdir -p $IPSEC_DIR + [ ! -d $IPSEC_CONF_DIR ] && mkdir -p $IPSEC_CONF_DIR + + cat << EOF > "$tmp_config_file" +config setup + ${debug:+plutodebug=${debug}} + ${uniqueids:+uniqueids=${uniqueids}} + ${listen:+listen=${listen}} + ${virtual_private:+virtual-private=%v4:${virtual_private// /,%v4:}} + ${nflog_all:+nflog-all=${nflog_all}} +EOF + + if ! cmp "$IPSEC_CONF" "$tmp_config_file" 2>/dev/null; then + mv "$tmp_config_file" "$IPSEC_CONF" + set_restart_flag 1 + else + rm -f "$tmp_config_file" + fi + + return 0 +} + +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_BIN} _stackmanager start + + procd_open_instance + procd_set_param command $PROG --nofork + procd_set_param respawn + procd_close_instance +} + +stop_service() { + ${IPSEC_BIN} whack --shutdown + ${IPSEC_BIN} _stackmanager stop +} + +stop_tunnel() { + ${IPSEC_AUTO} --delete "$1" > /dev/null 2>&1 + rm -f ${IPSEC_CONF_DIR}/$1.* +} + +start_tunnel() { + generate_tunnel_config "$1" + ${IPSEC_AUTO} --add "$1" > /dev/null 2>&1 + ${IPSEC_AUTO} --rereadsecrets + ${IPSEC_AUTO} --up "$1" > /dev/null 2>&1 & +} + +reload_tunnel() { + generate_tunnel_config "$1" + + replace_flag "$1" || return 0 + + ${IPSEC_AUTO} --rereadsecrets + ${IPSEC_AUTO} --replace "$1" > /dev/null 2>&1 + ${IPSEC_AUTO} --up "$1" > /dev/null 2>&1 & +} + +reload_service() { + local active_tunnels uci_tunnels + uci_tunnels="$@" + + config_load libreswan + generate_daemon_config + + if restart_flag; then + restart + return 0 + fi + + [ -z "$uci_tunnels" ] && config_get uci_tunnels tunnel SECTIONS + + active_tunnels="$(active_conns)" + + for tunnel in $active_tunnels; do + list_contains uci_tunnels "$tunnel" || stop_tunnel "$tunnel" + done + + for tunnel in $uci_tunnels; do + if list_contains active_tunnels "$tunnel"; then + reload_tunnel "$tunnel" + else + start_tunnel "$tunnel" + fi + done +} + +service_triggers() { + procd_add_reload_trigger 'libreswan' +} diff --git a/net/libreswan/files/etc/ipsec.conf b/net/libreswan/files/etc/ipsec.conf new file mode 100644 index 0000000000..3b8f2dc3f3 --- /dev/null +++ b/net/libreswan/files/etc/ipsec.conf @@ -0,0 +1,3 @@ +include /var/run/ipsec/setup.conf +include /var/run/ipsec/conf.d/*.conf +include /etc/ipsec.d/*.conf diff --git a/net/libreswan/files/etc/ipsec.secrets b/net/libreswan/files/etc/ipsec.secrets new file mode 100644 index 0000000000..68bbe91755 --- /dev/null +++ b/net/libreswan/files/etc/ipsec.secrets @@ -0,0 +1,2 @@ +include /var/run/ipsec/conf.d/*.secret +include /etc/ipsec.d/*.secrets diff --git a/net/libreswan/files/etc/libreswan_firewall.sh b/net/libreswan/files/etc/libreswan_firewall.sh new file mode 100755 index 0000000000..94ba275f6d --- /dev/null +++ b/net/libreswan/files/etc/libreswan_firewall.sh @@ -0,0 +1,90 @@ +#!/bin/sh + +FW4="$(command -v fw4)" +[ -n "$FW4" ] && exit 0 + +IPT_LEGACY="$(command -v iptables-legacy)" +IPT="$(command -v iptables)" +BIN="${IPT_LEGACY:-$IPT}" +[ -z "$BIN" ] && exit 0 + +LIBRESWAN_INPUT="libreswan_input" +LIBRESWAN_FORWARD="libreswan_forward" +LIBRESWAN_OUTPUT="libreswan_output" +LIBRESWAN_NFLOG_INPUT="libreswan_nflog_input" +LIBRESWAN_NFLOG_OUTPUT="libreswan_nflog_output" +LIBRESWAN_POSTROUTING="libreswan_postrouting" + +FW_DIR="/tmp/libreswan/firewall.d" +LIBRESWAN_RULES_FILE="$FW_DIR/libreswan.rules" + +flush_delete_chain() { + [ $# -lt 2 ] && return + + $BIN -t $1 -nL $2 > /dev/null 2>&1 || return + + $BIN -t $1 -F $2 + $BIN -t $1 -X $2 +} + +cleanup_libreswan_rules() { + $BIN -t filter -C input_rule -j $LIBRESWAN_INPUT > /dev/null 2>&1 + [ $? -eq 0 ] && $BIN -t filter -D input_rule -j $LIBRESWAN_INPUT + + $BIN -t filter -C output_rule -j $LIBRESWAN_OUTPUT > /dev/null 2>&1 + [ $? -eq 0 ] && $BIN -t filter -D output_rule -j $LIBRESWAN_OUTPUT + + $BIN -t filter -C forwarding_rule -j $LIBRESWAN_FORWARD > /dev/null 2>&1 + [ $? -eq 0 ] && $BIN -t filter -D forwarding_rule -j $LIBRESWAN_FORWARD + + $BIN -t nat -C postrouting_rule -j $LIBRESWAN_POSTROUTING > /dev/null 2>&1 + [ $? -eq 0 ] && $BIN -t nat -D postrouting_rule -j $LIBRESWAN_POSTROUTING + + flush_delete_chain filter $LIBRESWAN_NFLOG_INPUT + flush_delete_chain filter $LIBRESWAN_INPUT + flush_delete_chain filter $LIBRESWAN_FORWARD + flush_delete_chain filter $LIBRESWAN_NFLOG_OUTPUT + flush_delete_chain filter $LIBRESWAN_OUTPUT + flush_delete_chain filter $LIBRESWAN_NFLOG_INPUT + flush_delete_chain filter $LIBRESWAN_NFLOG_OUTPUT + flush_delete_chain nat $LIBRESWAN_POSTROUTING +} + +create_chain_jump() { + [ $# -lt 3 ] && return + + local table=$1 + local chain=$2 + local base_chain=$3 + + $BIN -t $table -N $chain + $BIN -t $table -C $base_chain -j $chain + [ $? -ne 0 ] && $BIN -t $table -I $base_chain -j $chain + $BIN -t $table -F $chain +} + +if ! /etc/init.d/ipsec running; then + cleanup_libreswan_rules + exit 0 +fi + +eval $(ipsec addconn --configsetup) + +create_chain_jump filter "$LIBRESWAN_INPUT" "insert_rule" +create_chain_jump filter "$LIBRESWAN_FORWARD" "forwarding_rule" +create_chain_jump filter "$LIBRESWAN_OUTPUT" "output_rule" + +create_chain_jump filter "$LIBRESWAN_NFLOG_INPUT" "$LIBRESWAN_INPUT" +create_chain_jump filter "$LIBRESWAN_NFLOG_OUTPUT" "$LIBRESWAN_OUTPUT" + +create_chain_jump nat "$LIBRESWAN_POSTROUTING" "postrouting_rule" + +[ ! -f $LIBRESWAN_RULES_FILE ] && exit 0 + +if [ -n "$nflog_all" ]; then + sed -i -e '/NFLOG/d' "$LIBRESWAN_RULES_FILE" + $BIN -t filter -I $LIBRESWAN_NFLOG_INPUT -m policy --dir in --pol ipsec -j NFLOG --nflog-group ${nflog_all} --nflog-prefix all-ipsec + $BIN -t filter -I $LIBRESWAN_NFLOG_OUTPUT -m policy --dir out --pol ipsec -j NFLOG --nflog-group ${nflog_all} --nflog-prefix all-ipsec +fi + +sh $LIBRESWAN_RULES_FILE diff --git a/net/libreswan/files/etc/uci-defaults/091-libreswan b/net/libreswan/files/etc/uci-defaults/091-libreswan new file mode 100644 index 0000000000..91a16e1b3f --- /dev/null +++ b/net/libreswan/files/etc/uci-defaults/091-libreswan @@ -0,0 +1,8 @@ +#!/bin/sh + +. /lib/functions.sh + +uci_add firewall include libreswan +uci_set firewall libreswan path '/etc/libreswan_firewall.sh' +uci_set firewall libreswan reload 1 +uci_commit firewall diff --git a/net/libreswan/files/ipsec.conf b/net/libreswan/files/ipsec.conf deleted file mode 100644 index 8b7493b865..0000000000 --- a/net/libreswan/files/ipsec.conf +++ /dev/null @@ -1,25 +0,0 @@ -config setup - # needed when using PSK only. Not needed for X.509 based servers - uniqueids=no - virtual_private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12,%v4:25.0.0.0/8,%v4:100.64.0.0/10,%v4:!100.64.0.0/24 - -conn ikev1 - authby=secret - pfs=no - auto=add - rekey=no - left=%defaultroute - right=%any - ikev2=never - type=transport - leftprotoport=17/1701 - rightprotoport=17/%any - dpddelay=15 - dpdtimeout=30 - dpdaction=clear - -conn ikev1-nat - also=ikev1 - rightsubnet=vhost:%priv - -# include /etc/ipsec.d/*.conf diff --git a/net/libreswan/files/ipsec.init b/net/libreswan/files/ipsec.init deleted file mode 100755 index f33d412924..0000000000 --- a/net/libreswan/files/ipsec.init +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/sh /etc/rc.common - -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 - -checkconfig() { - ${IPSEC_BIN} addconn --checkconfig || return 1 - mkdir -p /var/run/pluto -} - -start_service() { - checkconfig || return 1 - - ipsec _stackmanager start - # Enable nflog if configured - ipsec --checknflog > /dev/null - - procd_open_instance - procd_set_param command $PROG --config ${IPSEC_CONF} --nofork --secretsfile ${IPSEC_SECRETS} - procd_set_param respawn - procd_close_instance -} - -stop_service() { - ipsec whack --shutdown - ipsec _stackmanager stop - ipsec --stopnflog > /dev/null - -} - diff --git a/net/libreswan/files/ipsec.secrets b/net/libreswan/files/ipsec.secrets deleted file mode 100644 index 5ef87b09c8..0000000000 --- a/net/libreswan/files/ipsec.secrets +++ /dev/null @@ -1,10 +0,0 @@ -# Unlike older openswan, this file does NOT contain any X.509 related -# information such as private key :RSA statements as these now reside -# in the NSS database. See: -# -# https://libreswan.org/wiki/Using_NSS_with_libreswan -# https://libreswan.org/wiki/Migrating_from_Openswan - -# A.B.C.D %any : PSK "SsEeCcRrEeTt" -: PSK "SsEeCcRrEeTt" -# include /etc/ipsec.d/*.secrets diff --git a/net/libreswan/files/usr/libexec/ipsec/_updown.xfrm b/net/libreswan/files/usr/libexec/ipsec/_updown.xfrm new file mode 100644 index 0000000000..58b51ba281 --- /dev/null +++ b/net/libreswan/files/usr/libexec/ipsec/_updown.xfrm @@ -0,0 +1,3 @@ +#!/bin/sh + +/sbin/hotplug-call libreswan diff --git a/net/libreswan/files/usr/libexec/rpcd/libreswan b/net/libreswan/files/usr/libexec/rpcd/libreswan new file mode 100644 index 0000000000..cf251f0c67 --- /dev/null +++ b/net/libreswan/files/usr/libexec/rpcd/libreswan @@ -0,0 +1,183 @@ +#!/bin/sh + +. /lib/functions.sh +. /usr/share/libubox/jshn.sh + +RPC_SCRIPTS=/usr/libexec/libreswan/rpc + +[ -d $RPC_SCRIPTS ] && include $RPC_SCRIPTS + +IPSEC_TRAFFIC_STATES="/tmp/ipsec_traffic.$$" +IPSEC_TUNNEL_STATUS="/tmp/ipsec_status.$$" + +__function__() { + type "$1" > /dev/null 2>&1 +} + +foreach_extra() { + local file obj + + [ ! -d $RPC_SCRIPTS ] && return + + for file in $RPC_SCRIPTS/*; do + obj="${file##*/}" + $1 "${obj%%.*}" + done +} + +get_index() { + [ $# -lt 2 ] && return 1 + + local var=$1 + local str=$2 + local ele + local i=1 + + eval "val=\"\${$var}\"" + + for ele in ${val}; do + if [[ "$ele" = "$str" ]]; then + echo "$i" + return 0 + fi + i="$((i+1))" + done + + return 1 +} + +phase1_established() { + grep -q "\"${1%/*}\/.*(IKE SA established)\|\"${1%/*}\/.*(established IKE SA)" "$IPSEC_TUNNEL_STATUS" +} + +phase2_established() { + grep -q "\"$1\".*(IPsec SA established)\|\"$1\".*(established Child SA)" "$IPSEC_TUNNEL_STATUS" +} + +add_tunnel_object() { + local id="$1" + local leftsubnets rightsubnets right ctime active_right + local phase1=0 phase2=0 add_time inBytes outBytes + + config_get right "$id" right + config_get leftsubnets "$id" leftsubnets + config_get rightsubnets "$id" rightsubnets + + if [ -z "$right" ] || [ "$right" = "%any" ] || [ "$right" == "0.0.0.0" ]; then + active_right=$(awk -F'[: ]' '{ if ( $4 ~ "'"$id/"'") {print $5; exit 0};}' "$IPSEC_TUNNEL_STATUS") + fi + + for lsubnet in $leftsubnets; do + lidx=$(get_index leftsubnets $lsubnet) + for rsubnet in $rightsubnets; do + ridx=$(get_index rightsubnets $rsubnet) + tid="${id}/${lidx}x${ridx}" + + eval $(awk -F, '{if ($1 ~ "'"$tid"'" ) {printf("%s %s %s", $3, $4, $5)};}' "$IPSEC_TRAFFIC_STATES") + json_add_object tunnels + json_add_string name "$id" + json_add_string right "$right${active_right:+ (${active_right})}" + json_add_string leftsubnet "$lsubnet" + json_add_string rightsubnet "$rsubnet" + json_add_int tx "$outBytes" + json_add_int rx "$inBytes" + + phase1_established "$tid" && phase1=1 + phase2_established "$tid" && phase2=1 + + json_add_boolean phase1 "$phase1" + json_add_boolean phase2 "$phase2" + + if [ "$phase1" = "1" ] && [ "$phase2" = "1" ]; then + ctime="$(date +%s)" + json_add_boolean connected 1 + json_add_int uptime "$((ctime - add_time))" + else + json_add_boolean connected 0 + json_add_int uptime 0 + fi + + json_close_object + done + done +} + +generate_libreswan_states() { + ipsec trafficstatus > "$IPSEC_TRAFFIC_STATES" + ipsec status > "$IPSEC_TUNNEL_STATUS" +} + +clean_libreswan_states() { + return + rm -f "$IPSEC_TRAFFIC_STATES" "$IPSEC_TUNNEL_STATUS" +} + +libreswan_status() { + config_load libreswan + + generate_libreswan_states + + json_init + json_add_array tunnels + config_foreach add_tunnel_object tunnel + json_close_array + json_dump + + clean_libreswan_states +} + +call_extra() { + if __function__ "$1"; then + $1 + else + json_init + json_add_string error "invalid call $1" + json_dump + fi +} + +call_method() { + case "$1" in + status) + libreswan_status + ;; + *) + call_extra $1 + ;; + esac +} + +list_extra() { + if __function__ "${1}_help"; then + ${1}_help + else + json_add_object "$1" + json_close_object + fi +} + +list_methods() { + local file + + json_init + + json_add_object status + json_close_object + + foreach_extra list_extra ${1} + + json_dump +} + +main () { + case "$1" in + list) + list_methods + ;; + call) + call_method $2 + ;; + esac +} + +main "$@" diff --git a/net/libreswan/files/usr/share/nftables.d/chain-pre/forward/001-libreswan.nft b/net/libreswan/files/usr/share/nftables.d/chain-pre/forward/001-libreswan.nft new file mode 100644 index 0000000000..7861a913d6 --- /dev/null +++ b/net/libreswan/files/usr/share/nftables.d/chain-pre/forward/001-libreswan.nft @@ -0,0 +1 @@ +jump libreswan_forward diff --git a/net/libreswan/files/usr/share/nftables.d/chain-pre/input/001-libreswan.nft b/net/libreswan/files/usr/share/nftables.d/chain-pre/input/001-libreswan.nft new file mode 100644 index 0000000000..665930953c --- /dev/null +++ b/net/libreswan/files/usr/share/nftables.d/chain-pre/input/001-libreswan.nft @@ -0,0 +1,2 @@ +jump libreswan_nflog_input +jump libreswan_input diff --git a/net/libreswan/files/usr/share/nftables.d/chain-pre/output/001-libreswan.nft b/net/libreswan/files/usr/share/nftables.d/chain-pre/output/001-libreswan.nft new file mode 100644 index 0000000000..825666adef --- /dev/null +++ b/net/libreswan/files/usr/share/nftables.d/chain-pre/output/001-libreswan.nft @@ -0,0 +1,2 @@ +jump libreswan_nflog_output +jump libreswan_output diff --git a/net/libreswan/files/usr/share/nftables.d/chain-pre/srcnat/001-libreswan.nft b/net/libreswan/files/usr/share/nftables.d/chain-pre/srcnat/001-libreswan.nft new file mode 100644 index 0000000000..4c9fbecf53 --- /dev/null +++ b/net/libreswan/files/usr/share/nftables.d/chain-pre/srcnat/001-libreswan.nft @@ -0,0 +1 @@ +jump libreswan_srcnat diff --git a/net/libreswan/files/usr/share/nftables.d/table-post/001-libreswan.nft b/net/libreswan/files/usr/share/nftables.d/table-post/001-libreswan.nft new file mode 100644 index 0000000000..0e00ea0b02 --- /dev/null +++ b/net/libreswan/files/usr/share/nftables.d/table-post/001-libreswan.nft @@ -0,0 +1,6 @@ +chain libreswan_input {} +chain libreswan_nflog_input {} +chain libreswan_forward {} +chain libreswan_output {} +chain libreswan_nflog_output {} +chain libreswan_srcnat {}