Giter VIP home page Giter VIP logo

openvpn-auth-azure-ad's Introduction

CI PyPI PyPI - Downloads Docker Pulls GitHub license

openvpn-auth-azure-ad

State: Discontinued - Follow up project: https://github.com/jkroepke/openvpn-auth-oauth2

openvpn-auth-azure-ad is an external service connects to the openvpn management interface and handle the authentication of connecting users against Azure AD.

OpenVPN version 2.4 is required. 2.5 is not tested yet.

Tested environment

Python

  • Python 3.11

Server

  • OpenVPN 2.5.6

Client

Authenticators

Currently, openvpn-auth-azure-ad supports 2 authentication method against Azure AD:

Additionally, if enabled openvpn-auth-azure-ad supports OpenVPNs auth-token mechanismus to allow users to bypass then authenticator above on re-authentications, e.g. due reneg-sec.

Installation

via pip

# pip install openvpn-auth-azure-ad

For install pip on your system, see pip docs.

To run a persistent daemon, you copy the systemd unit file to /etc/systemd/system, then run

# systemctl enable openvpn-auth-azure-ad
# systemctl start openvpn-auth-azure-ad

via docker

https://hub.docker.com/r/jkroepke/openvpn-auth-azure-ad

# docker run --rm \
    -v <path of openvpn mgmt socket>:/openvpn/management.sock
    -v /etc/openvpn-auth-azure-ad/config.conf:/etc/openvpn-auth-azure-ad/config.conf \
    -e AAD_CLIENT_ID= \
    -e OPENVPN_AAD_AUTH_SOCKET_PATH=/openvpn/management.sock \
    -e OPENVPN_AAD_AUTH_PASSWORD= \
    jkroepke/openvpn-auth-azure-ad

Usage

