Create an ovpn admin panel login page
Do you have a method for creating an admin username and password to access the OVPN management panel?
I had the same question and I read in an older issue that it's being considered. Someone remarked that it's easy to add nginx in front to provide authentication. Not sure if the following details helps you at all but I'm happy so share my solution along with some critical details that come with my implemention choices.
I ended up using nginx in front as well. My problem was that I didn't want to expose the management interface of OpenVPN by running it at any interface (0.0.0.0) which makes it vulnerable so I had it running at 127.0.0.1. For me it was no option to install nginx at the device itself, I wanted ovpn-admin and nginx both running in containers in a pod. The latest image at dockerhub is quite old so i decided to build an image myself. The next problem was that I wanted 8080 to be exposed via the pod to nginx only and that I couldn't reach the management interface at 127.0.0.1 (as it's the pods local ip) having it implemented like that. I use podman instead of docker so I figured that if I configure the gateway of the default podman network (10.88.0.1 a.k.a. host.docker.internal ) as the ip to run the management interface at ovpn-admin is able to reach it and in that way it's not publicly exposed while I can reach it from within the pod. Nginx provides basic auth (user, pass) and with that it meets my requirements.
If I can help someone out with the for all of this then let me know, I'm happy to share it.
I had the same question and I read in an older issue that it's being considered. Someone remarked that it's easy to add nginx in front to provide authentication. Not sure if the following details helps you at all but I'm happy so share my solution along with some critical details that come with my implemention choices.
I ended up using nginx in front as well. My problem was that I didn't want to expose the management interface of OpenVPN by running it at any interface (0.0.0.0) which makes it vulnerable so I had it running at 127.0.0.1. For me it was no option to install nginx at the device itself, I wanted ovpn-admin and nginx both running in containers in a pod. The latest image at dockerhub is quite old so i decided to build an image myself. The next problem was that I wanted 8080 to be exposed via the pod to nginx only and that I couldn't reach the management interface at 127.0.0.1 (as it's the pods local ip) having it implemented like that. I use podman instead of docker so I figured that if I configure the gateway of the default podman network (10.88.0.1 a.k.a. host.docker.internal ) as the ip to run the management interface at ovpn-admin is able to reach it and in that way it's not publicly exposed while I can reach it from within the pod. Nginx provides basic auth (user, pass) and with that it meets my requirements.
If I can help someone out with the for all of this then let me know, I'm happy to share it.
please explain more
I failed, I need help
In order to help you out, I need to know where you're stuck. Maybe sharing this basic example of configuration will help you out. Please mention that in this example no secure connection is provided for nginx. If you want to use that, create at least a self signed certificate and add it to your nginx configuration. Also, step 6 and 8 are highly depending on where your easy-rsa config resides, mounting /etc/openvpn to the container might not be what you want as well as running containers as root, latest tags etc. and make sure port 8080 is reachable from an selinux (or apparmor etc.) and firewall perspective. You can also use systemd to add services to create the containers and pod for persistence.
Hope this gives an impression of how I solved it. It's also completely possible to get this done without the use of containers. Just install nginx locally and use 127.0.0.1 for the management interface.
- create a username and password
htpasswd -c /container-data/nginx/.htpasswd admin
- add or adjust the management interface in /etc/openvpn/server/server.conf
management 10.88.0.1 8989
- create a pod
podman pod create --name ovpn -p 8080:8080
- nginx config at /container-data/nginx/default.conf
server {
listen 8080;
server_name 127.0.0.1;
location / {
auth_basic "Pass";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass http://127.0.0.1:8888;
}
}
- start nginx container
/usr/bin/podman run --name nginx -d --pod ovpn -v /container-data/nginx/.htpasswd:/etc/nginx/.htpasswd:ro -v /container-data/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro docker.io/nginx:latest
- custom ovpn container definition at ~/ovpn-container/Containerfile
FROM alpine:latest
RUN apk update && apk upgrade && apk add bash openssl curl
RUN ln -s /bin/sh /usr/bin/sh
WORKDIR /bin
COPY ovpn-admin .
ENV PATH=$PATH:/etc/openvpn/easy-rsa
CMD /bin/ovpn-admin
- build custom ovpn-container
cd ~/ovpn-container
podman build -t localhost:ovpn-admin Containerfile
- start ovpn-admin container
/usr/bin/podman run --pod ovpn -d --name ovpn-admin -v /etc/openvpn:/etc/openvpn:Z localhost:ovpn-admin ovpn-admin --listen.host=127.0.0.1 --listen.port=8888 --mgmt=main=10.88.0.1:8989 --easyrsa.index-path="/etc/openvpn/easy-rsa/pki/index.txt" --easyrsa.path="/etc/openvpn/easy-rsa" --ccd --ccd.path=/etc/openvpn/server/ccd --ovpn.server=10.88.0.1:34494
- go to http://your-ip-or-domain:8080/ and use the credentials created in the first step to login
Hello, Chiming in as I am working on this as well. I am trying to put nginx in front of the admin panel at http://192.168.1.97:8080/ Do you happen to have a dockerfile?
I am using Docker for this project. (management with Portainer)
What I have so far:
- I have ovpn-admin working, with clients connecting and local access.
What I need to do: Actually have ngnix sit in front of the admin panel .
- Set ovpn admin to localhost:8080
- Create ngnix container
- set nginx correctly
The main problem I am having is that nginx (conf below) gets a 502 error when trying to proxy to the ovpn-admin ui at docker-compose ports "127.0.0.1:8888:8080"
the UI works fine when I switch to just 8888:8080 , or if I disable nginx and do 8080:8080. I just cant get nginx to proxy correctly to the ovpn-admin ui.
nginx conf:
server {
listen 8080;
server_name 127.0.0.1;
location / {
auth_basic "Pass";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass http://127.0.0.1:8888;
}
}
Docker-compose:
version: '3'
services:
openvpn:
build:
context: .
dockerfile: Dockerfile.openvpn
image: openvpn:local
command: /etc/openvpn/setup/configure.sh
environment:
OVPN_SERVER_NET: "192.168.100.0"
OVPN_SERVER_MASK: "255.255.255.0"
OVPN_PASSWD_AUTH: "true"
cap_add:
- NET_ADMIN
ports:
- "7777:1194" # for openvpn
- "127.0.0.1:8888:8080" # for ovpn-admin because of network_mode
volumes:
- ./easyrsa_master:/etc/openvpn/easyrsa
- ./ccd_master:/etc/openvpn/ccd
ovpn-admin:
build:
context: .
image: ovpn-admin:local
command: /app/ovpn-admin
environment:
OVPN_DEBUG: "true"
OVPN_VERBOSE: "true"
OVPN_NETWORK: "192.168.100.0/24"
OVPN_CCD: "true"
OVPN_CCD_PATH: "/mnt/ccd"
EASYRSA_PATH: "/mnt/easyrsa"
OVPN_SERVER: "#HOSTNAME#:7777:tcp"
OVPN_INDEX_PATH: "/mnt/easyrsa/pki/index.txt"
OVPN_AUTH: "true"
OVPN_AUTH_DB_PATH: "/mnt/easyrsa/pki/users.db"
LOG_LEVEL: "debug"
network_mode: service:openvpn
volumes:
- ./easyrsa_master:/mnt/easyrsa
- ./ccd_master:/mnt/ccd
nginx:
image: nginx:latest
container_name: nginx
ports:
- "8080:8080" # for nginx
- "8081:8081" # for nginx
volumes:
- /home/machine/nginx/.htpasswd:/etc/nginx/.htpasswd:ro
- /home/machine/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
In this case, I figured out ovpn-admin was still running on the container but at 8080, even when the dockerfile specified " - "127.0.0.1:8888:8080" # for ovpn-admin because of network_mode
"
My new nginx conf: looks like:
server {
listen 8080;
server_name 127.0.0.1;
location / {
auth_basic "Pass";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass http://ovpn-admin-openvpn-1:8080;
}
}
the docker-compose for ovpn /ovpn admin looks like
version: '3'
services:
openvpn:
build:
context: .
dockerfile: Dockerfile.openvpn
image: openvpn:local
command: /etc/openvpn/setup/configure.sh
environment:
OVPN_SERVER_NET: "192.168.100.0"
OVPN_SERVER_MASK: "255.255.255.0"
OVPN_PASSWD_AUTH: "true"
cap_add:
- NET_ADMIN
ports:
- "7777:1194" # for openvpn
- "127.0.0.1:8888:8080" # for ovpn-admin because of network_mode - dnw-127.0.0.1:8888
volumes:
- ./easyrsa_master:/etc/openvpn/easyrsa
- ./ccd_master:/etc/openvpn/ccd
ovpn-admin:
build:
context: .
image: ovpn-admin:local
command: /app/ovpn-admin
environment:
OVPN_DEBUG: "true"
OVPN_VERBOSE: "true"
OVPN_NETWORK: "192.168.100.0/24"
OVPN_CCD: "true"
OVPN_CCD_PATH: "/mnt/ccd"
EASYRSA_PATH: "/mnt/easyrsa"
OVPN_SERVER: "##HOSTNAME###:7777:tcp"
OVPN_INDEX_PATH: "/mnt/easyrsa/pki/index.txt"
OVPN_AUTH: "true"
OVPN_AUTH_DB_PATH: "/mnt/easyrsa/pki/users.db"
LOG_LEVEL: "debug"
network_mode: service:openvpn
volumes:
- ./easyrsa_master:/mnt/easyrsa
- ./ccd_master:/mnt/ccd
the docker-compose for nginx looks like
version: '3'
services:
nginx:
image: nginx:latest
container_name: nginx
ports:
- "8080:8080" # for nginx
- "8081:8081" # for nginx
volumes:
- /home/machine/nginx/.htpasswd:/etc/nginx/.htpasswd:ro
- /home/machine/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
Note the other 8081 port was to test the nginx page
Got this to work:
location /vpn/ {
auth_basic "Administrator’s Area";
auth_basic_user_file /etc/nginx/.htpasswd-vpn;
# Disable caching of credentials
add_header Cache-Control "no-store, private, no-cache, must-revalidate, max-age=0";
add_header Pragma "no-cache";
add_header Expires "Thu, 01 Jan 1970 00:00:00 GMT";
proxy_pass http://localhost:8083/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_redirect http://localhost:8083/ /vpn;
}
I came up to this solution, resulting the web UI admin panel being accessible only for specific users from inside the VPN network and management port 8989 not being accessible from the VPN network.
changes made:
docker-compose.yaml
ports:
- 1194:1194/udp # for openvpn
# - "127.0.0.1:9999:9999" # for ovpn-admin because of network_mode
networks:
vpn:
ipv4_address: 10.99.0.2
## ovpn admin container
OVPN_LISTEN_PORT: "9999"
# OVPN_LISTEN_HOST: "127.0.0.1"
OVPN_MGMT: "10.99.0.2:8989"
# network_mode: service:openvpn
ports:
- 9999:9999
networks:
vpn:
ipv4_address: 10.99.0.3
volumes:
- ./easyrsa_master:/mnt/easyrsa
- ./ccd_master:/mnt/ccd
networks:
vpn:
driver: bridge
ipam:
driver: default
config:
- subnet: 10.99.0.0/24
gateway: 10.99.0.1
This allows to access the web admin panel only through nginx proxy, not from the VPN network
To disable the possibility of access the management port of VPN from inside the VPN network (if some will add 10.99.0.2 IP to routing table somehow). setup/config.sh
#exclude 10.99.0.2 from NATing
iptables -t nat -I POSTROUTING 1 -d 10.99.0.2 -j RETURN
iptables -t nat -D POSTROUTING -s ${OVPN_SRV_NET}/${OVPN_SRV_MASK} ! -d ${OVPN_SRV_NET}/${OVPN_SRV_MASK} -j MASQUERADE || true
iptables -t nat -A POSTROUTING -s ${OVPN_SRV_NET}/${OVPN_SRV_MASK} ! -d ${OVPN_SRV_NET}/${OVPN_SRV_MASK} -j MASQUERADE
# add reject rule from VPN network to interface 10.99.0.2 inside the docker
iptables -A INPUT -i tun0 -d 10.99.0.2 -j REJECT
##end line
openvpn --config /etc/openvpn/openvpn.conf --client-config-dir /etc/openvpn/ccd --port 1194 --proto udp --management **10.99.0.2** 8989
Use an additional webserver as a proxy, being accessible only from a VPN network. Port 443 to the VPN server accessible only from that additional proxy.
strong username + password as basic auth on nginx