A REST API developed with FastAPI for managing network routes on a Linux machine using the ip command. It allows you to query active routes, create new routes, update or pause existing ones, and delete routes. The system includes route scheduling based on timestamps, persistence using SQLite, and lifecycle management through a background loop.
- Features
- Repository Layout
- Prerequisites
- Installation
- Usage
- API Documentation
- Logging
- Future development
- Security Considerations
- License
- Query Active Routes: Retrieve all routes currently active in the system and stored in the database.
- Create Routes: Add new routes with options to schedule their creation and deletion.
- Lifecycle Management: A background task checks and updates route states based on timestamps.
- Route Status: Each route can be in one of five states:
pending,active,paused,expired, ordeleted. - Pause/Resume Routes: Temporarily pause or resume active routes via dedicated endpoints.
- Delete Routes: Remove existing routes and unschedule their deletion.
- Deleted Routes History: A separate table
Deleted_Routestracks all expired or manually deleted routes. - Authentication: Protect endpoints using a Bearer token for authentication.
- Persistence: Store scheduled routes in a SQLite database to ensure they are reloaded after service restarts.
- Service: Integrate with systemd to run the API as a system service.
- Logging: Detailed logging of operations and errors for monitoring and debugging.
├── LICENSE # Licensing information for the repository
├── README.md # The documentation you are reading right now
├── .devcontainer/ # (Optional) Configuration for devcontainers.
├── .env # (Optional) Sample configuration values to overwrite the defaults
├── app/ # Main directory for the application code
│ ├── __init__.py # Makes "app" a "Python package" (ignore it)
│ ├── core/ # Configurations and global logic.
│ │ ├── __init__.py
│ │ ├── config.py # Global application settings
│ │ ├── logging.py # Global logging settings
│ ├── db/ # Database-related modules and utilities
│ │ ├── __init__.py
│ │ ├── database.py # Handles database connection and initialization
│ │ ├── models/ # Database models
│ │ │ ├── __init__.py
│ │ │ ├── routes.py # SQLModel for stored routes
│ │ │ └── deleted_routes.py # SQLModel for deleted routes
│ │ └── routes.py # Utilities for interaction with the routes database
│ ├── routers/ # Manage application routes
│ │ ├── __init__.py
│ │ └── routes.py # Defines API endpoints for routes
│ ├── schemas/ # Pydantic models for data validation and serialization
│ │ ├── __init__.py
│ │ └── routes.py # Main schemas for routes
│ ├── services/ # Auxiliary utilities and services for the API endpoints
│ │ ├── __init__.py
│ │ ├── auth.py # Functions related to user authentication and authorization
│ │ ├── lifecycle.py # Loop wich validate the routes status
│ │ ├── routes.py # Service functions for routes
│ │ └── utils.py # Miscellaneous utility functions
│ ├── tests/ # (Not yet implemented) Contains test modules
│ │ ├── __init__.py
│ │ └─── test_routes.py # (Not yet implemented) Tests for the Routes module
│ ├── __init__.py
│ └── main.py # Initializes the FastAPI application.
├── app_flow.drawio # Visual representation of the API endpoints and expected behaviour of the app
├── pyproject.toml # Python project configuration file used by tools like Poetry or uv (uv in our case)
└── uv.lock # Lock file where uv manages app dependencies
- Operating System: Linux-based. Tested on Ubuntu 22.04 and Debian 12.
- Python: Version 3.12 or higher
- Permissions: Superuser permissions to manage network routes (capability
NET_ADMIN) and to configuresystemdservices
All steps are intended to be run as root.
Clone this repository to your local machine:
git https://github.com/6G-SANDBOX/route-manager-api /opt/route-manager-api
cd route-manager-apiThe tool uv will take care for everything python-releated, from python versions, to virtual enviroments and dependencies.
curl -LsSf https://astral.sh/uv/install.sh | shDownload all necessary dependencies in a virtual environment as specified in the pyproject.toml file using uv
uv syncTo run the API as a system service, create a systemd unit file. Uf you want to directly try the tool, run:
uv run fastapi run --port 8172 # Default port is 8000Create a file named route-manager-api.service in /etc/systemd/system/:
cat > /etc/systemd/system/route-manager-api.service << 'EOF'
[Unit]
Description=A REST API developed with FastAPI for managing network routes on a Linux machine using the ip command. It allows you to query active routes, create new routes, and delete existing routes, with token-based authentication and persistence of scheduled routes to ensure their availability even after service restarts.
After=network.target
[Service]
Type=simple
User=root
Group=root
ExecStart=/root/.local/bin/uv --directory /opt/route-manager-api/ run fastapi run --port 8172
StandardOutput=append:/var/log/route_manager.log
StandardError=append:/var/log/route_manager.log
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOFsystemctl daemon-reload
systemctl enable route-manager-api.service
systemctl start route-manager-api.servicesystemctl status route-manager.serviceYou should see that the service is active and running. If there are any errors, they will appear in the output of this command.
The API offers the following endpoints:
| Method | Path | Description |
|---|---|---|
| GET | /routes/ |
Fetch current system & DB routes |
| PUT | /routes/ |
Add a new route (scheduled or now) |
| PATCH | /routes/ |
Update route fields |
| DELETE | /routes/ |
Remove a route manually |
| PATCH | /routes/pause |
Pause an active route |
| PATCH | /routes/activate |
Resume a paused route |
| GET | /routes/deleted |
Show deleted or expired routes |
WARNING: Beware the trailing slash
Each route progresses through the following states:
- pending: Waiting for
create_atto be reached - active: Between
create_atanddelete_at - paused: Manually paused by user during active state
- expired: Automatically marked after
delete_at - deleted: Manually removed by the user
The background lifecycle loop (runs every 10 seconds):
- Activates pending routes when their
create_atis reached - Expires active routes when
delete_atis reached - Ignores paused routes
curl -X 'GET' \
'http://localhost:8172/routes/' \
-H 'accept: application/json' \
-H 'Authorization: Bearer this_is_something_secret'Successful Response:
Code: 200
{
"database_routes": [
{
"via": "192.168.215.100",
"create_at": "2025-01-27T03:03:44.501824+00:00",
"to": "10.10.2.10/32",
"active": true,
"dev": null,
"delete_at": null
},
{
"via": null,
"create_at": "2027-01-30T09:38:59.284000+00:00",
"to": "10.20.30.0/24",
"active": false,
"dev": "eth0",
"delete_at": "2027-02-4T09:38:59.284000+00:00"
}
],
"system_routes": [
"default via 192.168.215.1 dev eth0",
"10.10.2.10/32 via 192.168.215.100 scope link",
"192.168.215.0/24 dev eth0 proto kernel scope link src 192.168.215.2"
]
}curl -X 'PUT' \
'http://localhost:8172/routes/' \
-H 'accept: application/json' \
-H 'Authorization: Bearer this_is_something_secret' \
-H 'Content-Type: application/json' \
-d '{
"to": "10.10.2.10/32",
"via": "192.168.215.100",
"create_at": "2025-01-27T03:03:44.501824+00:00"
}'Successful Response:
Code: 201
{
"message": "Route succesfully added or scheduled"
}Route already exists:
Also succesful to achieve idempotency
Code: 200
{
"message": "A route to 10.10.2.10/32 already exists in the system"
}curl -X 'DELETE' \
'http://localhost:8172/routes/' \
-H 'accept: application/json' \
-H 'Authorization: Bearer this_is_something_secret' \
-H 'Content-Type: application/json' \
-d '{
"to": "10.10.2.10"
}'Successful Response:
Code: 200
{
"message": "Route succesfully deleted"
}Route Not Found:
Code: 404
{
"detail": "Route to 10.10.2.10/32 not found in the database."
}curl -X 'PATCH' \
'http://localhost:8172/routes/' \
-H 'accept: application/json' \
-H 'Authorization: Bearer this_is_something_secret' \
-H 'Content-Type: application/json' \
-d '{
"to": "10.10.2.10/32",
"delete_at": "2025-01-27T03:03:44.501824+00:00"
}'Successful Response:
Code: 200
{
"message": "Route succesfully updated"
}Route Not Found:
Code: 404
{
"detail": "Route to 10.10.2.10/32 not found in the database."
}curl -X 'GET' \
'http://localhost:8172/routes/deleted' \
-H 'accept: application/json' \
-H 'Authorization: Bearer this_is_something_secret'Successful Response:
Code: 200
{
"deleted_routes": [
{
"create_at": "2025-03-19T18:40:00",
"to": "10.10.20.0/24",
"via": null,
"removed_at": "2025-03-24T18:11:06.458151+00:00",
"id": 1,
"dev": "eth0",
"delete_at": "2025-03-24T18:11:00",
"status": "expired"
},
{
"create_at": "2025-03-19T18:40:00",
"to": "10.10.20.0/24",
"via": null,
"removed_at": "2025-03-24T18:13:06.628571+00:00",
"id": 2,
"dev": "eth0",
"delete_at": "2025-03-24T18:13:00",
"status": "expired"
},
]
}curl -X PATCH http://localhost:8172/routes/pause \
-H 'Authorization: Bearer your_token' \
-H 'Content-Type: application/json' \
-d '{"to": "10.10.2.10/32"}'Successful Response:
Code: 200
{
"message": "Route succesfully paused"
}Route Not Found:
Code: 404
{
"detail": "Route to 10.10.2.10/32 not found in the database."
}curl -X PATCH http://localhost:8172/routes/activate \
-H 'Authorization: Bearer your_token' \
-H 'Content-Type: application/json' \
-d '{"to": "10.10.2.10/32"}'Successful Response:
Code: 200
{
"message": "Route succesfully activated"
}Route Not Found:
Code: 404
{
"detail": "Route to 10.10.2.10/32 not found in the database."
}FastAPI automatically generates interactive API documentation accessible at:
- Swagger UI: http://localhost:8172/docs
- Redoc: http://localhost:8172/redoc
The application logs detailed information about its operations and errors using Python's standard logging module. Logs include:
- Executed commands and their outputs.
- Route existence checks.
- Route creation and deletion operations.
- Database interactions.
- Authentication events.
By default, logs are displayed in the console where the service is running. To redirect logs to a file, modify the logging configuration in app/core/logging.py:
logging.basicConfig(
filename='app.log',
level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s"
)As seen in the app_flow.drawio, an internal loop will manage the lifecycle of routes stored in the database.
By default, the app will remove all routes added by it when terminating the service. This will be an optional feature, that can be disabled with an envvar.
When using this component inside the 6G-Sandbox bastion, added routes should also create exceptions for the highly restrictive firewall of the bastion.
Currently, the integration of the following ip route subcommands:
metrictablescopeprotosrcnexthoponlinkis not an urgent task, but the tool may be expanded to include them
Help is always welcomed, but yeah, some stuff might be improcise/wrong
- Authentication Token: The API uses a static token for Bearer authentication. Ensure you protect this token and change it to a secure value before deploying to production.
- Input Validation: While
pydanticis used for data validation, consider implementing additional security measures as needed for your environment.
This project is licensed under the MIT License. See the LICENSE file for more details.
Note: This project is designed for Linux environments with appropriate permissions to manage network routes. Ensure you understand the commands and configurations used before deploying to a production environment.