diff --git a/Dockerfile b/Dockerfile old mode 100644 new mode 100755 index 4ece3147..c984c54e --- a/Dockerfile +++ b/Dockerfile @@ -1,13 +1,13 @@ -# Original credit: https://github.com/jpetazzo/dockvpn +# Original credit: https://github.com/kylemanna/docker-openvpn # Smallest base image FROM alpine:latest -LABEL maintainer="Kyle Manna " +LABEL maintainer="Nanda Bhikkhu " # Testing: pamtester RUN echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing/" >> /etc/apk/repositories && \ - apk add --update openvpn iptables bash easy-rsa openvpn-auth-pam google-authenticator pamtester libqrencode && \ + apk add --update openvpn iptables bash easy-rsa openvpn-auth-pam google-authenticator pamtester libqrencode lighttpd lighttpd-mod_auth coreutils && \ ln -s /usr/share/easy-rsa/easyrsa /usr/local/bin && \ rm -rf /tmp/* /var/tmp/* /var/cache/apk/* /var/cache/distfiles/* @@ -15,17 +15,32 @@ RUN echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing/" >> /etc/apk/reposi ENV OPENVPN=/etc/openvpn ENV EASYRSA=/usr/share/easy-rsa \ EASYRSA_CRL_DAYS=3650 \ - EASYRSA_PKI=$OPENVPN/pki + EASYRSA_CERT_RENEW=3650 \ + EASYRSA_PKI=$OPENVPN/pki \ + EASYRSA_BATCH=1 \ + OVPN_USER=openvpn \ + OVPN_GROUP=openvpn + +ADD ./lighttpd/htdocs/ /var/www/localhost/htdocs/ +ADD ./lighttpd/config/* /etc/lighttpd/ +RUN OPENVPN=$(echo $OPENVPN | sed -e 's/\//\\\//g') && sed -i /etc/lighttpd/lighttpd.conf -e 's/server\.username.*/server.username\ =\ "'$OVPN_USER'"/' \ + -e 's/server\.groupname.*/server.groupname\ =\ "'$OVPN_GROUP'"/' \ + -e 's/^var\.ovpndir.*$/var.ovpndir\ =\ "'${OPENVPN}'"/' && \ + chown -R ${OVPN_USER}:${OVPN_GROUP} /var/www/localhost/htdocs /etc/lighttpd /var/log/lighttpd + +ADD ./bin /usr/local/bin +RUN chmod 755 /usr/local/bin/* && chown root:${OVPN_GROUP} /usr/local/bin/* + +# Add support for OTP authentication using a PAM module +ADD ./otp/openvpn /etc/pam.d/ VOLUME ["/etc/openvpn"] +VOLUME ["/var/log"] # Internally uses port 1194/udp, remap using `docker run -p 443:1194/tcp` EXPOSE 1194/udp +EXPOSE 443/tcp CMD ["ovpn_run"] +USER $OVPN_USER:$OVPN_GROUP -ADD ./bin /usr/local/bin -RUN chmod a+x /usr/local/bin/* - -# Add support for OTP authentication using a PAM module -ADD ./otp/openvpn /etc/pam.d/ diff --git a/README.md b/README.md index a9106737..63081b25 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ a corresponding [Digital Ocean Community Tutorial](http://bit.ly/1AGUZkq). * Start OpenVPN server process - docker run -v $OVPN_DATA:/etc/openvpn -d -p 1194:1194/udp --cap-add=NET_ADMIN kylemanna/openvpn + docker run --user root -v $OVPN_DATA:/etc/openvpn -v $OVPN_LOGS:/var/log -d -p 1194:1194/udp -p 443:443 --cap-add=NET_ADMIN kylemanna/openvpn * Generate a client certificate without a passphrase @@ -132,6 +132,19 @@ and they might not answer to you. If that happens, use public DNS resolvers like those of Google (8.8.4.4 and 8.8.8.8) or OpenDNS (208.67.222.222 and 208.67.220.220). +## Https user admin +If you wish to use https interface for configuring the clients +* Pass -H to ovpn_genconfig + docker run -v $OVPN_DATA:/etc/openvpn -v $OVPN_LOG:/var/log -H --rm kylemanna/openvpn ovpn_genconfig -u udp://VPN.SERVERNAME.COM +It will ask you to specify username/password for the interface & for domain name for https certificate +* If you wish to supply your certificate/key for the https server, place it in $OPENVPN/http/ and set ownership and access rights. + cp server.pem server.key $OPENVPN/http/ + chown 101:102 $OPENVPN/http/server* + chmod 600 $OPENVPN/http/server.key + chmod 644 $OPENVPN/http/server.cer +* Be aware that the lighttpd log files are not logrotated. + +NOTE: requires easy-rsa 3.0.8 or higher (make sure you make the docker image from alpine 3.13 or so) ## Security Discussion diff --git a/bin/openssl-htpasswd b/bin/openssl-htpasswd new file mode 100755 index 00000000..d807419c --- /dev/null +++ b/bin/openssl-htpasswd @@ -0,0 +1,70 @@ +#!/bin/bash +# + +print_help() +{ + echo "$(basename \"$0\") [-Dci] passwdfile username [password]" + echo -e "\t-D delete given user" + echo -e "\t-c truncate file (will contain only new user" + echo -e "\t-i read password from stdin" + echo -e "\t-h print this help" +} + +ensure_pwd() +{ + [ "$STDIN" = 1 ] && read -s PWD + [ -z "$PWD" ] && echo "missing or empty password" >&2 && print_help >&2 && exit 1 + PWD=$(openssl passwd -6 "$PWD") +} + +action="modify" +while getopts "Dcid" arg; do + case $arg in + D) + action="delete" + ;; + c) + action="create" + ;; + i) + STDIN=1 + ;; + *) + echo "invalid usage" >&2 + print_help >&2 + exit 1 + ;; + esac +done +shift $(($OPTIND - 1)) + +FILE="$1" +USER="$2" +PWD="$3" + +[ -z "$USER" ] && echo "missing username" >&2 && print_help >&2 && exit 1 +[ -z "$FILE" ] && echo "missing filename" >&2 && print_help >&2 + +case "$action" in + delete) + [ ! -f "$FILE" ] && exit 0 + tmp=$(mktemp) + grep -v "^$USER:" "$FILE" > "$tmp" + cat "$tmp" > "$FILE" && rm "$tmp" && exit 0 + ;; + + create) + ensure_pwd + echo "$USER:$PWD" > "$FILE" && exit 0 + ;; + + modify) + ensure_pwd + tmp=$(mktemp) + (grep -v "^$USER:" "$FILE" 2>/dev/null; echo "$USER:$PWD") > "$tmp" && cat "$tmp" > "$FILE" && rm "$tmp" && exit 0 + ;; +esac + +# should not reach here +exit 1 + diff --git a/bin/ovpn_genconfig b/bin/ovpn_genconfig index c2ebca6c..9267226f 100755 --- a/bin/ovpn_genconfig +++ b/bin/ovpn_genconfig @@ -89,6 +89,7 @@ usage() { echo " [-p PUSH ...]" echo " [-r ROUTE ...]" echo " [-s SERVER_SUBNET]" + echo " [-H]" echo echo "optional arguments:" echo " -2 Enable two factor authentication using Google Authenticator." @@ -104,6 +105,7 @@ usage() { echo " -t Use TAP device (instead of TUN device)" echo " -T Encrypt packets with the given cipher algorithm instead of the default one (tls-cipher)." echo " -z Enable comp-lzo compression." + echo " -H Enable admin https server" } process_route_config() { @@ -129,6 +131,21 @@ process_extra_config() { [[ -n "$ovpn_extra_config" ]] && echo "$ovpn_extra_config" >> "$TMP_EXTRA_CONFIGFILE" } +gen_lighttpd_config() { + read -p "https username:" http_user || return 1 + read -sp "$http_user password:" http_password || return 1 + openssl-htpasswd "$OPENVPN/http/htpasswd" "$http_user" "$http_password" + + if [ ! -f "$OPENVPN/http/server.key" ]; then + echo "generating https server cert..." + read -p "https server domain/ip:" cn || return 1 + openssl req -x509 -newkey rsa:4096 -nodes -subj "/CN=$cn" -keyout "$OPENVPN/http/server.key" -out "$OPENVPN/http/server.pem" -days +365 || return 1 + chown openvpn:openvpn "$OPENVPN"/http/server.* + fi + + return 0 +} + if [ "${DEBUG:-}" == "1" ]; then set -x fi @@ -167,12 +184,15 @@ OVPN_ROUTES=() OVPN_SERVER=192.168.255.0/24 OVPN_SERVER_URL='' OVPN_TLS_CIPHER='' +OVPN_HTTPS_ADMIN=0 +OVPN_USER=openvpn +OVPN_GROUP=openvpn # Import existing configuration if present [ -r "$OVPN_ENV" ] && source "$OVPN_ENV" # Parse arguments -while getopts ":a:e:E:C:T:r:s:du:bcp:n:k:DNm:f:tz2" opt; do +while getopts ":a:e:E:C:T:r:s:du:bcp:n:k:DNm:f:tz2H" opt; do case $opt in a) OVPN_AUTH="$OPTARG" @@ -253,6 +273,9 @@ while getopts ":a:e:E:C:T:r:s:du:bcp:n:k:DNm:f:tz2" opt; do f) OVPN_FRAGMENT="$OPTARG" ;; + H) + OVPN_HTTPS_ADMIN=1 + ;; \?) set +x echo "Invalid option: -$OPTARG" >&2 @@ -409,4 +432,9 @@ if diff -q "${bak:-}" "$conf" 2>/dev/null; then rm -fv "$bak" fi +[ "$OVPN_HTTPS_ADMIN" = 1 ] && gen_lighttpd_config + +# just to be sure if someone run this as root +chown -R openvpn:openvpn "$OPENVPN" "/var/www" "/etc/lighttpd" + echo "Successfully generated config" diff --git a/bin/ovpn_run b/bin/ovpn_run index e93201bc..529c6198 100755 --- a/bin/ovpn_run +++ b/bin/ovpn_run @@ -54,6 +54,9 @@ addArg "--config" "$OPENVPN/openvpn.conf" source "$OPENVPN/ovpn_env.sh" +[ -n "${OVPN_USER}" ] && addArg "--user" "${OVPN_USER}" +[ -n "${OVPN_GROUP}" ] && addArg "--group" "${OVPN_GROUP}" + mkdir -p /dev/net if [ ! -c /dev/net/tun ]; then mknod /dev/net/tun c 10 200 @@ -101,5 +104,18 @@ if [ $? = 0 ]; then fi fi +chown -R openvpn:openvpn "$OPENVPN" + +echo "running https admin iface" +if [ "$OVPN_HTTPS_ADMIN" = 1 ]; then + env | grep EASYRSA | while read line; do echo "export $line"; done > $OPENVPN/http/easyrsa.env && chown openvpn $OPENVPN/http/easyrsa.env + lighttpd -f /etc/lighttpd/lighttpd.conf +fi + +# TODO: ovpn user echo "Running 'openvpn ${ARGS[@]} ${USER_ARGS[@]}'" exec openvpn ${ARGS[@]} ${USER_ARGS[@]} + +echo "shutting down https admin iface" +[ "$OVPN_HTTPS_ADMIN" = 1 ] && [ -f /var/run/lighttpd.pid ] && kill -TERM $(cat /var/run/lighttpd.pid) + diff --git a/lighttpd/config/lighttpd.conf b/lighttpd/config/lighttpd.conf new file mode 100644 index 00000000..95ab1c7a --- /dev/null +++ b/lighttpd/config/lighttpd.conf @@ -0,0 +1,287 @@ +############################################################################### +# Default lighttpd.conf for Gentoo. +# $Header: /var/cvsroot/gentoo-x86/www-servers/lighttpd/files/conf/lighttpd.conf,v 1.3 2005/09/01 14:22:35 ka0ttic Exp $ +############################################################################### + +# {{{ variables +var.basedir = "/var/www/localhost" +var.logdir = "/var/log/lighttpd" +var.statedir = "/var/lib/lighttpd" +var.ovpndir = "/etc/openvpn" +# }}} + +# {{{ modules +# At the very least, mod_access and mod_accesslog should be enabled. +# All other modules should only be loaded if necessary. +# NOTE: the order of modules is important. +server.modules = ( +# "mod_rewrite", +# "mod_redirect", +# "mod_alias", + "mod_access", +# "mod_cml", +# "mod_trigger_b4_dl", + "mod_auth", + "mod_authn_file", + "mod_openssl", +# "mod_status", + "mod_setenv", +# "mod_proxy", +# "mod_simple_vhost", +# "mod_evhost", +# "mod_userdir", +# "mod_compress", +# "mod_ssi", +# "mod_usertrack", +# "mod_expire", +# "mod_secdownload", +# "mod_rrdtool", +# "mod_webdav", + "mod_accesslog" +) +# }}} + +# {{{ includes +include "mime-types.conf" +# uncomment for cgi support +include "mod_cgi.conf" +# uncomment for php/fastcgi support +# include "mod_fastcgi.conf" +# uncomment for php/fastcgi fpm support +# include "mod_fastcgi_fpm.conf" +# }}} + +# {{{ server settings +server.username = "openvpn" +server.groupname = "openvpn" + +server.document-root = var.basedir + "/htdocs" +server.pid-file = "/run/lighttpd.pid" + +server.errorlog = var.logdir + "/error.log" +server.breakagelog = var.logdir + "/stderr.log" +# log errors to syslog instead +# server.errorlog-use-syslog = "enable" + +server.indexfiles = ("index.cgi", "index.html", + "index.htm", "default.htm") + +# server.tag = "lighttpd" + +server.follow-symlink = "enable" + +# event handler (defaults to "poll") +# see performance.txt +# +# for >= linux-2.4 +# server.event-handler = "linux-rtsig" +# for >= linux-2.6 +# server.event-handler = "linux-sysepoll" +# for FreeBSD +# server.event-handler = "freebsd-kqueue" + +# chroot to directory (defaults to no chroot) +# server.chroot = "/" + +# bind to port (defaults to 80) +# server.port = 81 + +# bind to name (defaults to all interfaces) +# server.bind = "grisu.home.kneschke.de" + +# error-handler for status 404 +# server.error-handler-404 = "/error-handler.html" +# server.error-handler-404 = "/error-handler.php" + +# Format: .html +# -> ..../status-404.html for 'File not found' +# server.errorfile-prefix = var.basedir + "/error/status-" + +# FAM support for caching stat() calls +# requires that lighttpd be built with USE=fam +# server.stat-cache-engine = "fam" +# }}} + +# {{{ mod_staticfile + +# which extensions should not be handled via static-file transfer +# (extensions that are usually handled by mod_cgi, mod_fastcgi, etc). +static-file.exclude-extensions = (".php", ".pl", ".cgi", ".fcgi") +# }}} + +# {{{ mod_accesslog +accesslog.filename = var.logdir + "/access.log" +# }}} + +# {{{ mod_dirlisting +# enable directory listings +# dir-listing.activate = "enable" +# +# don't list hidden files/directories +# dir-listing.hide-dotfiles = "enable" +# +# use a different css for directory listings +# dir-listing.external-css = "/path/to/dir-listing.css" +# +# list of regular expressions. files that match any of the +# specified regular expressions will be excluded from directory +# listings. +# dir-listing.exclude = ("^\.", "~$") +# }}} + +# {{{ mod_access +# see access.txt + +url.access-deny = ("~", ".inc") +# }}} + +# {{{ mod_userdir +# see userdir.txt +# +# userdir.path = "public_html" +# userdir.exclude-user = ("root") +# }}} + +# {{{ mod_ssi +# see ssi.txt +# +# ssi.extension = (".shtml") +# }}} + +# {{{ mod_ssl +# see ssl.txt +# + ssl.engine = "enable" + ssl.pemfile = var.ovpndir + "/http/server.pem" + ssl.privkey = var.ovpndir + "/http/server.key" +# }}} + +# {{{ mod_status +# see status.txt +# +# status.status-url = "/server-status" +# status.config-url = "/server-config" +# }}} + +# {{{ mod_simple_vhost +# see simple-vhost.txt +# +# If you want name-based virtual hosting add the next three settings and load +# mod_simple_vhost +# +# document-root = +# virtual-server-root + virtual-server-default-host + virtual-server-docroot +# or +# virtual-server-root + http-host + virtual-server-docroot +# +# simple-vhost.server-root = "/home/weigon/wwwroot/servers/" +# simple-vhost.default-host = "grisu.home.kneschke.de" +# simple-vhost.document-root = "/pages/" +# }}} + +# {{{ mod_auth +# see authentication.txt +# + auth.backend = "htpasswd" + auth.backend.htpasswd.userfile = var.ovpndir + "/http/htpasswd" + + auth.require = ( "" => +# ( +# "method" => "digest", +# "realm" => "download archiv", +# "require" => "user=jan" +# ), +# "/server-info" => + ( + "method" => "basic", + "realm" => "Openvpn config", + "require" => "valid-user" + ) + ) +# }}} + +# {{{ mod_evhost +# define a pattern for the host url finding +# %% => % sign +# %0 => domain name + tld +# %1 => tld +# %2 => domain name without tld +# %3 => subdomain 1 name +# %4 => subdomain 2 name +# +# evhost.path-pattern = "/home/storage/dev/www/%3/htdocs/" +# }}} + +# {{{ mod_expire +# expire.url = ( +# "/buggy/" => "access 2 hours", +# "/asdhas/" => "access plus 1 seconds 2 minutes" +# ) +# }}} + +# {{{ mod_rrdtool +# see rrdtool.txt +# +# rrdtool.binary = "/usr/bin/rrdtool" +# rrdtool.db-name = var.statedir + "/lighttpd.rrd" +# }}} + +# {{{ mod_setenv +# see setenv.txt +# +# setenv.add-request-header = ( "TRAV_ENV" => "mysql://user@host/db" ) +# setenv.add-response-header = ( "X-Secret-Message" => "42" ) +# }}} + +# {{{ mod_trigger_b4_dl +# see trigger_b4_dl.txt +# +# trigger-before-download.gdbm-filename = "/home/weigon/testbase/trigger.db" +# trigger-before-download.memcache-hosts = ( "127.0.0.1:11211" ) +# trigger-before-download.trigger-url = "^/trigger/" +# trigger-before-download.download-url = "^/download/" +# trigger-before-download.deny-url = "http://127.0.0.1/index.html" +# trigger-before-download.trigger-timeout = 10 +# }}} + +# {{{ mod_cml +# see cml.txt +# +# don't forget to add index.cml to server.indexfiles +# cml.extension = ".cml" +# cml.memcache-hosts = ( "127.0.0.1:11211" ) +# }}} + +# {{{ mod_webdav +# see webdav.txt +# +# $HTTP["url"] =~ "^/dav($|/)" { +# webdav.activate = "enable" +# webdav.is-readonly = "enable" +# } +# }}} + +# {{{ extra rules +# +# set Content-Encoding and reset Content-Type for browsers that +# support decompressing on-thy-fly (requires mod_setenv) +# $HTTP["url"] =~ "\.gz$" { +# setenv.add-response-header = ("Content-Encoding" => "x-gzip") +# mimetype.assign = (".gz" => "text/plain") +# } + +# $HTTP["url"] =~ "\.bz2$" { +# setenv.add-response-header = ("Content-Encoding" => "x-bzip2") +# mimetype.assign = (".bz2" => "text/plain") +# } +# +# }}} + +# {{{ debug +# debug.log-request-header = "enable" +# debug.log-response-header = "enable" +# debug.log-request-handling = "enable" +# debug.log-file-not-found = "enable" +# }}} + +# vim: set ft=conf foldmethod=marker et : diff --git a/lighttpd/config/mod_cgi.conf b/lighttpd/config/mod_cgi.conf new file mode 100644 index 00000000..7a8ad9fc --- /dev/null +++ b/lighttpd/config/mod_cgi.conf @@ -0,0 +1,31 @@ +############################################################################### +# mod_cgi.conf +# include'd by lighttpd.conf. +# $Header: /var/cvsroot/gentoo-x86/www-servers/lighttpd/files/conf/mod_cgi.conf,v 1.1 2005/08/27 12:36:13 ka0ttic Exp $ +############################################################################### + +# +# see cgi.txt for more information on using mod_cgi +# + +server.modules += ("mod_cgi") + +# +# Note that you'll also want to enable the +# cgi-bin alias via mod_alias (above). +# + +# disable directory listings +dir-listing.activate = "disable" +cgi.assign = ( + ".cgi" => "/bin/bash" + ) + +# TODO: send directly not to leave stuff around +cgi.x-sendfile = "enable" # default "disable" +cgi.x-sendfile-docroot = ( var.basedir + "/vpn_configs" ) + +setenv.set-environment = ( "PATH" => "/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin", + "OPENVPN" => "/etc/openvpn/") + +# vim: set ft=conf foldmethod=marker et : diff --git a/lighttpd/htdocs/defs b/lighttpd/htdocs/defs new file mode 100644 index 00000000..74d158b4 --- /dev/null +++ b/lighttpd/htdocs/defs @@ -0,0 +1,36 @@ +HEAD=' + + + + + Openvpn client management + +' + +END='' + +function urldecode() { : "${*//+/ }"; echo -e "${_//%/\\x}"; } + + +parse_get_arg() +{ + while IFS='=' read -r -d '&' var val; do + var=$(urldecode "$var") + [ "$var" = "$1" ] && echo $(urldecode "$val") && return 0 + done<<<"${QUERY_STRING}&" + return 1 +} +export -f parse_get_arg + +parse_post_arg() +{ + while IFS='=' read -r -d '&' var val; do + var=$(urldecode "$var") + [ "$var" = "$1" ] && echo $(urldecode "$val") && return 0 + done<<<"${POST_STRING}&" + return 1 +} +export -f parse_post_arg + + +. /etc/openvpn/http/easyrsa.env diff --git a/lighttpd/htdocs/index.cgi b/lighttpd/htdocs/index.cgi new file mode 100755 index 00000000..4d421d88 --- /dev/null +++ b/lighttpd/htdocs/index.cgi @@ -0,0 +1,76 @@ +#!/bin/bash + +print_user_table() +{ +# name,begin,end,status +# ariya,Jul 21 11:15:44 2020 GMT,Jul 6 11:15:44 2023 GMT,VALID + + echo '
' + + echo ' + ' + + ovpn_listclients | tail -n +2 | while IFS=, read -r name valid_from valid_to status; do + + echo " + + " + done + + echo '
Existing users
UsernameValid fromValid toStatusConfig
$name$valid_from$valid_to$statusDOWNLOAD_CONFIG
+