Args that start with '--' (eg. -V) can also be set in a config file (/etc/openvpn-auth-azure-ad/config.conf or ~/.openvpn-auth-azure-ad or specified via -c). Config file syntax allows: key=value, flag=true, stuff=[a,b,c] (for details, see syntax at https://goo.gl/R74nmi). If an arg is specified in more than one place, then commandline values override environment variables which override config file values which override defaults.

usage: openvpn-auth-azure-ad.py [-h] [-c CONFIG] [-V] [-t THREADS] [-a AUTHENTICATORS] [--auth-token] [--auth-token-lifetime AUTH_TOKEN_LIFETIME] [--remember-user] [--webauth] [--webauth-url WEBAUTH_URL]
                                [--openvpn-identity-key {common_name,username}] [--verify-openvpn-client] [--verify-openvpn-client-id-token-claim] [-H OPENVPN_HOST] [-P OPENVPN_PORT] [-s OPENVPN_SOCKET]
                                [-p OPENVPN_PASSWORD] [--openvpn-release-hold] --client-id CLIENT_ID [--token-authority TOKEN_AUTHORITY] [--graph-endpoint GRAPH_ENDPOINT] [--prometheus]
                                [--prometheus-listen-addr PROMETHEUS_LISTEN_ADDR] [--prometheus-listen-port PROMETHEUS_LISTEN_PORT] [--log-level LOG_LEVEL]

options:
  -h, --help            show this help message and exit
  -c CONFIG, --config CONFIG
                        path of config file [env var: AAD_CONFIG_PATH]
  -V, --version         show program's version number and exit
  -t THREADS, --threads THREADS
                        Amount of threads to handle authentication [env var: AAD_THREAD_COUNT]

OpenVPN User Authentication:
  -a AUTHENTICATORS, --authenticators AUTHENTICATORS
                        Enable authenticators. Multiple authenticators can be separated with comma [env var: AAD_AUTHENTICATORS]
  --auth-token          Use auth token to re-authenticate clients [env var: AAD_AUTH_TOKEN]
  --auth-token-lifetime AUTH_TOKEN_LIFETIME
                        Lifetime of auth tokens in seconds [env var: AAD_AUTH_TOKEN_LIFETIME]
  --remember-user       If user authenticated once, the users refresh token is used to reauthenticate silently if possible. [env var: AAD_REMEMBER_USER]
  --webauth             Support OpenVPN WebAuth capabilities, if client supports. [env var: AAD_REMEMBER_USER]
  --webauth-url WEBAUTH_URL
                        Wrapper Page for WebAuth capabilities. Copy docs/ folder to host a dedicated one. [env var: AAD_REMEMBER_USER]
  --openvpn-identity-key {common_name,username}
                        Define which value from OpenVPN should be used for identity the AAD user. Supported values: 'common_name', 'username' [env var: AAD_OPENVPN_IDENTITY_KEY]
  --verify-openvpn-client
                        Check if openvpn client common_name matches Azure AD token claim [env var: AAD_VERIFY_OPENVPN_CLIENT]
  --verify-openvpn-client-id-token-claim
                        AAD id_token claim used for client verification [env var: AAD_VERIFY_OPENVPN_CLIENT_ID_TOKEN_CLAIM]

OpenVPN Management Interface settings:
  -H OPENVPN_HOST, --openvpn-host OPENVPN_HOST
                        Host of OpenVPN management interface. [env var: OPENVPN_AAD_AUTH_HOST]
  -P OPENVPN_PORT, --openvpn-port OPENVPN_PORT
                        Port of OpenVPN management interface. [env var: OPENVPN_AAD_AUTH_PORT]
  -s OPENVPN_SOCKET, --openvpn-socket OPENVPN_SOCKET
                        Path of socket or OpenVPN management interface. [env var: OPENVPN_AAD_AUTH_SOCKET_PATH]
  -p OPENVPN_PASSWORD, --openvpn-password OPENVPN_PASSWORD
                        Passwort for OpenVPN management interface. [env var: OPENVPN_AAD_AUTH_PASSWORD]
  --openvpn-release-hold
                        Release hold on OpenVPN Server if --management-hold is enabled [env var: OPENVPN_AAD_AUTH_RELEASE_HOLD]

Azure AD settings:
  --client-id CLIENT_ID
                        Client ID of application. [env var: AAD_CLIENT_ID]
  --token-authority TOKEN_AUTHORITY
                        A URL that identifies a token authority. It should be of the format https://login.microsoftonline.com/your_tenant. By default, we will use
                        https://login.microsoftonline.com/organizations [env var: AAD_TOKEN_AUTHORITY]
  --graph-endpoint GRAPH_ENDPOINT
                        Endpoint of the graph API. See: https://developer.microsoft.com/en-us/graph/graph-explorer [env var: AAD_GRAPH_ENDPOINT]

Prometheus settings:
  --prometheus          Enable prometheus statistics [env var: AAD_PROMETHEUS_ENABLED]
  --prometheus-listen-addr PROMETHEUS_LISTEN_ADDR
                        prometheus listen addr [env var: AAD_PROMETHEUS_LISTEN_HOST]
  --prometheus-listen-port PROMETHEUS_LISTEN_PORT
                        prometheus statistics [env var: AAD_PROMETHEUS_PORT]
  --log-level LOG_LEVEL
                        Configure the logging level. [env var: AAD_LOG_LEVEL]

Args that start with '--' (eg. -V) can also be set in a config file (/etc/openvpn-auth-azure-ad/config.conf or ~/.openvpn-auth-azure-ad or specified via -c). Config file syntax allows: key=value, flag=true,
stuff=[a,b,c] (for details, see syntax at https://goo.gl/R74nmi). If an arg is specified in more than one place, then commandline values override environment variables which override config file values which
override defaults.

Register an app with AAD

See: https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app

TL;DR

  1. Login as admin into tenant
  2. Open App registrations in Azure AD admin center
  3. Click new registration
  4. Pick a name, chose a "Supported account types"-option. Let the redirect uri blank and click register.
  5. Copy the client-id. You need the client-id as configuration option for openvpn-auth-azure-ad.
  6. Click on Authentication on the left menu
  7. "Add a platform", pick Mobile and desktop applications and chose the "MSAL only" option.
  8. On Advanced settings, set "Allow public client flows" to yes.

Required settings on OpenVPN configuration files

server.conf

Use auth-gen-token only on OpenVPN 2.5+. It conflicts with --auth-token.

management socket-name unix [pw-file]
management-hold
management-client-auth

See Reference manual for OpenVPN for detailed management settings.

If no client certificate are required

If your setup does not require certificates, the following options are required:

username-as-common-name

client.conf

auth-user-pass
auth-retry interact

auth-user-pass is always required otherwise dynamic challenges will not work.

Prometheus support

openvpn-auth-azure-ad has some built-in prometheus support to collect some statistics about authenticators. By default, the prometheus endpoint listen on port 9723.

Related projects

Copyright and license

© 2022 Jan-Otto Kröpke (jkroepke)

Licensed under the MIT License

openvpn-auth-azure-ad's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

openvpn-auth-azure-ad's Issues

`username-as-common-name` option when using this solution

I'm testing various connection methods and i've got my head around how it all works I think. The way we currently use openvpn with client certs, we don't generate a cert for each user, but we recycle them on a tight interval and have users redownload via self service portal. While possible to generate client certs based on the user downloading it, i'd rather keep the ovpn files able to be distributed and preserve the authentication layer using openvpn-auth-ldap, and just stack this device login workflow on top of it.

Right now the issue i'm having is that it seems openvpn-auth-ldap is forcing a connection reset because it doesn't get the devicelogin response within 5s, which is quite impossible to do.

Works just fine if I use only the management-client-auth directive, so thank you for this streamlined approach to the python script. Hoping you may have guidance on how to best implement these two layers of authentication

Version issues

the latest tag in docker hub is 7months old, and the main tag seems to have an error :(

image

Can't use unix sockets to talk to openvpn management interface

Hi,

I've been trying this out and I don't seem to be able to talk OpnVPN management interface with unix sockets. I just get the error:

Traceback (most recent call last): File "/usr/local/bin/openvpn-auth-azure-ad", line 8, in <module> sys.exit(main()) File "/usr/local/lib/python3.9/dist-packages/openvpn_auth_azure_ad/__init__.py", line 191, in main aad_authenticator = AADAuthenticator( File "/usr/local/lib/python3.9/dist-packages/openvpn_auth_azure_ad/authenticator.py", line 93, in __init__ self._openvpn.connect() File "/usr/local/lib/python3.9/dist-packages/openvpn_auth_azure_ad/openvpn/__init__.py", line 80, in connect self._mgmt_host, AttributeError: 'OpenVPNManagementInterface' object has no attribute '_mgmt_host'

I took a quick look at the code and it looks like the logging added to openvpn_auth_azure_ad/openvpn/init.py line 80 as part of this commit doesn't take into account that you might be using unix sockets. It tries to log self._mgmt_host regardless.

The fix seems simple enough. Probably just move the logging into the conditional that follows it. I don't know python things enough to know how to do that and then test it though :(

client certificate does not match Azure AD user

I want to use SSO with Azure AD to login openvpn. After importing profile then input multi-factor authencation. I met error message as below. I don't know how to fix this issue. Thanks for help.

image

root@vpn:~# openvpn-auth-azure-ad --client-id xxxxxxx -H 127.0.0.1 -P 7505 --token-authority https://login.microsoftonline.com/xxxxx.onmicrosoft.com
2022-04-14 18:56:49,815 INFO Connection to OpenVPN management interfaced established.
2022-04-14 18:56:49,816 INFO Running openvpn-auth-azure-ad 1.2.0
2022-04-14 18:56:54,200 INFO [cid: 4]: Received client connect
2022-04-14 18:56:54,200 INFO [cid: 4]: Start to authenticate using device token flow
2022-04-14 18:56:55,286 INFO [cid: 4]: Received client disconnect event
2022-04-14 18:57:21,425 INFO [cid: 5]: Received client connect
2022-04-14 18:57:21,425 INFO [cid: 5]: Continue to authenticate using device token flow
2022-04-14 18:57:21,865 INFO [cid: 5]: client certificate does not match Azure AD user.
2022-04-14 18:57:22,491 INFO [cid: 5]: Received client disconnect event

OpenVPN Clinet log

[Apr 14, 2022, 18:03:18] OpenVPN core 3.git::d3f8b18b win x86_64 64-bit built on Mar 17 2022 11:42:02
⏎[Apr 14, 2022, 18:03:18] Frame=512/2048/512 mssfix-ctrl=1250
⏎[Apr 14, 2022, 18:03:18] UNUSED OPTIONS
4 [resolv-retry] [infinite]
5 [nobind]
6 [persist-key]
7 [persist-tun]
11 [auth-nocache]
13 [ignore-unknown-option] [block-outside-dns]
14 [block-outside-dns]
15 [verb] [3]
⏎[Apr 14, 2022, 18:03:18] EVENT: RESOLVE ⏎[Apr 14, 2022, 18:03:18] EVENT: WAIT ⏎[Apr 14, 2022, 18:03:18] WinCommandAgent: transmitting bypass route to 192.168.3.76
{
"host" : "192.168.3.76",
"ipv6" : false
}
⏎[Apr 14, 2022, 18:03:18] Connecting to [192.168.3.76]:1194 (192.168.3.76) via TCPv4
⏎[Apr 14, 2022, 18:03:18] EVENT: CONNECTING ⏎[Apr 14, 2022, 18:03:18] Tunnel Options:V4,dev-type tun,link-mtu 1523,tun-mtu 1500,proto TCPv4_CLIENT,cipher AES-128-GCM,auth [null-digest],keysize 128,key-method 2,tls-client
⏎[Apr 14, 2022, 18:03:18] Creds: DynamicChallenge
⏎[Apr 14, 2022, 18:03:18] Peer Info:
IV_VER=3.git::d3f8b18b
IV_PLAT=win
IV_NCP=2
IV_TCPNL=1
IV_PROTO=30
IV_CIPHERS=AES-256-GCM:AES-128-GCM:CHACHA20-POLY1305
IV_GUI_VER=OCWindows_3.3.6-2752
IV_SSO=webauth,openurl,crtext
[Apr 14, 2022, 18:03:19] SSL Handshake: peer certificate: CN=server_tQbNQlk72SYn6Xol, 256 bit EC, curve:prime256v1, cipher: TLS_AES_256_GCM_SHA384 TLSv1.3 Kx=any Au=any Enc=AESGCM(256) Mac=AEAD
[Apr 14, 2022, 18:03:19] Session is ACTIVE
⏎[Apr 14, 2022, 18:03:19] EVENT: GET_CONFIG ⏎[Apr 14, 2022, 18:03:19] Sending PUSH_REQUEST to server...
⏎[Apr 14, 2022, 18:03:20] Sending PUSH_REQUEST to server...
⏎[Apr 14, 2022, 18:03:20] AUTH_FAILED
⏎[Apr 14, 2022, 18:03:20] EVENT: AUTH_FAILED ⏎[Apr 14, 2022, 18:03:20] EVENT: DISCONNECTED ⏎

Server.conf

port 1194
proto tcp
dev tun
user nobody
group nogroup
persist-key
persist-tun
keepalive 10 120
topology subnet
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
push "dhcp-option DNS 168.95.1.1"
push "dhcp-option DNS 8.8.8.8"
push "redirect-gateway def1 bypass-dhcp"
dh none
ecdh-curve prime256v1
tls-crypt tls-crypt.key
crl-verify crl.pem
ca ca.crt
client-cert-not-required
cert server_tQbNQlk72SYn6Xol.crt
key server_tQbNQlk72SYn6Xol.key
auth SHA256
cipher AES-128-GCM
ncp-ciphers AES-128-GCM
tls-server
tls-version-min 1.2
tls-cipher TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256
client-config-dir /etc/openvpn/ccd
status /var/log/openvpn/status.log
verb 3
management localhost 7505
#management socket-name unix [pw-file]
management-client-auth

Frequent disconnections from the OpenVPN server

Hello, I configured OpenVPN server with device auth flow from Azure AD and I'm faced with the problem of often disconnection from my OpenVPN server, I do not observe any problems with the network, not found any criticals error/ warnings in the OpenVPN server logs. But in the logs of the "openvpn-auth-azure-ad" service, at the time of the disconnect, there is a message "Received client re auth event". Can you tell me which way to look?

Move user authentication in a thread

openvpn-auth-azure-ad is checking max. 30 seconds for a successful device token flow.

Since the waiting loop runs in the main thread, no other users can be authenticated.

openvpn_auth_azure_ad.util.errors.ConnectError: [Errno 111] Connection refused

When I run

python3 openvpn-auth-azure-ad.py --client-id xxxx -H xxxx -P xxxx -p xxxx
I got the following response

Traceback (most recent call last): File "openvpn-auth-azure-ad.py", line 6, in <module> main() File "/etc/openvpn/server/openvpn-auth-azure-ad-master/openvpn_auth_azure_ad/cli.py", line 177, in main authenticator = AADAuthenticator( File "/etc/openvpn/server/openvpn-auth-azure-ad-master/openvpn_auth_azure_ad/authenticator.py", line 60, in __init__ self._openvpn.connect() File "/etc/openvpn/server/openvpn-auth-azure-ad-master/openvpn_auth_azure_ad/openvpn/__init__.py", line 138, in connect raise errors.ConnectError(str(e)) from None openvpn_auth_azure_ad.util.errors.ConnectError: [Errno 111] Connection refused

Any other arguments I have to set? Please kindly help.

Stuck on "PUSH REQUEST"

My openvpn.log

WR2022-11-29 17:32:02 us=372844 xxxxxxxxxxxxxx:63767 PUSH: Received control message: 'PUSH_REQUEST'
WR2022-11-29 17:32:07 us=643615 xxxxxxxxxxxxxx:63767 PUSH: Received control message: 'PUSH_REQUEST'
WR2022-11-29 17:32:12 us=910058 xxxxxxxxxxxxxx:63767 PUSH: Received control message: 'PUSH_REQUEST'
WR2022-11-29 17:32:18 us=186870 xxxxxxxxxxxxxx:63767 PUSH: Received control message: 'PUSH_REQUEST'
WR2022-11-29 17:32:23 us=268419 xxxxxxxxxxxxxx:63767 PUSH: Received control message: 'PUSH_REQUEST'
WR2022-11-29 17:32:27 us=338487 xxxxxxxxxxxxxx:63767 PUSH: Received control message: 'PUSH_REQUEST'
WR2022-11-29 17:32:32 us=498104 xxxxxxxxxxxxxx:63767 PUSH: Received control message: 'PUSH_REQUEST'

No ending connection

Multiple issue about remember users

At openvpn_auth_azure_ad/authenticator.py, 323 lines, we define the result as an empty Dict.
At 343 lines, we set result as the self.handle_response_challenge(client) 's return value . In some time ( not unusual ). If the result isn't None, it will run the code between 345 to 381 lines.
At 391 lines, if remember-user is enabled, we will use util.is_authenticated(result) to determine whether the user is authenticated. And it uses return "access_token" in result to decide.
But It causes a problem . The result that can be None, and it will causes TypeError: argument of type 'NoneType' is not iterable .

So, I changed the util.is_authenticated 's code to return result is not None and "access_token" in result, and I will test whether it runs correctly in the next few hours.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.