123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252 |
- #!/bin/bash
- # VPN Client app for YunoHost
- # Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
- # Contribute at https://github.com/labriqueinternet/vpnclient_ynh
- #
- # This program is free software: you can redistribute it and/or modify
- # it under the terms of the GNU Affero General Public License as published by
- # the Free Software Foundation, either version 3 of the License, or
- # (at your option) any later version.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU Affero General Public License for more details.
- #
- # You should have received a copy of the GNU Affero General Public License
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
- ###################################################################################
- # Logging helpers #
- ###################################################################################
- LOGFILE="/var/log/ynh-vpnclient.log"
- touch $LOGFILE
- chown root:root $LOGFILE
- chmod 600 $LOGFILE
- function success()
- {
- echo "[ OK ] $1" | tee -a $LOGFILE
- }
- function info()
- {
- echo "[INFO] $1" | tee -a $LOGFILE
- }
- function warn()
- {
- echo "[WARN] $1" | tee -a $LOGFILE >&2
- }
- function error()
- {
- echo "[FAIL] $1" | tee -a $LOGFILE >&2
- }
- function critical()
- {
- echo "[CRIT] $1" | tee -a $LOGFILE >&2
- exit 1
- }
- ###################################################################################
- # Cleanup #
- ###################################################################################
- cleanup() {
- local last_exit_code="$?"
- if [[ "${action}" != "stop" && "${last_exit_code}" -ne 0 ]]; then
- rm -f /tmp/.ynh-vpnclient-started
- fi
- }
- # Cleanup before exit
- trap cleanup 0
- ###################################################################################
- # Time sync #
- ###################################################################################
- sync_time() {
- info "Now synchronizing time using ntp..."
- systemctl stop ntp
- timeout 20 ntpd -qg &> /dev/null
-
- # Some networks drop ntp port (udp 123).
- # Try to get the date with an http request on the internetcube web site
- if [ $? -ne 0 ]; then
- info "ntp synchronization failed, falling back to curl method"
- http_date=$(curl --max-time 5 -sD - yunohost.org | grep -i '^Date:' | cut -d' ' -f2-)
- http_date_seconds=$(date -d "${http_date}" +%s)
- curr_date_seconds=$(date +%s)
- # Set the new date if it's greater than the current date
- # So it does if 1970 year or if old fake-hwclock date is used
- if [ $http_date_seconds -ge $curr_date_seconds ]; then
- date -s "${http_date}"
- fi
- fi
- systemctl start ntp
- }
- ###################################################################################
- # The actual ynh vpnclient management thing #
- ###################################################################################
- check_config() {
- info "Checking if configuration is valid..."
- if [[ ! -e /etc/openvpn/keys/ca-server.crt ]]; then
- critical "You need a CA server (you can add it through the web admin)"
- fi
- if [[ ! -e /etc/openvpn/keys/user.crt || ! -e /etc/openvpn/keys/user.key ]]; then
- if [[ -s /etc/openvpn/keys/credentials ]]; then
- login_user=$(sed -n 1p /etc/openvpn/keys/credentials)
- login_passphrase=$(sed -n 2p /etc/openvpn/keys/credentials)
- else
- login_user=""
- login_passphrase=""
- fi
- if [[ $login_user == "" || $login_passphrase == "" ]]; then
- critical "You need either a client certificate, either a username, or both (you can add one through the web admin)"
- fi
- elif [[ -e /etc/openvpn/keys/user.crt ]] && ! openssl x509 -in /etc/openvpn/keys/user.crt -noout -checkend 0 >/dev/null; then
- user_cert_expired_date=$(openssl x509 -in /etc/openvpn/keys/user.crt -noout -enddate | cut -d '=' -f 2)
- critical "The client certificate expired on $user_cert_expired_date"
- fi
- }
- action=${1}
- if [[ "$action" != restart ]]; then
- # Variables
- info "Retrieving Yunohost settings... "
- ynh_service_enabled=$(yunohost app setting "vpnclient" "service_enabled")
- success "Settings retrieved"
- fi
- ###################################################################################
- # Start / stop / restart / status handling #
- ###################################################################################
- case "$action" in
- # ########## #
- # Starting #
- # ########## #
- start)
- info "[vpnclient] Starting..."
-
- if [[ -e /tmp/.ynh-vpnclient.started ]] || systemctl -q is-active openvpn@client.service; then
- info "Service is already running"
- exit 0
- elif [[ "${ynh_service_enabled}" -eq 0 ]]; then
- warn "Service is disabled, not starting it"
- exit 0
- fi
- touch /tmp/.ynh-vpnclient-started
- sync_time
- check_config
- info "Now actually starting OpenVPN client..."
- if systemctl start openvpn@client.service; then
- info "OpenVPN client started ... waiting for tun0 interface to show up"
- else
- tail -n 20 /var/log/openvpn-client.log | tee -a $LOGFILE
- critical "Failed to start OpenVPN :/"
- fi
- has_errors=true
- for attempt in $(seq 0 20); do
- sleep 1
- if ip link show dev tun0 &> /dev/null; then
- success "tun0 interface is up!"
- has_errors=false
- break
- fi
- done
-
- if $has_errors; then
- error "Tun0 interface did not show up ... most likely an issue happening in OpenVPN client ... below is an extract of the log that might be relevant to pinpoint the issue"
- tail -n 20 /var/log/openvpn-client.log | tee -a $LOGFILE
- systemctl stop openvpn@client.service
- critical "Failed to start OpenVPN client : tun0 interface did not show up"
- fi
- info "Waiting for VPN client to be ready..."
- if ! timeout 180 tail -n 0 -f /var/log/openvpn-client.log | grep -q "Initialization Sequence Completed"; then
- error "The VPN client didn't complete initiliasation"
- tail -n 20 /var/log/openvpn-client.log | tee -a $LOGFILE
- systemctl stop openvpn@client.service
- critical "Failed to start OpenVPN client"
- fi
- info "Validating that VPN is up and the server is connected to internet..."
- ipv4=$(timeout 5 ping -w3 -c1 ip.yunohost.org >/dev/null 2>&1 && curl --max-time 5 https://ip.yunohost.org --silent)
- ipv6=$(timeout 5 ping -w3 -c1 ip6.yunohost.org >/dev/null 2>&1 && curl --max-time 5 https://ip6.yunohost.org --silent)
- if ip route get 1.2.3.4 | grep -q tun0; then
- if timeout 5 ping -c1 -w3 debian.org >/dev/null; then
- success "YunoHost VPN client started!"
- info "IPv4 address is $ipv4"
- info "IPv6 address is $ipv6"
- else
- critical "The VPN is up but debian.org cannot be reached, indicating that something is probably misconfigured/blocked."
- fi
- else
- critical "IPv4 routes are misconfigured !?"
- fi
- ;;
- # ########## #
- # Stopping #
- # ########## #
- stop)
- info "[vpnclient] Stopping..."
- rm -f /tmp/.ynh-vpnclient-started
- if systemctl is-active -q openvpn@client.service; then
- info "Stopping OpenVPN service"
- systemctl stop openvpn@client.service
- for attempt in $(seq 0 20); do
- if ip link show dev tun0 &> /dev/null; then
- info "(Waiting for tun0 to disappear if it was up)"
- sleep 1
- fi
- done
- fi
- ;;
- # ########## #
- # Restart #
- # ########## #
- restart)
- $0 stop
- $0 start
- ;;
- # ########## #
- # Halp #
- # ########## #
- *)
- echo "Usage: $0 {start|stop|restart}"
- ;;
- esac
- exit 0
|