#!/bin/bash DIR=/config/vpn-management-site LOGFILE=/var/log/vpn-management-site.log set -eE err_report() { error="HTTP/1.1 500 Internal server error\n\nserver.sh: Error on line ${1}" echo -e error >> ${LOGFILE} echo -e error } trap 'err_report $LINENO' ERR # Read first line of HTTP request, set operation var OP="" IFS= read -r LINE_NL LINE=${LINE_NL::-1} if [[ "${LINE}" == "POST "* ]]; then OP="modify_vpn" elif [[ "${LINE}" == "GET /servers.json"* ]]; then OP="get_server_list" elif [[ "${LINE}" == "GET /"* ]]; then OP="get_html" else RESPONSE="HTTP/1.1 400 Bad Request\n\nInvalid HTTP prelude\n${LINE}" echo -e $RESPONSE >> ${LOGFILE} echo -e $RESPONSE fi # Find the content length (nc doesn't send an EOL) CONTENT_LENGTH=-1 while IFS= read -r LINE_NL; do LINE=${LINE_NL::-1} if [[ "${LINE}" == "Content-Length:"* ]]; then CONTENT_LENGTH=${LINE:16} elif [[ "${LINE}" == "" ]]; then break fi done # If the request is about a static resource, just send that if [[ "${OP}" == "get_html" ]]; then HTML=$(cat ${DIR}/index.html) RESPONSE="HTTP/1.1 200 OK\nContent-Type: text/html\n\n${HTML}" echo -e RESPONSE >> ${LOGFILE} echo -e RESPONSE exit 0 fi if [[ "${OP}" == "get_server_list" ]]; then JSON=$(cat ${DIR}/servers.json) RESPONSE="HTTP/1.1 200 OK\nContent-Type: application/json\n\n${JSON}" echo -e RESPONSE >> ${LOGFILE} echo -e RESPONSE exit 0 fi # Otherwise the request must be about setting the VPN state if [[ "${OP}" != "modify_vpn" ]]; then echo "Invalid operation ${OP}" >> ${LOGFILE} RESPONSE="HTTP/1.1 400 Bad Request\n\n" echo -e RESPONSE >> ${LOGFILE} echo -e RESPONSE fi # Read CONTENT_LENGTH worth of content IFS= read -n${CONTENT_LENGTH} -d$'\0' -r CONTENT # Read the action field from the content JSON (either enable or disable) ACTION=$(echo ${CONTENT} | jq -r .action) # Make router configuration commands available source /opt/vyatta/etc/functions/script-template > /dev/null # If action is disable, disable the openvpn interface if [[ "${ACTION}" == "disable" ]]; then echo "Disabling VPN..." >> ${LOGFILE} configure 2>&1 >> ${LOGFILE} set interfaces openvpn vtun0 disable 2>&1 >> ${LOGFILE} commit 2>&1 >> ${LOGFILE} save 2>&1 >> ${LOGFILE} RESPONSE="HTTP/1.1 200 OK\n\nVPN disabled" echo -e RESPONSE >> ${LOGFILE} echo -e RESPONSE exit 0 fi # Otherwise the action must be enable if [[ "${ACTION}" != "enable" ]]; then echo "Invalid action ${ACTION}" >> ${LOGFILE} RESPONSE="HTTP/1.1 400 Bad Request\n\nInvalid action ${ACTION}" echo -e RESPONSE >> ${LOGFILE} echo -e RESPONSE exit 1 fi echo "Enabling VPN..." >> ${LOGFILE} # Read the VPN server domain and IP from the request content JSON DOMAIN=$(echo ${CONTENT} | jq -r .domain) IP=$(echo ${CONTENT} | jq -r .ip) # Produce an openvpn config cat > /config/openvpn/vpn.ovpn <<- ENDOUT client dev tun proto udp remote ${IP} 1194 resolv-retry infinite remote-random nobind tun-mtu 1500 tun-mtu-extra 32 mssfix 1450 persist-key persist-tun ping 15 ping-restart 0 ping-timer-rem reneg-sec 0 comp-lzo no verify-x509-name CN=${DOMAIN} remote-cert-tls server auth-user-pass /config/openvpn/nordvpnauth.txt route-nopull verb 3 pull fast-io cipher AES-256-CBC auth SHA512 -----BEGIN CERTIFICATE----- MIIFCjCCAvKgAwIBAgIBATANBgkqhkiG9w0BAQ0FADA5MQswCQYDVQQGEwJQQTEQ MA4GA1UEChMHTm9yZFZQTjEYMBYGA1UEAxMPTm9yZFZQTiBSb290IENBMB4XDTE2 MDEwMTAwMDAwMFoXDTM1MTIzMTIzNTk1OVowOTELMAkGA1UEBhMCUEExEDAOBgNV BAoTB05vcmRWUE4xGDAWBgNVBAMTD05vcmRWUE4gUm9vdCBDQTCCAiIwDQYJKoZI hvcNAQEBBQADggIPADCCAgoCggIBAMkr/BYhyo0F2upsIMXwC6QvkZps3NN2/eQF kfQIS1gql0aejsKsEnmY0Kaon8uZCTXPsRH1gQNgg5D2gixdd1mJUvV3dE3y9FJr XMoDkXdCGBodvKJyU6lcfEVF6/UxHcbBguZK9UtRHS9eJYm3rpL/5huQMCppX7kU eQ8dpCwd3iKITqwd1ZudDqsWaU0vqzC2H55IyaZ/5/TnCk31Q1UP6BksbbuRcwOV skEDsm6YoWDnn/IIzGOYnFJRzQH5jTz3j1QBvRIuQuBuvUkfhx1FEwhwZigrcxXu MP+QgM54kezgziJUaZcOM2zF3lvrwMvXDMfNeIoJABv9ljw969xQ8czQCU5lMVmA 37ltv5Ec9U5hZuwk/9QO1Z+d/r6Jx0mlurS8gnCAKJgwa3kyZw6e4FZ8mYL4vpRR hPdvRTWCMJkeB4yBHyhxUmTRgJHm6YR3D6hcFAc9cQcTEl/I60tMdz33G6m0O42s Qt/+AR3YCY/RusWVBJB/qNS94EtNtj8iaebCQW1jHAhvGmFILVR9lzD0EzWKHkvy WEjmUVRgCDd6Ne3eFRNS73gdv/C3l5boYySeu4exkEYVxVRn8DhCxs0MnkMHWFK6 MyzXCCn+JnWFDYPfDKHvpff/kLDobtPBf+Lbch5wQy9quY27xaj0XwLyjOltpiST LWae/Q4vAgMBAAGjHTAbMAwGA1UdEwQFMAMBAf8wCwYDVR0PBAQDAgEGMA0GCSqG SIb3DQEBDQUAA4ICAQC9fUL2sZPxIN2mD32VeNySTgZlCEdVmlq471o/bDMP4B8g nQesFRtXY2ZCjs50Jm73B2LViL9qlREmI6vE5IC8IsRBJSV4ce1WYxyXro5rmVg/ k6a10rlsbK/eg//GHoJxDdXDOokLUSnxt7gk3QKpX6eCdh67p0PuWm/7WUJQxH2S DxsT9vB/iZriTIEe/ILoOQF0Aqp7AgNCcLcLAmbxXQkXYCCSB35Vp06u+eTWjG0/ pyS5V14stGtw+fA0DJp5ZJV4eqJ5LqxMlYvEZ/qKTEdoCeaXv2QEmN6dVqjDoTAo k0t5u4YRXzEVCfXAC3ocplNdtCA72wjFJcSbfif4BSC8bDACTXtnPC7nD0VndZLp +RiNLeiENhk0oTC+UVdSc+n2nJOzkCK0vYu0Ads4JGIB7g8IB3z2t9ICmsWrgnhd NdcOe15BincrGA8avQ1cWXsfIKEjbrnEuEk9b5jel6NfHtPKoHc9mDpRdNPISeVa wDBM1mJChneHt59Nh8Gah74+TM1jBsw4fhJPvoc7Atcg740JErb904mZfkIEmojC VPhBHVQ9LHBAdM8qFI2kRK0IynOmAZhexlP/aT/kpEsEPyaZQlnBn3An1CRz8h0S PApL8PytggYKeQmRhl499+6jLxcZ2IegLfqq41dzIjwHwTMplg+1pKIOVojpWA== -----END CERTIFICATE----- key-direction 1 # # 2048 bit OpenVPN static key # -----BEGIN OpenVPN Static key V1----- e685bdaf659a25a200e2b9e39e51ff03 0fc72cf1ce07232bd8b2be5e6c670143 f51e937e670eee09d4f2ea5a6e4e6996 5db852c275351b86fc4ca892d78ae002 d6f70d029bd79c4d1c26cf14e9588033 cf639f8a74809f29f72b9d58f9b8f5fe fc7938eade40e9fed6cb92184abb2cc1 0eb1a296df243b251df0643d53724cdb 5a92a1d6cb817804c4a9319b57d53be5 80815bcfcb2df55018cc83fc43bc7ff8 2d51f9b88364776ee9d12fc85cc7ea5b 9741c4f598c485316db066d52db4540e 212e1518a9bd4828219e24b20d88f598 a196c9de96012090e333519ae18d3509 9427e7b372d348d352dc4c85e18cd4b9 3f8a56ddb2e64eb67adfc9b337157ff4 -----END OpenVPN Static key V1----- ENDOUT # Cycle the openvpn interface off and on to force config reload configure 2>&1 >> ${LOGFILE} set interfaces openvpn vtun0 disable 2>&1 >> ${LOGFILE} commit 2>&1 >> ${LOGFILE} delete interfaces openvpn vtun0 disable 2>&1 >> ${LOGFILE} commit 2>&1 >> ${LOGFILE} save 2>&1 >> ${LOGFILE} # Send OK response RESPONSE="HTTP/1.1 200 OK\n\nVPN enabled, IP: ${IP}, domain: ${DOMAIN}" echo -e RESPONSE >> ${LOGFILE} echo -e RESPONSE exit 0