+ +
* Global passphrase for the user management, can be found in keepassxc pwd db
+
+ +
Openvpn admin web (this page) access management + + ' +} + + +MY_PATH=$(readlink -f "$BASH_SOURCE") +MYDIR=$(dirname "$MY_PATH") +. "$MYDIR/defs" + +read -t 5 POST_STRING + +action=$(parse_post_arg "action") +username=$(parse_post_arg "username") +capassphrase=$(parse_post_arg "capassphrase") +export EASYRSA_PASSIN="pass:$capassphrase" +export EASYRSA_BATCH=1 +case "$action" in + del) echo "$capassphrase" | ovpn_revokeclient "$username" remove 1>&2 && message="

User $username removed

";; + add) echo "$capassphrase" | easyrsa build-client-full "$username" nopass 1>&2 && message="

Succesfully created user $username

";; + renew) echo "$capassphrase" | easyrsa renew "$username" nopass 1>&2 && message="

Certificate of user $username renewed

";; +esac + +echo "$HEAD" + +print_user_table +echo "$message" + +echo "$END" diff --git a/lighttpd/htdocs/style.css b/lighttpd/htdocs/style.css new file mode 100644 index 00000000..47d7d016 --- /dev/null +++ b/lighttpd/htdocs/style.css @@ -0,0 +1,11 @@ +table, th, td { + padding: 5px; +} + +th { + border: 1px solid black; +} + +tr { + height: 12px; +} diff --git a/lighttpd/htdocs/user_config.cgi b/lighttpd/htdocs/user_config.cgi new file mode 100755 index 00000000..af30795c --- /dev/null +++ b/lighttpd/htdocs/user_config.cgi @@ -0,0 +1,18 @@ +#!/bin/bash + +MY_PATH=$(readlink -f "$BASH_SOURCE") +MYDIR=$(dirname "$MY_PATH") +. "$MYDIR/defs" + + +username=$(parse_get_arg username) +[ "$?" != 0 -o -z "$username" ] && echo -e "$HEAD\n no valid user supplied!\n$END" && exit 1 + +CONFIG=$(ovpn_getclient "$username") +[ -z "$CONFIG" -o $? != 0 ] && echo -e "$HEAD error generating config for user $username\n$END" && exit 1 + +echo "Content-type: application/x-openvpn-profile" +echo "Content-Disposition:attachment; filename=$username.ovpn" +echo "" +echo "$CONFIG" + diff --git a/lighttpd/htdocs/web_password.cgi b/lighttpd/htdocs/web_password.cgi new file mode 100755 index 00000000..fb68c9bd --- /dev/null +++ b/lighttpd/htdocs/web_password.cgi @@ -0,0 +1,59 @@ +#!/bin/bash + + +MY_PATH=$(readlink -f "$BASH_SOURCE") +MYDIR=$(dirname "$MY_PATH") +. "$MYDIR/defs" +db="$OPENVPN/http/htpasswd" + +read -t 5 POST_STRING + +username=$(parse_post_arg "username") +pass=$(parse_post_arg "password") + +res=-1 +if [ -n "$username" ]; then + if [ -z "$pass" ]; then + openssl-htpasswd -D "$db" "$username" + res=$? + else + openssl-htpasswd "$db" "$username" "$pass" + res=$? + fi +fi + +echo "$HEAD" +echo ' +

Openvpn admin web access config

+

Current user list

+

+

    +' +cat "$db" | cut -d ':' -f 1 | while read un; do echo "
  • $un
  • "; done +echo '

+

User Management

+

+

+ + + + + + + + + +
Username
Password*
+ +
+

+
*use empty password to delete user
' + +if [ "$res" != '-1' ]; then + [ "$res" = 0 ] && echo "

Success

" || echo "

Failed

" + echo "

(modyfiing user $username)

" +fi + +echo "$END" +