diff --git a/net/openfortivpn/Makefile b/net/openfortivpn/Makefile index e59a9657e..84148c435 100644 --- a/net/openfortivpn/Makefile +++ b/net/openfortivpn/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=openfortivpn -PKG_VERSION:=1.14.1 -PKG_RELEASE:=8 +PKG_VERSION:=1.15.0 +PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/adrienverge/openfortivpn/tar.gz/v$(PKG_VERSION)? -PKG_HASH:=bc62fc6ecaaa6c6f8f2510e14a067a0cb9762158d9460c04555990bba44b50ca +PKG_HASH:=5279dbd3da779b818d201bbd9243cff9421a7e790fd2190438610a03c88641f8 PKG_MAINTAINER:=Lucian Cristian PKG_LICENSE:=GPL-3.0-or-later OpenSSL @@ -32,7 +32,7 @@ define Package/openfortivpn CATEGORY:=Network TITLE:=Fortinet SSL VPN client URL:=https://github.com/adrienverge/openfortivpn - DEPENDS:=+ppp +libopenssl +resolveip + DEPENDS:=+ppp +libopenssl endef define Package/openfortivpn/description @@ -59,7 +59,6 @@ define Package/openfortivpn/install $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/openfortivpn $(1)/usr/sbin/ $(INSTALL_BIN) ./files/openfortivpn-wrapper $(1)/usr/sbin/ $(INSTALL_BIN) ./files/openfortivpn.sh $(1)/lib/netifd/proto/ - $(INSTALL_BIN) ./files/14-openforticlient $(1)/etc/hotplug.d/iface/ $(INSTALL_BIN) ./files/openfortivpn-ppp-up $(1)/lib/netifd/openfortivpn-ppp-up endef diff --git a/net/openfortivpn/files/14-openforticlient b/net/openfortivpn/files/14-openforticlient deleted file mode 100644 index a9a24b18b..000000000 --- a/net/openfortivpn/files/14-openforticlient +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/sh -. /lib/functions.sh -. /usr/share/libubox/jshn.sh -[ "$ACTION" != ifup ] && exit - -handle_network() -{ - config_get iface $1 iface_name - [ $INTERFACE != "$iface" ] && return - [ $(config_get $1 proto) != "openfortivpn" ] && return - - config_get_bool load_on_boot $1 auto - [ -n "$load_on_boot" ] && [ "$load_on_boot" -eq 0 ] && return - status="$(ifstatus $1)" || continue - json_load "$status" - json_get_var autostart autostart - logger -t "openfortivpnhotplug" "$ACTION on $INTERFACE to bring up $1. Autostart is $autostart" - [ "$autostart" -eq 0 ] && { - logger -t "openfortivpnhotplug" "auto-start was false. bringing $1 up" - ubus call network.interface up "{ \"interface\" : \"$1\" }" - } -} - - -config_load network -config_foreach handle_network interface -exit 0 diff --git a/net/openfortivpn/files/openfortivpn.sh b/net/openfortivpn/files/openfortivpn.sh index 14f613eab..9414591dd 100755 --- a/net/openfortivpn/files/openfortivpn.sh +++ b/net/openfortivpn/files/openfortivpn.sh @@ -3,6 +3,7 @@ . /lib/functions/network.sh . ../netifd-proto.sh init_proto "$@" +IPv4_REGEX="((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)" append_args() { while [ $# -gt 0 ]; do @@ -27,7 +28,7 @@ proto_openfortivpn_init_config() { proto_openfortivpn_setup() { local config="$1" - local msg ifname ip server_ip pwfile callfile + local msg ifname ip server_ips pwfile callfile local host peeraddr port tunlink local_ip username password trusted_cert \ remote_status_check @@ -38,53 +39,72 @@ proto_openfortivpn_setup() { [ -n "$tunlink" ] && { - network_get_device iface_device_name "$tunlink" - network_is_up "$tunlink" || { - msg="$tunlink is not up $iface_device_up" - logger -t "openfortivpn" "$config: $msg" - proto_notify_error "$config" "$msg" - proto_block_restart "$config" - exit 1 - } + network_get_device iface_device_name "$tunlink" + network_is_up "$tunlink" || { + msg="$tunlink is not up $iface_device_up" + logger -t "openfortivpn" "$config: $msg" + proto_notify_error "$config" "$msg" + proto_block_restart "$config" + exit 1 + } } - server_ip=$(resolveip -4 -t 10 "$peeraddr") + if echo "$peeraddr" | grep -q -E "$IPv4_REGEX"; then + server_ips="$peeraddr" + elif command -v resolveip >/dev/null ; then + server_ips="$(resolveip -4 -t 10 "$peeraddr")" + [ $? -eq 0 ] || { + msg="$config: failed to resolve server ip for $peeraddr" + logger -t "openfortivpn" "$msg" + sleep 10 + proto_notify_error "$config" "$msg" + proto_setup_failed "$config" + exit 1 + } + else + logger -t "openfortivpn" "resolveip not present, could not resolve $peeraddr" + fi - [ $? -eq 0 ] || { - msg="$config: failed to resolve server ip for $peeraddr" - logger -t "openfortivpn" "$msg" - sleep 10 - proto_notify_error "$config" "$msg" - proto_setup_failed "$config" - exit 1 - } [ "$remote_status_check" = "curl" ] && { - curl -k --head -s --connect-timeout 10 ${tunlink:+--interface} $iface_device_name https://$server_ip > /dev/null || { - msg="failed to reach https://${server_ip}${tunlink:+ on $iface_device_name}" - logger -t "openfortivpn" "$config: $msg" - sleep 10 - proto_notify_error "$config" "$msg" - proto_setup_failed "$config" - exit 1 - } + curl -k --head -s --connect-timeout 10 ${tunlink:+--interface} $iface_device_name https://$peeraddr > /dev/null || { + msg="failed to reach https://$peeraddr${tunlink:+ on $iface_device_name}" + logger -t "openfortivpn" "$config: $msg" + sleep 10 + proto_notify_error "$config" "$msg" + proto_setup_failed "$config" + exit 1 + } } [ "$remote_status_check" = "ping" ] && { - ping ${tunlink:+-I} $iface_device_name -c 1 -w 10 $server_ip > /dev/null 2>&1 || { - msg="$config: failed to ping $server_ip on $iface_device_name" - logger -t "openfortvpn" "$config: $msg" - sleep 10 - proto_notify_error "$config" "failed to ping $server_ip on $iface_device_name" - proto_setup_failed "$config" - exit 1 - } + ping ${tunlink:+-I} $iface_device_name -c 1 -w 10 $peeraddr > /dev/null 2>&1 || { + msg="$config: failed to ping $peeraddr on $iface_device_name" + logger -t "openfortvpn" "$config: $msg" + sleep 10 + proto_notify_error "$config" "$msg" + proto_setup_failed "$config" + exit 1 + } } - for ip in $(resolveip -4 -t 10 "$peeraddr"); do - logger -p 6 -t "openfortivpn" "$config: adding host dependency for $ip on $tunlink at $config" - proto_add_host_dependency "$config" "$ip" "$tunlink" - done - + if [ -n "$server_ips" ]; then + for ip in $server_ips; do + logger -p 6 -t "openfortivpn" "$config: adding host dependency for $ip on $tunlink at $config" + proto_add_host_dependency "$config" "$ip" "$tunlink" + done + fi + + # uclient-fetch cannot bind to interface, so perform check after adding host dependency + [ "$remote_status_check" = "fetch" ] && { + uclient-fetch --no-check-certificate -q -s --timeout=10 https://$peeraddr > /dev/null 2>&1 || { + msg="$config: failed to reach ${server_ip:-$peeraddr} on $iface_device_name" + logger -t "openfortvpn" "$config: $msg" + sleep 10 + proto_notify_error "$config" "$msg" + proto_setup_failed "$config" + exit 1 + } + } [ -n "$port" ] && port=":$port" @@ -106,7 +126,7 @@ proto_openfortivpn_setup() { echo "$password" > "$pwfile" } - [ -n "$local_ip" ] || local_ip=$server_ip + [ -n "$local_ip" ] || local_ip=192.0.2.1 [ -e '/etc/ppp/peers' ] || mkdir -p '/etc/ppp/peers' [ -e '/etc/ppp/peers/openfortivpn' ] || { ln -s -T '/var/etc/openfortivpn/peers' '/etc/ppp/peers/openfortivpn' 2> /dev/null diff --git a/net/openfortivpn/patches/010-bind-iface.patch b/net/openfortivpn/patches/010-bind-iface.patch deleted file mode 100644 index 76bc8c84f..000000000 --- a/net/openfortivpn/patches/010-bind-iface.patch +++ /dev/null @@ -1,182 +0,0 @@ ---- a/doc/openfortivpn.1.in -+++ b/doc/openfortivpn.1.in -@@ -12,6 +12,7 @@ openfortivpn \- Client for PPP+SSL VPN t - [\fB\-\-otp\-prompt=\fI\fR] - [\fB\-\-otp\-delay=\fI\fR] - [\fB\-\-realm=\fI\fR] -+[\fB\-\-ifname=\fI\fR] - [\fB\-\-set\-routes=\fR] - [\fB\-\-no\-routes\fR] - [\fB\-\-set\-dns=\fR] -@@ -83,6 +84,9 @@ no wait (this is the default). - Connect to the specified authentication realm. Defaults to empty, which - is usually what you want. - .TP -+\fB\-\-ifname=\fI\fR -+Bind the connection to the specified network interface. -+.TP - \fB\-\-set\-routes=\fI\fR, \fB\-\-no-routes\fR - Set if openfortivpn should try to configure IP routes through the VPN when - tunnel is up. If used multiple times, the last one takes priority. ---- a/src/config.c -+++ b/src/config.c -@@ -50,6 +50,7 @@ const struct vpn_config invalid_cfg = { - .otp_delay = -1, - .pinentry = NULL, - .realm = {'\0'}, -+ .iface_name = {'\0'}, - .set_routes = -1, - .set_dns = -1, - .pppd_use_peerdns = -1, -@@ -490,6 +491,8 @@ void merge_config(struct vpn_config *dst - } - if (src->realm[0]) - strcpy(dst->realm, src->realm); -+ if (src->iface_name[0]) -+ strcpy(dst->iface_name, src->iface_name); - if (src->set_routes != invalid_cfg.set_routes) - dst->set_routes = src->set_routes; - if (src->set_dns != invalid_cfg.set_dns) ---- a/src/config.h -+++ b/src/config.h -@@ -86,6 +86,7 @@ struct vpn_config { - char *otp_prompt; - unsigned int otp_delay; - char *pinentry; -+ char iface_name[FIELD_SIZE + 1]; - char realm[FIELD_SIZE + 1]; - - int set_routes; ---- a/src/main.c -+++ b/src/main.c -@@ -51,16 +51,16 @@ - " resolver and routes directly.\n" \ - " --pppd-ifname= Set the pppd interface name, if supported by pppd.\n" \ - " --pppd-ipparam= Provides an extra parameter to the ip-up, ip-pre-up\n" \ --" and ip-down scripts. See man (8) pppd\n" \ -+" and ip-down scripts. See man (8) pppd.\n" \ - " --pppd-call= Move most pppd options from pppd cmdline to\n" \ - " /etc/ppp/peers/ and invoke pppd with\n" \ --" 'call '\n" -+" 'call '.\n" - #elif HAVE_USR_SBIN_PPP - #define PPPD_USAGE \ - " [--ppp-system=]\n" - #define PPPD_HELP \ - " --ppp-system= Connect to the specified system as defined in\n" \ --" /etc/ppp/ppp.conf\n" -+" /etc/ppp/ppp.conf.\n" - #else - #error "Neither HAVE_USR_SBIN_PPPD nor HAVE_USR_SBIN_PPP have been defined." - #endif -@@ -69,7 +69,7 @@ - #define RESOLVCONF_USAGE \ - "[--use-resolvconf=<0|1>] " - #define RESOLVCONF_HELP \ --" --use-resolvconf=[01] If possible use resolvconf to update /etc/resolv.conf\n" -+" --use-resolvconf=[01] If possible use resolvconf to update /etc/resolv.conf.\n" - #else - #define RESOLVCONF_USAGE "" - #define RESOLVCONF_HELP "" -@@ -77,14 +77,14 @@ - - #define usage \ - "Usage: openfortivpn [[:]] [-u ] [-p ]\n" \ --" [--pinentry=]\n" \ --" [--realm=] [--otp=] [--otp-delay=]\n" \ --" [--otp-prompt=] [--set-routes=<0|1>]\n" \ -+" [--otp=] [--otp-delay=] [--otp-prompt=]\n" \ -+" [--pinentry=] [--realm=]\n" \ -+" [--ifname=] [--set-routes=<0|1>]\n" \ - " [--half-internet-routes=<0|1>] [--set-dns=<0|1>]\n" \ - PPPD_USAGE \ - " " RESOLVCONF_USAGE "[--ca-file=]\n" \ - " [--user-cert=] [--user-key=]\n" \ --" [--trusted-cert=] [--use-syslog]\n" \ -+" [--use-syslog] [--trusted-cert=]\n" \ - " [--persistent=] [-c ] [-v|-q]\n" \ - " openfortivpn --help\n" \ - " openfortivpn --version\n" \ -@@ -115,10 +115,11 @@ PPPD_USAGE \ - " -u , --username= VPN account username.\n" \ - " -p , --password= VPN account password.\n" \ - " -o , --otp= One-Time-Password.\n" \ --" --otp-prompt= Search for the OTP prompt starting with this string\n" \ -+" --otp-prompt= Search for the OTP prompt starting with this string.\n" \ - " --otp-delay= Wait seconds before sending the OTP.\n" \ --" --pinentry= Use the program to supply a secret instead of asking for it\n" \ -+" --pinentry= Use the program to supply a secret instead of asking for it.\n" \ - " --realm= Use specified authentication realm.\n" \ -+" --ifname= Bind to interface.\n" \ - " --set-routes=[01] Set if openfortivpn should configure routes\n" \ - " when tunnel is up.\n" \ - " --no-routes Do not configure routes, same as --set-routes=0.\n" \ -@@ -127,7 +128,7 @@ PPPD_USAGE \ - " --set-dns=[01] Set if openfortivpn should add DNS name servers\n" \ - " and domain search list in /etc/resolv.conf.\n" \ - " If installed resolvconf is used for the update.\n" \ --" --no-dns Do not reconfigure DNS, same as --set-dns=0\n" \ -+" --no-dns Do not reconfigure DNS, same as --set-dns=0.\n" \ - " --ca-file= Use specified PEM-encoded certificate bundle\n" \ - " instead of system-wide store to verify the gateway\n" \ - " certificate.\n" \ -@@ -199,6 +200,7 @@ int main(int argc, char **argv) - .otp_delay = 0, - .pinentry = NULL, - .realm = {'\0'}, -+ .iface_name = {'\0'}, - .set_routes = 1, - .set_dns = 1, - .use_syslog = 0, -@@ -245,6 +247,7 @@ int main(int argc, char **argv) - {"otp", required_argument, NULL, 'o'}, - {"otp-prompt", required_argument, NULL, 0}, - {"otp-delay", required_argument, NULL, 0}, -+ {"ifname", required_argument, NULL, 0}, - {"set-routes", required_argument, NULL, 0}, - {"no-routes", no_argument, &cli_cfg.set_routes, 0}, - {"half-internet-routes", required_argument, NULL, 0}, -@@ -427,6 +430,12 @@ int main(int argc, char **argv) - break; - } - if (strcmp(long_options[option_index].name, -+ "ifname") == 0) { -+ strncpy(cli_cfg.iface_name, optarg, FIELD_SIZE); -+ cli_cfg.iface_name[FIELD_SIZE] = '\0'; -+ break; -+ } -+ if (strcmp(long_options[option_index].name, - "set-routes") == 0) { - int set_routes = strtob(optarg); - ---- a/src/tunnel.c -+++ b/src/tunnel.c -@@ -523,12 +523,28 @@ static int tcp_connect(struct tunnel *tu - int ret, handle; - struct sockaddr_in server; - char *env_proxy; -+ const int iface_len = strnlen(tunnel->config->iface_name, IFNAMSIZ); - - handle = socket(AF_INET, SOCK_STREAM, 0); -+ - if (handle == -1) { - log_error("socket: %s\n", strerror(errno)); - goto err_socket; - } -+ if (iface_len == IFNAMSIZ) { -+ log_error("socket: Too long iface name"); -+ goto err_socket; -+ } -+ if (iface_len > 0) { -+ ret = setsockopt(handle, SOL_SOCKET, SO_BINDTODEVICE, -+ tunnel->config->iface_name, iface_len); -+ if (ret) { -+ log_error("socket: setting interface name failed with error: %d", -+ errno); -+ goto err_socket; -+ } -+ } -+ - env_proxy = getenv("https_proxy"); - if (env_proxy == NULL) - env_proxy = getenv("HTTPS_PROXY");