Files
mikrotik-proxy-api/README.md
T

187 lines
5.4 KiB
Markdown
Raw Normal View History

2026-09-20 19:47:02 +03:00
# MikroTik Proxy API Dashboard
A modern, secure web interface and proxy API for managing MikroTik Firewall Address Lists. Designed for remote control with IP identification and administrative management.
## 🌟 Key Features
- **JWT Authentication**: Secure administrative access with username/password hashing.
- **Structured List Management**: Define named lists (e.g., `trusted`, `guests`) and assign IPs via a strict interface.
- **Client Dashboard**: Pure IP-based identification for end-users to toggle their own access status.
- **Glassmorphism UI**: Premium, responsive interface using modern CSS and the "Outfit" typography.
- **SQLite Integration**: Local source of truth for synchronization consistency.
---
## 🏗 Architecture
```mermaid
graph TD
Client[End-User Browser] -->|IP Auth| API[Flask Proxy]
Admin[Admin Browser] -->|JWT Auth| API
API --> DB[(SQLite DB)]
API --> MT[MikroTik RouterOS]
```
---
## ⚙️ Configuration
Copy `.env.example` to `.env` and fill in your details:
| Variable | Description |
| :--- | :--- |
| `MT_HOST` | MikroTik Router IP/Hostname |
| `MT_USER` | MikroTik API User |
| `MT_PASS` | MikroTik API Password |
| `APP_SECRET_KEY` | Key for signing JWT tokens |
| `ADMIN_PASS` | Initial password for the `admin` user |
---
## 🚀 Installation & Deployment
### 1. Requirements
- Python 3.8+
- `pip install -r requirements.txt`
### 2. Running as a Service
#### **Alpine Linux (OpenRC)**
Create `/etc/init.d/mt-proxy`:
```bash
#!/sbin/openrc-run
description="MikroTik Proxy API"
command="/usr/bin/python3"
command_args="/path/to/app/main.py"
command_background="yes"
pidfile="/run/mt-proxy.pid"
directory="/path/to/app"
environment="PYTHONPATH=/path/to/app"
depend() {
need net
}
```
`chmod +x /etc/init.d/mt-proxy && rc-update add mt-proxy default && rc-service mt-proxy start`
#### **Debian / Ubuntu (systemd)**
Create `/etc/systemd/system/mt-proxy.service`:
```ini
[Unit]
Description=MikroTik Proxy API
After=network.target
[Service]
User=www-data
WorkingDirectory=/var/www/mt-proxy
Environment="PATH=/var/www/mt-proxy/venv/bin"
ExecStart=/var/www/mt-proxy/venv/bin/python main.py
Restart=always
[Install]
WantedBy=multi-user.target
```
`systemctl enable mt-proxy && systemctl start mt-proxy`
---
## 🌐 Nginx Reverse Proxy
To access the API on port 80/443:
```nginx
server {
listen 80;
server_name proxy.example.com;
location / {
proxy_pass http://127.0.0.1:5001;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
```
---
## 🛠 API Documentation
### 1. Authentication
*Used to obtain a JWT token for administrative actions.*
**POST** `/api/v1/auth/login`
- **Body**: `{"username": "admin", "password": "..."}`
- **Success (200)**:
```json
{
"success": true,
"data": { "token": "ey..." }
}
```
- **Error (401)**: `{"success": false, "error": "Invalid credentials"}`
---
### 2. Administrative API (Protected)
*Required Header: `Authorization: Bearer <token>`*
#### **Address Assignments**
- **GET** `/api/v1/addresses`: List all IP assignments.
- **Success**: `{"success": true, "data": [{"id": 1, "ip": "1.2.3.4", "list_name": "trusted", "enabled": true, ...}]}`
- **POST** `/api/v1/addresses`: Assign IP to a list.
- **Body**: `{"address": "1.2.3.4", "list": "trusted", "comment": "Work PC"}`
- **Success (201)**: `{"success": true, "data": {"mikrotik_id": "*1A"}}`
- **DELETE** `/api/v1/addresses/<id>`: Remove assignment.
- **PUT** `/api/v1/addresses/<id>/enable`: Activate IP.
- **PUT** `/api/v1/addresses/<id>/disable`: Deactivate IP.
#### **Named Lists Management**
- **GET** `/api/v1/named-lists`: List all managed address lists.
- **Success**: `{"success": true, "data": [{"id": 1, "name": "trusted"}, {"id": 2, "name": "guests"}]}`
- **POST** `/api/v1/named-lists`: Create a new list name.
- **Body**: `{"name": "office_vpn"}`
- **DELETE** `/api/v1/named-lists/<id>`: Remove list definition.
- **Error (400)**: `{"success": false, "error": "Cannot delete: 5 addresses are still in this list"}`
#### **Profile Management**
- **POST** `/api/v1/admin/profile`: Update your credentials.
- **Body**: `{"username": "new_admin", "password": "new_password"}` (password optional)
---
### 3. Client Dashboard API (No Auth)
*Determines status based on the calling user's public IP.*
#### **Check Status**
- **GET** `/api/v1/client/status`
- **Success (200)**:
```json
{
"success": true,
"data": {
"ip": "82.202.10.5",
"enabled": true,
"list": "trusted",
"comment": "Home Office"
}
}
```
- **Forbidden (403)**: `{"success": false, "error": "Access denied for IP 8.8.8.8"}` (IP not in any whitelist)
#### **Toggle Status**
- **PUT** `/api/v1/client/toggle`
- **Success**: `{"success": true, "data": {"new_state": false}}`
---
## 🔍 Architecture & Sync Details
- **Master Database**: SQLite is the source of truth. Changes are committed to DB *before* calling the MikroTik API to ensure consistency.
- **MikroTik Sync**: The proxy uses the native MikroTik API (`/ip/firewall/address-list/set`) using internal IDs for high performance.
- **Security**: Admin passwords are salted and hashed using PBKDF2. JWT tokens expire after 24 hours.
## 📜 Maintenance
- **Primary Admin**: Created automatically on first run using values from `.env`.
- **Logs**: Standard output. On Alpine/Debian, use `logread` or `journalctl -u mt-proxy`.