Compare commits
No commits in common. "65b5fca5f431b02c4b6c5e9036c0776b8ce3b0b9" and "9765095babb3a16c81df841731b5e279aa33a5ce" have entirely different histories.
65b5fca5f4
...
9765095bab
@ -1,27 +0,0 @@
|
|||||||
{
|
|
||||||
"mcpServers": {
|
|
||||||
"sequentialthinking": {
|
|
||||||
"command": "npx",
|
|
||||||
"args": [
|
|
||||||
"-y",
|
|
||||||
"@modelcontextprotocol/server-sequential-thinking"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"serena": {
|
|
||||||
"command": "uvx",
|
|
||||||
"args": [
|
|
||||||
"--from",
|
|
||||||
"git+https://github.com/oraios/serena",
|
|
||||||
"serena",
|
|
||||||
"start-mcp-server",
|
|
||||||
"--context",
|
|
||||||
"ide-assistant",
|
|
||||||
"--project",
|
|
||||||
"/Users/arthur/Desktop/code/vpn-access-server"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"context7": {
|
|
||||||
"url": "https://mcp.context7.com/sse"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,9 +1 @@
|
|||||||
3.13
|
3.13
|
||||||
|
|
||||||
.claude
|
|
||||||
.gemini
|
|
||||||
.serena
|
|
||||||
.venv
|
|
||||||
|
|
||||||
CLAUDE.md
|
|
||||||
GEMINI.md
|
|
||||||
|
|||||||
1
.serena/.gitignore
vendored
1
.serena/.gitignore
vendored
@ -1 +0,0 @@
|
|||||||
/cache
|
|
||||||
@ -1,71 +0,0 @@
|
|||||||
# language of the project (csharp, python, rust, java, typescript, go, cpp, or ruby)
|
|
||||||
# * For C, use cpp
|
|
||||||
# * For JavaScript, use typescript
|
|
||||||
# Special requirements:
|
|
||||||
# * csharp: Requires the presence of a .sln file in the project folder.
|
|
||||||
language: python
|
|
||||||
|
|
||||||
# the encoding used by text files in the project
|
|
||||||
# For a list of possible encodings, see https://docs.python.org/3.11/library/codecs.html#standard-encodings
|
|
||||||
encoding: "utf-8"
|
|
||||||
|
|
||||||
# whether to use the project's gitignore file to ignore files
|
|
||||||
# Added on 2025-04-07
|
|
||||||
ignore_all_files_in_gitignore: true
|
|
||||||
# list of additional paths to ignore
|
|
||||||
# same syntax as gitignore, so you can use * and **
|
|
||||||
# Was previously called `ignored_dirs`, please update your config if you are using that.
|
|
||||||
# Added (renamed) on 2025-04-07
|
|
||||||
ignored_paths: []
|
|
||||||
|
|
||||||
# whether the project is in read-only mode
|
|
||||||
# If set to true, all editing tools will be disabled and attempts to use them will result in an error
|
|
||||||
# Added on 2025-04-18
|
|
||||||
read_only: false
|
|
||||||
|
|
||||||
# list of tool names to exclude. We recommend not excluding any tools, see the readme for more details.
|
|
||||||
# Below is the complete list of tools for convenience.
|
|
||||||
# To make sure you have the latest list of tools, and to view their descriptions,
|
|
||||||
# execute `uv run scripts/print_tool_overview.py`.
|
|
||||||
#
|
|
||||||
# * `activate_project`: Activates a project by name.
|
|
||||||
# * `check_onboarding_performed`: Checks whether project onboarding was already performed.
|
|
||||||
# * `create_text_file`: Creates/overwrites a file in the project directory.
|
|
||||||
# * `delete_lines`: Deletes a range of lines within a file.
|
|
||||||
# * `delete_memory`: Deletes a memory from Serena's project-specific memory store.
|
|
||||||
# * `execute_shell_command`: Executes a shell command.
|
|
||||||
# * `find_referencing_code_snippets`: Finds code snippets in which the symbol at the given location is referenced.
|
|
||||||
# * `find_referencing_symbols`: Finds symbols that reference the symbol at the given location (optionally filtered by type).
|
|
||||||
# * `find_symbol`: Performs a global (or local) search for symbols with/containing a given name/substring (optionally filtered by type).
|
|
||||||
# * `get_current_config`: Prints the current configuration of the agent, including the active and available projects, tools, contexts, and modes.
|
|
||||||
# * `get_symbols_overview`: Gets an overview of the top-level symbols defined in a given file.
|
|
||||||
# * `initial_instructions`: Gets the initial instructions for the current project.
|
|
||||||
# Should only be used in settings where the system prompt cannot be set,
|
|
||||||
# e.g. in clients you have no control over, like Claude Desktop.
|
|
||||||
# * `insert_after_symbol`: Inserts content after the end of the definition of a given symbol.
|
|
||||||
# * `insert_at_line`: Inserts content at a given line in a file.
|
|
||||||
# * `insert_before_symbol`: Inserts content before the beginning of the definition of a given symbol.
|
|
||||||
# * `list_dir`: Lists files and directories in the given directory (optionally with recursion).
|
|
||||||
# * `list_memories`: Lists memories in Serena's project-specific memory store.
|
|
||||||
# * `onboarding`: Performs onboarding (identifying the project structure and essential tasks, e.g. for testing or building).
|
|
||||||
# * `prepare_for_new_conversation`: Provides instructions for preparing for a new conversation (in order to continue with the necessary context).
|
|
||||||
# * `read_file`: Reads a file within the project directory.
|
|
||||||
# * `read_memory`: Reads the memory with the given name from Serena's project-specific memory store.
|
|
||||||
# * `remove_project`: Removes a project from the Serena configuration.
|
|
||||||
# * `replace_lines`: Replaces a range of lines within a file with new content.
|
|
||||||
# * `replace_symbol_body`: Replaces the full definition of a symbol.
|
|
||||||
# * `restart_language_server`: Restarts the language server, may be necessary when edits not through Serena happen.
|
|
||||||
# * `search_for_pattern`: Performs a search for a pattern in the project.
|
|
||||||
# * `summarize_changes`: Provides instructions for summarizing the changes made to the codebase.
|
|
||||||
# * `switch_modes`: Activates modes by providing a list of their names
|
|
||||||
# * `think_about_collected_information`: Thinking tool for pondering the completeness of collected information.
|
|
||||||
# * `think_about_task_adherence`: Thinking tool for determining whether the agent is still on track with the current task.
|
|
||||||
# * `think_about_whether_you_are_done`: Thinking tool for determining whether the task is truly completed.
|
|
||||||
# * `write_memory`: Writes a named memory (for future reference) to Serena's project-specific memory store.
|
|
||||||
excluded_tools: []
|
|
||||||
|
|
||||||
# initial prompt for the project. It will always be given to the LLM upon activating the project
|
|
||||||
# (contrary to the memories, which are loaded on demand).
|
|
||||||
initial_prompt: ""
|
|
||||||
|
|
||||||
project_name: "vpn-access-server"
|
|
||||||
93
GEMINI.md
93
GEMINI.md
@ -1,93 +0,0 @@
|
|||||||
# GEMINI.md
|
|
||||||
|
|
||||||
## Project Overview
|
|
||||||
|
|
||||||
This project is a **VPN Access Server**, written in Python, designed to extend an OpenVPN server with custom authentication and session management features. It uses a MySQL database to store user information, authorized MAC addresses, and session data.
|
|
||||||
|
|
||||||
The core functionality is to:
|
|
||||||
1. **Validate MAC Addresses**: Ensure only devices with authorized MAC addresses can connect to the VPN.
|
|
||||||
2. **Enforce Session Time**: Manage and enforce session duration policies on a per-user basis.
|
|
||||||
|
|
||||||
The architecture is based on OpenVPN's `client-connect` and `client-disconnect` hooks, which execute Python scripts to perform the validation logic.
|
|
||||||
|
|
||||||
**Technologies:**
|
|
||||||
* **Language:** Python 3
|
|
||||||
* **Database:** MySQL
|
|
||||||
* **VPN:** OpenVPN (as the execution environment)
|
|
||||||
* **Dependencies:** `mysql-connector-python`, `pytest`
|
|
||||||
|
|
||||||
## Building and Running
|
|
||||||
|
|
||||||
The project is managed via a central command-line interface in `main.py`.
|
|
||||||
|
|
||||||
### Initial Setup
|
|
||||||
|
|
||||||
1. **Install Dependencies:**
|
|
||||||
```bash
|
|
||||||
uv pip install -r requirements.txt
|
|
||||||
```
|
|
||||||
*(Note: Based on `pyproject.toml`, you might use `uv pip install .` or `uv pip install -e .` for editable mode)*
|
|
||||||
|
|
||||||
2. **Configure Environment:**
|
|
||||||
Create a `.env` file based on `.env.example` and provide the necessary database credentials:
|
|
||||||
```bash
|
|
||||||
cp .env.example .env
|
|
||||||
# Edit .env with your DB settings
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Initialize the Database:**
|
|
||||||
This script will create the necessary tables (`employees`, `mac_addresses`, `sessions`) in the database.
|
|
||||||
```bash
|
|
||||||
python main.py init-db
|
|
||||||
```
|
|
||||||
|
|
||||||
### Running the Application
|
|
||||||
|
|
||||||
The main application logic is triggered by OpenVPN. However, you can run the individual components for testing or health checks.
|
|
||||||
|
|
||||||
* **Run a Health Check:**
|
|
||||||
Verifies the configuration and database connection.
|
|
||||||
```bash
|
|
||||||
python main.py health-check
|
|
||||||
```
|
|
||||||
|
|
||||||
* **Show Status:**
|
|
||||||
Displays the current configuration.
|
|
||||||
```bash
|
|
||||||
python main.py status
|
|
||||||
```
|
|
||||||
|
|
||||||
* **Run Authentication/Session Logic (Manual Simulation):**
|
|
||||||
These commands are intended to be called by OpenVPN but can be run manually if the required environment variables are set.
|
|
||||||
```bash
|
|
||||||
# Simulate OpenVPN client-connect
|
|
||||||
python main.py auth
|
|
||||||
|
|
||||||
# Simulate OpenVPN client-disconnect
|
|
||||||
python main.py session
|
|
||||||
```
|
|
||||||
|
|
||||||
### Running Tests
|
|
||||||
|
|
||||||
The project uses `pytest` for testing.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
python main.py test
|
|
||||||
```
|
|
||||||
or
|
|
||||||
```bash
|
|
||||||
pytest
|
|
||||||
```
|
|
||||||
|
|
||||||
## Development Conventions
|
|
||||||
|
|
||||||
* **Modular Architecture:** The code is structured into modules with clear responsibilities:
|
|
||||||
* `access/auth.py`: User authentication and MAC validation.
|
|
||||||
* `access/session.py`: Session management.
|
|
||||||
* `access/db.py`: Database interaction.
|
|
||||||
* `access/config.py`: Configuration loading.
|
|
||||||
* `access/utils.py`: Shared utility functions.
|
|
||||||
* **Configuration:** Configuration is loaded from environment variables, following the 12-factor app methodology. A `.env` file is used for local development.
|
|
||||||
* **Database Management:** Database connections are managed through a connection pool in `db.py` for efficiency. All SQL queries are centralized in this file.
|
|
||||||
* **CLI:** A single entry point (`main.py`) provides a consistent way to interact with and manage the application.
|
|
||||||
* **Testing:** Unit tests are located in the `tests/` directory and can be run with `pytest`.
|
|
||||||
@ -1,102 +0,0 @@
|
|||||||
1. run this command to generated rquired client file:
|
|
||||||
```commandline
|
|
||||||
cd /etc/openvpn/easy-rsa/
|
|
||||||
./easyrsa build-client-full <username> nopass
|
|
||||||
```
|
|
||||||
# example create test client key for user name: [arthur]
|
|
||||||
arthur@server:~/openvpn-ca$ ./easyrsa gen-req arthur nopass
|
|
||||||
Using Easy-RSA 'vars' configuration:
|
|
||||||
* /home/arthur/openvpn-ca/vars
|
|
||||||
|
|
||||||
Using SSL:
|
|
||||||
* openssl OpenSSL 3.0.13 30 Jan 2024 (Library: OpenSSL 3.0.13 30 Jan 2024)
|
|
||||||
....+...+...+..+.......+.....+......+...+.......+.....+...+..........+.....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*..+....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*.+...........+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
..+...............+...+.....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*.+............+......+.......+.....+...+....+..+......+.......+......+......+......+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*...+..+......+....+..................+...+.....+.......+...+......+.....+....+.........+......+.....+....+..+.+........+......+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
-----
|
|
||||||
You are about to be asked to enter information that will be incorporated
|
|
||||||
into your certificate request.
|
|
||||||
What you are about to enter is what is called a Distinguished Name or a DN.
|
|
||||||
There are quite a few fields but you can leave some blank
|
|
||||||
For some fields there will be a default value,
|
|
||||||
If you enter '.', the field will be left blank.
|
|
||||||
-----
|
|
||||||
Common Name (eg: your user, host, or server name) [arthur]:
|
|
||||||
|
|
||||||
Notice
|
|
||||||
------
|
|
||||||
Private-Key and Public-Certificate-Request files created.
|
|
||||||
Your files are:
|
|
||||||
* req: /home/arthur/openvpn-ca/pki/reqs/arthur.req
|
|
||||||
* key: /home/arthur/openvpn-ca/pki/private/arthur.key
|
|
||||||
|
|
||||||
arthur@server:~/openvpn-ca$ ./easyrsa sign-req client arthur
|
|
||||||
Using Easy-RSA 'vars' configuration:
|
|
||||||
* /home/arthur/openvpn-ca/vars
|
|
||||||
|
|
||||||
Using SSL:
|
|
||||||
* openssl OpenSSL 3.0.13 30 Jan 2024 (Library: OpenSSL 3.0.13 30 Jan 2024)
|
|
||||||
You are about to sign the following certificate:
|
|
||||||
Please check over the details shown below for accuracy. Note that this request
|
|
||||||
has not been cryptographically verified. Please be sure it came from a trusted
|
|
||||||
source or that you have verified the request checksum with the sender.
|
|
||||||
Request subject, to be signed as a client certificate
|
|
||||||
for '825' days:
|
|
||||||
|
|
||||||
subject=
|
|
||||||
commonName = arthur
|
|
||||||
|
|
||||||
Type the word 'yes' to continue, or any other input to abort.
|
|
||||||
Confirm request details: yes
|
|
||||||
|
|
||||||
Using configuration from /home/arthur/openvpn-ca/pki/openssl-easyrsa.cnf
|
|
||||||
Check that the request matches the signature
|
|
||||||
Signature ok
|
|
||||||
The Subject's Distinguished Name is as follows
|
|
||||||
commonName :ASN.1 12:'arthur'
|
|
||||||
Certificate is to be certified until Dec 19 04:09:41 2027 GMT (825 days)
|
|
||||||
|
|
||||||
Write out database with 1 new entries
|
|
||||||
Database updated
|
|
||||||
|
|
||||||
Notice
|
|
||||||
------
|
|
||||||
Certificate created at:
|
|
||||||
* /home/arthur/openvpn-ca/pki/issued/arthur.crt
|
|
||||||
|
|
||||||
|
|
||||||
2. OpenVPN Server Configuration\
|
|
||||||
```commandline
|
|
||||||
|
|
||||||
### Check location of key before copy
|
|
||||||
------
|
|
||||||
CA creation complete. Your new CA certificate is at:
|
|
||||||
* /home/arthur/openvpn-ca/pki/ca.crt
|
|
||||||
------
|
|
||||||
Certificate created at:
|
|
||||||
* /home/arthur/openvpn-ca/pki/issued/server.crt
|
|
||||||
------
|
|
||||||
Private-Key and Public-Certificate-Request files created.
|
|
||||||
Your files are:
|
|
||||||
* req: /home/arthur/openvpn-ca/pki/reqs/server.req
|
|
||||||
* key: /home/arthur/openvpn-ca/pki/private/server.key
|
|
||||||
------
|
|
||||||
DH parameters of size 2048 created at:
|
|
||||||
* /home/arthur/openvpn-ca/pki/dh.pem
|
|
||||||
------
|
|
||||||
TA Key at:
|
|
||||||
* /home/arthur/openvpn-ca/ta.key
|
|
||||||
|
|
||||||
### Start copying requirement files
|
|
||||||
arthur@server:~/openvpn-ca$ sudo cp pki/ca.crt pki/issued/server.crt pki/private/server.key ta.key pki/dh.pem /etc/openvpn/server/
|
|
||||||
|
|
||||||
### Check the destination again
|
|
||||||
arthur@server:~/openvpn-ca$ ls -la /etc/openvpn/server/
|
|
||||||
total 32
|
|
||||||
drwxr-xr-x 2 root root 4096 Sep 15 04:17 .
|
|
||||||
drwxr-xr-x 4 root root 4096 Sep 15 03:39 ..
|
|
||||||
-rw------- 1 root root 1245 Sep 15 04:17 ca.crt
|
|
||||||
-rw------- 1 root root 424 Sep 15 04:17 dh.pem
|
|
||||||
-rw------- 1 root root 4728 Sep 15 04:17 server.crt
|
|
||||||
-rw------- 1 root root 1708 Sep 15 04:17 server.key
|
|
||||||
-rw------- 1 root root 636 Sep 15 04:17 ta.key
|
|
||||||
```
|
|
||||||
30
main.py
30
main.py
@ -104,14 +104,6 @@ def show_status():
|
|||||||
print(f"Max Session Limit: {config.server.max_session_limit}s ({config.server.max_session_limit//3600}h)")
|
print(f"Max Session Limit: {config.server.max_session_limit}s ({config.server.max_session_limit//3600}h)")
|
||||||
print("=" * 50)
|
print("=" * 50)
|
||||||
|
|
||||||
from util.client.generate_client import generate_client_config
|
|
||||||
|
|
||||||
|
|
||||||
def run_gen_client(username: str):
|
|
||||||
"""Generate a client .ovpn file."""
|
|
||||||
generate_client_config(username)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""Main entry point with command-line interface."""
|
"""Main entry point with command-line interface."""
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
@ -126,7 +118,6 @@ Examples:
|
|||||||
%(prog)s test # Run unit tests
|
%(prog)s test # Run unit tests
|
||||||
%(prog)s health-check # Check system health
|
%(prog)s health-check # Check system health
|
||||||
%(prog)s status # Show configuration status
|
%(prog)s status # Show configuration status
|
||||||
%(prog)s gen-client <user> # Generate a client .ovpn file
|
|
||||||
|
|
||||||
Environment Variables:
|
Environment Variables:
|
||||||
DB_HOST, DB_PORT, DB_NAME, DB_USER, DB_PASSWORD
|
DB_HOST, DB_PORT, DB_NAME, DB_USER, DB_PASSWORD
|
||||||
@ -136,18 +127,11 @@ See .env.example for full configuration options.
|
|||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
subparsers = parser.add_subparsers(dest='command', help='Commands')
|
parser.add_argument(
|
||||||
|
'command',
|
||||||
subparsers.add_parser('auth', help='Run authentication (for OpenVPN)')
|
choices=['auth', 'session', 'init-db', 'seed-data', 'test', 'health-check', 'status'],
|
||||||
subparsers.add_parser('session', help='Run session management (for OpenVPN)')
|
help='Command to execute'
|
||||||
subparsers.add_parser('init-db', help='Initialize database schema')
|
)
|
||||||
subparsers.add_parser('seed-data', help='Add sample data for testing')
|
|
||||||
subparsers.add_parser('test', help='Run unit tests')
|
|
||||||
subparsers.add_parser('health-check', help='Check system health')
|
|
||||||
subparsers.add_parser('status', help='Show configuration status')
|
|
||||||
|
|
||||||
gen_client_parser = subparsers.add_parser('gen-client', help='Generate a client .ovpn file')
|
|
||||||
gen_client_parser.add_argument('username', help='Username for the client config')
|
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--version',
|
'--version',
|
||||||
@ -155,7 +139,7 @@ See .env.example for full configuration options.
|
|||||||
version='VPN Access Server 1.0.0'
|
version='VPN Access Server 1.0.0'
|
||||||
)
|
)
|
||||||
|
|
||||||
if len(sys.argv) < 2:
|
if len(sys.argv) == 1:
|
||||||
parser.print_help()
|
parser.print_help()
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
@ -177,8 +161,6 @@ See .env.example for full configuration options.
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
elif args.command == 'status':
|
elif args.command == 'status':
|
||||||
show_status()
|
show_status()
|
||||||
elif args.command == 'gen-client':
|
|
||||||
run_gen_client(args.username)
|
|
||||||
|
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
print("\n⚠️ Operation cancelled by user")
|
print("\n⚠️ Operation cancelled by user")
|
||||||
|
|||||||
@ -1,69 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
if [[ $# -ne 4 ]]; then
|
|
||||||
cat >&2 <<USAGE
|
|
||||||
Usage: $0 /path/to/ca.crt /path/to/clientname.crt /path/to/clientname.key /path/to/ta.key
|
|
||||||
Example: ./gen-client.sh /etc/openvpn/ca.crt ./client1.crt ./client1.key ./ta.key
|
|
||||||
This writes output to stdout and also saves to ./<clientname>.ovpn
|
|
||||||
USAGE
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
ca="$1"
|
|
||||||
cert="$2"
|
|
||||||
key="$3"
|
|
||||||
ta="$4"
|
|
||||||
|
|
||||||
# verify files exist and are readable
|
|
||||||
for f in "$ca" "$cert" "$key" "$ta"; do
|
|
||||||
if [[ ! -r "$f" ]]; then
|
|
||||||
echo "Error: cannot read file '$f'." >&2
|
|
||||||
exit 2
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
# derive client name from certificate filename (remove extension)
|
|
||||||
clientname="$(basename "$cert")"
|
|
||||||
clientname="${clientname%.*}"
|
|
||||||
outfile="${clientname}.ovpn"
|
|
||||||
|
|
||||||
# build and write config (also send to stdout). Use a block to avoid command-substitution problems with large files.
|
|
||||||
{
|
|
||||||
cat <<'HEADER'
|
|
||||||
client
|
|
||||||
dev tun
|
|
||||||
proto udp
|
|
||||||
remote 14.241.240.102 1194 # use FTP IP address
|
|
||||||
resolv-retry infinite
|
|
||||||
nobind
|
|
||||||
persist-key
|
|
||||||
persist-tun
|
|
||||||
remote-cert-tls server
|
|
||||||
cipher AES-256-GCM
|
|
||||||
# push mac address info
|
|
||||||
push-peer-info
|
|
||||||
verb 3
|
|
||||||
|
|
||||||
HEADER
|
|
||||||
|
|
||||||
echo "<ca>"
|
|
||||||
cat "$ca"
|
|
||||||
echo "</ca>"
|
|
||||||
echo
|
|
||||||
echo "<cert>"
|
|
||||||
cat "$cert"
|
|
||||||
echo "</cert>"
|
|
||||||
echo
|
|
||||||
echo "<key>"
|
|
||||||
cat "$key"
|
|
||||||
echo "</key>"
|
|
||||||
echo
|
|
||||||
echo "<tls-auth>"
|
|
||||||
cat "$ta"
|
|
||||||
echo "</tls-auth>"
|
|
||||||
echo "key-direction 1"
|
|
||||||
} | tee "$outfile"
|
|
||||||
|
|
||||||
echo "Wrote config to ./${outfile}"
|
|
||||||
|
|
||||||
Binary file not shown.
@ -1,89 +0,0 @@
|
|||||||
"""
|
|
||||||
Utility for generating OpenVPN client configuration files.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
def generate_client_config(username: str):
|
|
||||||
"""
|
|
||||||
Generates a .ovpn file for a given user.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
username: The username for which to generate the config.
|
|
||||||
"""
|
|
||||||
ca_path = "/home/arthur/openvpn-ca/pki/ca.crt"
|
|
||||||
ta_path = "/home/arthur/openvpn-ca/ta.key"
|
|
||||||
client_crt_path = f"/home/arthur/openvpn-ca/pki/issued/{username}.crt"
|
|
||||||
client_key_path = f"/home/arthur/openvpn-ca/pki/private/{username}.key"
|
|
||||||
output_path = f"/etc/openvpn/client/{username}.ovpn"
|
|
||||||
|
|
||||||
# Verify that all required files exist
|
|
||||||
for f in [ca_path, ta_path, client_crt_path, client_key_path]:
|
|
||||||
if not os.path.isfile(f):
|
|
||||||
print(f"Error: Cannot read file '{f}'.")
|
|
||||||
return
|
|
||||||
|
|
||||||
# Read the content of the files
|
|
||||||
try:
|
|
||||||
with open(ca_path, 'r') as f:
|
|
||||||
ca_content = f.read()
|
|
||||||
with open(client_crt_path, 'r') as f:
|
|
||||||
client_crt_content = f.read()
|
|
||||||
with open(client_key_path, 'r') as f:
|
|
||||||
client_key_content = f.read()
|
|
||||||
with open(ta_path, 'r') as f:
|
|
||||||
ta_content = f.read()
|
|
||||||
except IOError as e:
|
|
||||||
print(f"Error reading files: {e}")
|
|
||||||
return
|
|
||||||
|
|
||||||
# Assemble the .ovpn configuration
|
|
||||||
ovpn_config = f"""
|
|
||||||
client
|
|
||||||
dev tun
|
|
||||||
proto udp
|
|
||||||
remote 14.241.240.102 1194 # use FTP IP address
|
|
||||||
resolv-retry infinite
|
|
||||||
nobind
|
|
||||||
persist-key
|
|
||||||
persist-tun
|
|
||||||
remote-cert-tls server
|
|
||||||
cipher AES-256-GCM
|
|
||||||
# push mac address info
|
|
||||||
push-peer-info
|
|
||||||
verb 3
|
|
||||||
|
|
||||||
<ca>
|
|
||||||
{ca_content}
|
|
||||||
</ca>
|
|
||||||
|
|
||||||
<cert>
|
|
||||||
{client_crt_content}
|
|
||||||
</cert>
|
|
||||||
|
|
||||||
<key>
|
|
||||||
{client_key_content}
|
|
||||||
</key>
|
|
||||||
|
|
||||||
<tls-auth>
|
|
||||||
{ta_content}
|
|
||||||
</tls-auth>
|
|
||||||
key-direction 1
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Write the configuration to the output file
|
|
||||||
try:
|
|
||||||
# Ensure the output directory exists
|
|
||||||
output_dir = os.path.dirname(output_path)
|
|
||||||
if not os.path.exists(output_dir):
|
|
||||||
# This part is tricky because of permissions.
|
|
||||||
# For now, we assume the directory exists.
|
|
||||||
# On a real server, this would be handled by deployment scripts.
|
|
||||||
pass
|
|
||||||
|
|
||||||
with open(output_path, 'w') as f:
|
|
||||||
f.write(ovpn_config)
|
|
||||||
print(f"Successfully generated client config: {output_path}")
|
|
||||||
except IOError as e:
|
|
||||||
print(f"Error writing to file: {e}")
|
|
||||||
|
|
||||||
Loading…
Reference in New Issue
Block a user