-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Duarte Mortágua
committed
Jul 31, 2023
0 parents
commit 6892687
Showing
31 changed files
with
1,268 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MIT License | ||
|
||
Copyright (c) 2023 Duarte Mortágua | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# vpn-idp | ||
|
||
This repository includes a VPN solution based on WireGuard that implements user authentication using OAuth2.0 and IdPs. The solution was proposed in my MSc thesis: | ||
|
||
- D. Mortágua, "Authentication in VPNs and 802.1X networks with Identity Providers," M.S. thesis, Department of Electronics, Telecommunications and Informatics, University of Aveiro, Aveiro, 2023. [Online]. Available: soon | ||
|
||
A PDF containing the dissertation presentation is present in both modules. | ||
|
||
### Author | ||
[Duarte Mortágua](mailto:[email protected]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
venv | ||
.env |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
# vpn-idp-client | ||
|
||
## Introduction | ||
|
||
VPN Client that authenticates with a VPN Server using external IdPs. | ||
|
||
This repository integrates part of the VPN solution proposed in my MSc thesis: | ||
|
||
- D. Mortágua, "Authentication in VPNs and 802.1X networks with Identity Providers," M.S. thesis, Department of Electronics, Telecommunications and Informatics, University of Aveiro, Aveiro, 2023. [Online]. Available: soon. | ||
|
||
### TL;DR: | ||
|
||
This work presents a streamlined VPN solution that utilizes external IdPs for client user authentication and leverages the OAuth 2.0 authorization process for WireGuard key negotiation, ensuring that only authenticated peers can establish a VPN connection. | ||
|
||
This piece of code implements the VPN Client module. The ```presentation.pdf``` file includes a brief explanaition of the architecture and communication implemented. | ||
|
||
## Installation: | ||
Set up the python environment by running: | ||
``` | ||
python3 -m venv venv | ||
source venv/bin/activate | ||
python3 -m pip install -r requirements.txt | ||
``` | ||
|
||
You need to set up the following environment variables (```.env``` file in root directory): | ||
`````` | ||
VPN_SERVER_URL=<your_vpn_server_url> | ||
VPN_CLIENT_WG_PUB_KEY=<your_vpn_client_wireguard_pub_key> | ||
`````` | ||
|
||
Finally, run the client: | ||
``` | ||
python3 client.py | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
import threading | ||
import time | ||
import webbrowser | ||
import socket | ||
import os | ||
from flask import Flask, redirect, request | ||
import logging | ||
from dotenv import load_dotenv | ||
|
||
load_dotenv() | ||
|
||
# Logging configuration | ||
logging.basicConfig( | ||
format='%(asctime)s %(levelname)-8s %(message)s', | ||
level=logging.INFO, | ||
datefmt='%d-%m-%Y %H:%M:%S') | ||
|
||
|
||
# Get environment variables | ||
VPN_SERVER_URL = os.getenv('VPN_SERVER_URL') | ||
VPN_CLIENT_WG_PUB_KEY = os.environ.get('VPN_CLIENT_WG_PUB_KEY') | ||
|
||
|
||
def initial_logging(port): | ||
logging.info(f"Local server listening on port {port}") | ||
logging.info(f"Launching browser...") | ||
logging.info(f"{VPN_SERVER_URL}/accounts/login/?port={port}") | ||
webbrowser.open( | ||
f"{VPN_SERVER_URL}/accounts/login/?port={port}") | ||
|
||
|
||
class MyFlaskApp(Flask): | ||
def run(self, host=None, port=None, debug=None, load_dotenv=True, **options): | ||
if not self.debug or os.getenv('WERKZEUG_RUN_MAIN') == 'true': | ||
with self.app_context(): | ||
initial_logging(port) | ||
super(MyFlaskApp, self).run(host=host, port=port, | ||
debug=debug, load_dotenv=load_dotenv, **options) | ||
|
||
|
||
# Initialize app | ||
app = MyFlaskApp(__name__) | ||
|
||
# Find available port | ||
sock = socket.socket() | ||
sock.bind(('', 0)) | ||
port = sock.getsockname()[1] | ||
sock.close() | ||
|
||
|
||
def create_vpn(params): | ||
""" | ||
Simulates the instatiation of a WireGuard VPN connection | ||
based on the parameters recieved from the VPN Server. | ||
""" | ||
|
||
if params.get('machine_id'): | ||
logging.info(f"Machine ID: {params.get('machine_id')}") | ||
logging.info(f"Client WG ipv4: {params.get('machine_wg_ipv4_address')}") | ||
logging.info(f"Client WG ipv4 pool: {params.get('machine_wg_ipv4_address_pool')}") | ||
logging.info(f"Client WG pub key: {params.get('machine_wg_pub_key')}") | ||
logging.info(f"Server WG pub key: {params.get('server_wg_pub_key')}") | ||
logging.info(f"Server WG public endpoint: {params.get('server_wg_public_endpoint')}") | ||
logging.info("VPN creation Thread starting (simulation)...") | ||
time.sleep(5) | ||
logging.info("VPN creation Thread finishing.") | ||
|
||
|
||
@app.route('/login_callback') | ||
def redirect_to_vpn_server(): | ||
""" | ||
Redcieves the callback from the IdP callback and redirects it to | ||
the real OAuth2.0 client, aka the VPN Server. If the response | ||
contains a code (Auth Grant flow), it adds the code to the | ||
redirection request. | ||
""" | ||
|
||
code = request.args.get("code") | ||
logging.info("Recieved redirect from IdP, redirecting token fragment to the VPN Server...") | ||
if code: | ||
logging.info("Found code, adding it to redirect...") | ||
return redirect(f'{VPN_SERVER_URL}/accounts/login_callback/?code={code}&wg_pub_key={VPN_CLIENT_WG_PUB_KEY}') | ||
return redirect(f'{VPN_SERVER_URL}/accounts/login_callback/?wg_pub_key={VPN_CLIENT_WG_PUB_KEY}') | ||
|
||
|
||
@app.route('/vpn_parameters') | ||
def recieve_vpn_parameters(): | ||
""" | ||
Endpoint where the VPN Server sends the final VPN parameters | ||
upon successful authentication. These parameters allow the client | ||
to initiate the VPN connection. | ||
""" | ||
|
||
logging.info("Recieved parameters from browser.") | ||
create_vpn_job = threading.Thread(target=create_vpn, args=(request.args,)) | ||
create_vpn_job.start() | ||
return 'Login successful. You can close this window now.' | ||
|
||
|
||
app.run(host="127.0.0.1", port=port) |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
websockets | ||
flask-sock | ||
flask | ||
requests | ||
python-dotenv |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
*.sql | ||
.vscode/ | ||
migrations/ | ||
# Byte-compiled / optimized / DLL files | ||
__pycache__/ | ||
*.py[cod] | ||
*$py.class | ||
|
||
# C extensions | ||
*.so | ||
|
||
# Distribution / packaging | ||
.Python | ||
build/ | ||
develop-eggs/ | ||
dist/ | ||
downloads/ | ||
eggs/ | ||
.eggs/ | ||
lib/ | ||
lib64/ | ||
parts/ | ||
sdist/ | ||
var/ | ||
wheels/ | ||
pip-wheel-metadata/ | ||
share/python-wheels/ | ||
*.egg-info/ | ||
.installed.cfg | ||
*.egg | ||
MANIFEST | ||
|
||
# PyInstaller | ||
# Usually these files are written by a python script from a template | ||
# before PyInstaller builds the exe, so as to inject date/other infos into it. | ||
*.manifest | ||
*.spec | ||
|
||
# Installer logs | ||
pip-log.txt | ||
pip-delete-this-directory.txt | ||
|
||
# Unit test / coverage reports | ||
htmlcov/ | ||
.tox/ | ||
.nox/ | ||
.coverage | ||
.coverage.* | ||
.cache | ||
nosetests.xml | ||
coverage.xml | ||
*.cover | ||
*.py,cover | ||
.hypothesis/ | ||
.pytest_cache/ | ||
|
||
# Translations | ||
*.mo | ||
*.pot | ||
|
||
# Django stuff: | ||
*.log | ||
local_settings.py | ||
db.sqlite3 | ||
db.sqlite3-journal | ||
|
||
# Flask stuff: | ||
instance/ | ||
.webassets-cache | ||
|
||
# Scrapy stuff: | ||
.scrapy | ||
|
||
# Sphinx documentation | ||
docs/_build/ | ||
|
||
# PyBuilder | ||
target/ | ||
|
||
# Jupyter Notebook | ||
.ipynb_checkpoints | ||
|
||
# IPython | ||
profile_default/ | ||
ipython_config.py | ||
|
||
# pyenv | ||
.python-version | ||
|
||
# pipenv | ||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. | ||
# However, in case of collaboration, if having platform-specific dependencies or dependencies | ||
# having no cross-platform support, pipenv may install dependencies that don't work, or not | ||
# install all needed dependencies. | ||
#Pipfile.lock | ||
|
||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow | ||
__pypackages__/ | ||
|
||
# Celery stuff | ||
celerybeat-schedule | ||
celerybeat.pid | ||
|
||
# SageMath parsed files | ||
*.sage.py | ||
|
||
# Environments | ||
.env | ||
.venv | ||
env/ | ||
venv/ | ||
ENV/ | ||
env.bak/ | ||
venv.bak/ | ||
|
||
# Spyder project settings | ||
.spyderproject | ||
.spyproject | ||
|
||
# Rope project settings | ||
.ropeproject | ||
|
||
# mkdocs documentation | ||
/site | ||
|
||
# mypy | ||
.mypy_cache/ | ||
.dmypy.json | ||
dmypy.json | ||
|
||
# Pyre type checker | ||
.pyre/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
# vpn-idp-server | ||
|
||
## Introduction | ||
|
||
VPN server that allows a VPN client to authenticate via an external Identity Provider, using OAuth2.0, avoiding the usual ID/Password authentication. | ||
|
||
This repository integrates part of the VPN solution proposed in my MSc thesis: | ||
|
||
- D. Mortágua, "Authentication in VPNs and 802.1X networks with Identity Providers," M.S. thesis, Department of Electronics, Telecommunications and Informatics, University of Aveiro, Aveiro, 2023. [Online]. Available: soon. | ||
|
||
## Introduction | ||
|
||
### TL;DR: | ||
|
||
This work presents a streamlined VPN solution that utilizes external IdPs for client user authentication and leverages the OAuth 2.0 authorization process for WireGuard key negotiation, ensuring that only authenticated peers can establish a VPN connection. | ||
|
||
This piece of code implements the VPN Server module. The ```presentation.pdf``` file includes a brief explanaition of the architecture and communication implemented. | ||
|
||
## Installation: | ||
|
||
Set up the python environment by running: | ||
``` | ||
python3 -m venv venv | ||
source venv/bin/activate | ||
python3 -m pip install -r requirements.txt | ||
``` | ||
|
||
Apply the Django migrations: | ||
``` | ||
python3 manage.py makemigrations | ||
python3 manage.py migrate | ||
``` | ||
|
||
Create the Django admin user: | ||
``` | ||
python3 manage.py createsuperuser --username admin | ||
``` | ||
|
||
As this server acts like a OAuth2.0 client, it needs to hold credentials regarding the supported IdPs (client ID, client secret, etc...). This Django project is ready to hold a sqlite3 table that holds these credentials, according to the model ```IdentityProvider``` in ```accounts/models.py```. | ||
|
||
In order to facilitate the import of an IdP, you can set up a OAuth2.0 client (for example, [Google ID](https://developers.google.com/identity/protocols/oauth2)) and import it as a Django fixture. | ||
|
||
Example of a fixture file ```fixtures/idps.json``` holding 1 IdP configuration: | ||
```json | ||
[ | ||
{ | ||
"model": "accounts.identityprovider", | ||
"pk": 1, | ||
"fields": { | ||
"name" : "google", | ||
"type": "auth_code", | ||
"client_id": "********", | ||
"client_secret": "********", | ||
"auth_endpoint": "https://accounts.google.com/o/oauth2/v2/auth", | ||
"token_endpoint": "https://oauth2.googleapis.com/token", | ||
"scope": "https://www.googleapis.com/auth/userinfo.email", | ||
"response_type": "code", | ||
"redirect_uri": null, | ||
"code_challange_method" : "S256" | ||
} | ||
} | ||
] | ||
``` | ||
|
||
You can import the fixture file as follows: | ||
```bash | ||
python3 manage.py loaddata fixtures/idps.json --app accounts.IdentityProvider | ||
``` | ||
Finally, you can run the server: | ||
```bash | ||
python3 manage.py runserver 127.0.0.1:8000 | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
from django.contrib import admin | ||
|
||
# Register your models here. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
from django.apps import AppConfig | ||
|
||
|
||
class AccountsConfig(AppConfig): | ||
default_auto_field = 'django.db.models.BigAutoField' | ||
name = 'accounts' |
Oops, something went wrong.