libreswan: uci configuration support

Add libreswan UCI configuration and hotplug support

Signed-off-by: Jaymin Patel <jem.patel@gmail.com>
This commit is contained in:
Jaymin Patel 2022-08-22 16:41:33 +05:30
parent a2ef62e669
commit 52af24ff56
23 changed files with 1218 additions and 104 deletions

View 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))

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,7 @@
#!/bin/sh
[ -e "/etc/ipsec.user" ] && {
. /etc/ipsec.user
}
exit 0

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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'
}

View File

@ -0,0 +1,3 @@
include /var/run/ipsec/setup.conf
include /var/run/ipsec/conf.d/*.conf
include /etc/ipsec.d/*.conf

View File

@ -0,0 +1,2 @@
include /var/run/ipsec/conf.d/*.secret
include /etc/ipsec.d/*.secrets

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
}

View File

@ -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

View File

@ -0,0 +1,3 @@
#!/bin/sh
/sbin/hotplug-call libreswan

View File

@ -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 "$@"

View File

@ -0,0 +1 @@
jump libreswan_forward

View File

@ -0,0 +1,2 @@
jump libreswan_nflog_input
jump libreswan_input

View File

@ -0,0 +1,2 @@
jump libreswan_nflog_output
jump libreswan_output

View File

@ -0,0 +1 @@
jump libreswan_srcnat

View File

@ -0,0 +1,6 @@
chain libreswan_input {}
chain libreswan_nflog_input {}
chain libreswan_forward {}
chain libreswan_output {}
chain libreswan_nflog_output {}
chain libreswan_srcnat {}