libreswan: uci configuration support
authorJaymin Patel <jem.patel@gmail.com>
Mon, 22 Aug 2022 11:11:33 +0000 (16:41 +0530)
committerJaymin Patel <jem.patel@gmail.com>
Mon, 30 Oct 2023 18:14:39 +0000 (23:44 +0530)
Add libreswan UCI configuration and hotplug support

Signed-off-by: Jaymin Patel <jem.patel@gmail.com>
23 files changed:
net/libreswan/Makefile
net/libreswan/files/etc/config/libreswan [new file with mode: 0644]
net/libreswan/files/etc/hotplug.d/iface/89-libreswan [new file with mode: 0644]
net/libreswan/files/etc/hotplug.d/libreswan/00-default [new file with mode: 0644]
net/libreswan/files/etc/hotplug.d/libreswan/01-user [new file with mode: 0644]
net/libreswan/files/etc/hotplug.d/libreswan/02-vti [new file with mode: 0644]
net/libreswan/files/etc/hotplug.d/libreswan/61-iptables [new file with mode: 0644]
net/libreswan/files/etc/hotplug.d/libreswan/62-nftables [new file with mode: 0644]
net/libreswan/files/etc/init.d/ipsec [new file with mode: 0644]
net/libreswan/files/etc/ipsec.conf [new file with mode: 0644]
net/libreswan/files/etc/ipsec.secrets [new file with mode: 0644]
net/libreswan/files/etc/libreswan_firewall.sh [new file with mode: 0755]
net/libreswan/files/etc/uci-defaults/091-libreswan [new file with mode: 0644]
net/libreswan/files/ipsec.conf [deleted file]
net/libreswan/files/ipsec.init [deleted file]
net/libreswan/files/ipsec.secrets [deleted file]
net/libreswan/files/usr/libexec/ipsec/_updown.xfrm [new file with mode: 0644]
net/libreswan/files/usr/libexec/rpcd/libreswan [new file with mode: 0644]
net/libreswan/files/usr/share/nftables.d/chain-pre/forward/001-libreswan.nft [new file with mode: 0644]
net/libreswan/files/usr/share/nftables.d/chain-pre/input/001-libreswan.nft [new file with mode: 0644]
net/libreswan/files/usr/share/nftables.d/chain-pre/output/001-libreswan.nft [new file with mode: 0644]
net/libreswan/files/usr/share/nftables.d/chain-pre/srcnat/001-libreswan.nft [new file with mode: 0644]
net/libreswan/files/usr/share/nftables.d/table-post/001-libreswan.nft [new file with mode: 0644]

index 4ecc00a442bb273baed000fa6f2aadec466897d0..eb407e432c6518549dd786b14e92b6e5073c3d20 100644 (file)
@@ -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 (file)
index 0000000..140c8f6
--- /dev/null
@@ -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 (file)
index 0000000..9ebc618
--- /dev/null
@@ -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 (file)
index 0000000..940c495
--- /dev/null
@@ -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 (file)
index 0000000..1202609
--- /dev/null
@@ -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 (file)
index 0000000..719d60e
--- /dev/null
@@ -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 (file)
index 0000000..b795d30
--- /dev/null
@@ -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 (file)
index 0000000..fe88147
--- /dev/null
@@ -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 (file)
index 0000000..8a94785
--- /dev/null
@@ -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 (file)
index 0000000..3b8f2dc
--- /dev/null
@@ -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 (file)
index 0000000..68bbe91
--- /dev/null
@@ -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 (executable)
index 0000000..94ba275
--- /dev/null
@@ -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 (file)
index 0000000..91a16e1
--- /dev/null
@@ -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 (file)
index 8b7493b..0000000
+++ /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 (executable)
index f33d412..0000000
+++ /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 (file)
index 5ef87b0..0000000
+++ /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 (file)
index 0000000..58b51ba
--- /dev/null
@@ -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 (file)
index 0000000..cf251f0
--- /dev/null
@@ -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 (file)
index 0000000..7861a91
--- /dev/null
@@ -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 (file)
index 0000000..6659309
--- /dev/null
@@ -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 (file)
index 0000000..825666a
--- /dev/null
@@ -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 (file)
index 0000000..4c9fbec
--- /dev/null
@@ -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 (file)
index 0000000..0e00ea0
--- /dev/null
@@ -0,0 +1,6 @@
+chain libreswan_input {}
+chain libreswan_nflog_input {}
+chain libreswan_forward {}
+chain libreswan_output {}
+chain libreswan_nflog_output {}
+chain libreswan_srcnat {}