(20250209) Something about MikrTik. Don't ask

This commit is contained in:
2025-02-09 16:24:05 +05:30
parent 69c7a98225
commit 2b5beeb9e2
2 changed files with 570 additions and 0 deletions
+165
View File
@@ -0,0 +1,165 @@
"""
AUTHOR:
Khushal P Soonderji
DATE:
Sunday, 9th Feb, 2025.
OBJECTIVE:
To provide an easy way to configure MikroTik devices remotely.
REFERENCES:
N/A
DOWNLOADS:
N/A
"""
# *****************************************************************************************************************
# ***** ****
# *** IMPORT ***
# ***** ****
# *****************************************************************************************************************
# To make sibling directories accessible for imports:
import sys
sys.path.append(".")
sys.path.append("..")
# System-level activities:
import io
import os
# My utils:
from utils_v2.string import json
# For SSH:
from paramiko import SSHClient, AutoAddPolicy
# *****************************************************************************************************************
# ***** ****
# *** MACROS / ONE-TIME INIT ***
# ***** ****
# *****************************************************************************************************************
# --- Nothing Yet
# *****************************************************************************************************************
# ***** ****
# *** VARIABLES ***
# ***** ****
# *****************************************************************************************************************
# --- Nothing Yet
# *****************************************************************************************************************
# ***** ****
# *** FUNCTIONS ***
# ***** ****
# *****************************************************************************************************************
def ssh_exec_one(ssh: SSHClient, command: str):
# Start by assuming failure:
result = {
"stdin": None,
"stdout": None,
"stderr": None,
"returnCode": -999,
"exception": None
}
try:
# Run the command:
stdin, stdout, stderr = ssh.exec_command(command)
print(stdin)
# Extract the results:
result["stdin"] = stdin.read().decode("utf8")
result["stdout"] = stdout.read().decode("utf8")
result["stderr"] = stderr.read().decode("utf8")
result["returnCode"] = stdout.channel.recv_exit_status()
# Close the file-like objects:
stdin.close()
stdout.close()
stderr.close()
# If something goes wrong:
except Exception as exception:
result["exception"] = exception
raise exception
# Done here:
return result
# ---------------------------------------------------------------------------------------------------------------------
def ssh_test(config: dict):
# Initialize the object:
ssh = SSHClient()
# ssh.load_host_keys("~/.ssh/known_hosts")
ssh.load_system_host_keys()
ssh.set_missing_host_key_policy(AutoAddPolicy())
# Log in to the SSH client:
ssh.connect(
hostname = config["nasIp"],
port = 19991,
username = config["username"],
password = config["password"]
)
# Execute the needed commands:
result = ssh_exec_one(ssh, "hostname")
print("EXEC ONE JSON:", json.to_string(result, default = str))
# Close the connection:
ssh.close()
# *****************************************************************************************************************
# ***** ****
# *** MAIN PROGRAM ***
# ***** ****
# *****************************************************************************************************************
if __name__ == "__main__":
# The expected configuration structure from the database:
sample_config_json = {
"siteName": "Hirani Telcom",
# "nasIp": "102.210.175.251",
"nasIp": "wtt.ditscentre.in",
"radius": "102.210.175.242",
"secret": "abcdefgh",
# "username": "easyfi",
"username": "chaalu",
# "password": "easyfi",
"password": "hellochaalu",
"location": "Kenya",
"snmpCommunity": "abcdefgh"
}
ssh_test(config = sample_config_json)
+405
View File
@@ -0,0 +1,405 @@
# MiktoTik Configuration Steps
### We need to configure MikroTik servers for two end use cases - PPPoE or HotSpot. here are the steps to achieve them through MikroTik's REST API facility. Use the `MiktoTik (EasyFi)` Postman collection for this.
#### Authors: Bhushan, Hari, Khushal
#### Date: 20250209
### General Notes:
Private IP series has been allocated for doing carrier-grade NAT = 100.64.0.0/10
PPPoE user master subnet = 100.64.0.0/16
pppoe_ip_subnet: 100.64.0.0/24 = if user is under 256
pppoe_ip_subnet: 100.64.0.0/23 = if user is under 512
pppoe_ip_subnet: 100.64.0.0/22 = if user is under 1024
pppoe_ip_subnet: 100.64.0.0/21 = if user is under 2048
PPPoE deactivated user master subnet = 10.0.0.0/16
HotSpot user master subnet = 100.65.0.0/16
hotspot_ip_subnet: 100.65.0.0/24 = if user is under 256
hotspot_ip_subnet: 100.65.0.0/23 = if user is under 512
hotspot_ip_subnet: 100.65.0.0/22 = if user is under 1024
hotspot_ip_subnet: 100.65.0.0/21 = if user is under 2048
---
## Steps for HotSpot
### 1. Interface
- Enlist the available interfaces.
- Select the first one that has field `"running"` set to `"false"`, and pick its `".id"`.
- Rename it to `"hs-easyfi"` by its `".id"`.
### 2. Create a VLAN
Create a VLAN with the following config:
```json
{
"name": "easyfi-vlan-<vlan_id>",
"interface": "easyfi-hs", // The name that was given in the previous step.
"vlan-id": "<vlan_id>", // From the config received on the portal.
"disabled": "no"
}
```
### 3. Add a new IP Address to the VLAN interface
```json
{
"address": "<hotspot_ip_subnet>", // Refer to the general notes.
"interface": "easyfi-vlan-<vlan_id>", // Same as the 'name' given in the previous step.
"disabled": "no"
}
```
### 4. Add a New IP Pool for HotSpot Users
```json
{
"name": "easyfi-hs-pool-<vlan_id>",
"ranges": "<hotspot_ip_subnet>" // Refer to the general notes.
}
```
### 5. Add a New HotSpot Profile
```json
{
"dns-name": "hs01.easyfi.net.in",
"hotspot-address": "100.65.0.1", // First from the subnet. Refer to the general notes.
"html-directory": "hotspot",
"html-directory-override": "",
"http-cookie-lifetime": "3d",
"http-proxy": "0.0.0.0:0",
"install-hotspot-queue": "false",
"login-by": "cookie,http-chap",
"name": "hs01.easyfi.net.in",
"split-user-domain": "false",
"use-radius": "true",
"nas-port-type": "wireless-802.11",
"radius-accounting": "true",
"radius-default-domain": "",
"radius-interim-update": "received",
"radius-location-id": "",
"radius-location-name": "",
"radius-mac-format": "XX:XX:XX:XX:XX:XX"
}
```
### 6. Add a New HotSpot Server
```json
{
"address-pool": "easyfi-hs-pool-<vlan_id>", // Same as the name given when creating the pool.
"addresses-per-mac": "2",
"idle-timeout": "5m",
"interface": "easyfi-vlan-<vlan_id>", // Same as the 'name' given when creating the VLAN.
"keepalive-timeout": "none",
"login-timeout": "none",
"name": "hs01.easyfi.net.in",
"profile": "hs01.easyfi.net.in",
"disabled": "false"
}
```
### 7. Add a New DHCP Server
```json
{
"address-pool": "easyfi-hs-pool-<vlan_id>", // Same as the name given when creating the pool.
"authoritative": "yes",
"disabled": "false",
"interface": "easyfi-vlan-<vlan_id>", // Same as the 'name' given when creating the VLAN.
"lease-time": "30m",
"name": "easyfi-hs-dhcp-<vlan_id>",
"use-radius": "no"
}
```
### 8. Add a New DHCP Network
```json
{
"address": "<hotspot_ip_subnet>", // Refer to the general notes.
"gateway": "100.65.0.1", // First from the subnet. Refer to the general notes.
"netmask": "24", // Refer to the no. of users in the general notes.
"dns-server": "100.65.0.1" // First from the subnet. Refer to the general notes.
}
```
### 9. Whitelist the RADIUS Server IP in the HotSpot Server
Hint: Walled-Garden IPs
```json
{
"action": "accept",
"dst-address": "<radius_server_ip>" // Received from the portal.
}
```
### 10. Add a New RADIUS Server:
```json
{
"accounting-port": "1813",
"address": "<radius_server_ip>", // Received from the portal.
"authentication-port": "1812",
"disabled": "false",
"protocol": "udp",
"secret": "<radius_server_secret>", // Received from the portal.
"service": "ppp,login,hotspot,dhcp",
"timeout": "300ms"
}
```
### 11. Allow Incoming Communication from the RADIUS Server to the MikroTik Device
```json
{
"accept": "yes",
"port": "3799"
}
```
### 12. Add a New DNS Server
```json
{
"allow-remote-requests": "true",
"servers": "8.8.8.8,8.8.4.4"
}
```
### 13. Add Firewall Rules for NAT-ing
**NOTE:** Looping needed to split the bigger IP subnet into smaller subnets.
```json
{
"action": "src-nat",
"chain": "srcnat",
"disabled": "false",
"src-address": "100.65.0.16/28",
"to-addresses": "111.222.111.111"
}
```
### 14. Add a New SNMP Community
```json
{
"addresses": "::/0",
"authentication-password": "",
"authentication-protocol": "MD5",
"disabled": "false",
"encryption-password": "",
"encryption-protocol": "DES",
"name": "<random_16_chars>",
"read-access": "true",
"security": "none",
"write-access": "false" // ALWAYS FALSE
}
```
---
## Steps for PPPoE
### 1. Interface
- Enlist the available interfaces.
- Select the first one that has field `"running"` set to `"false"`, and pick its `".id"`.
- Rename it to `"easyfi-ppp"` by its `".id"`.
### 2. Create a VLAN
Create a VLAN with the following config:
```json
{
"name": "easyfi-vlan-<vlan_id>",
"interface": "easyfi-ppp", // The name that was given in the previous step.
"vlan-id": "<vlan_id>", // From the config received on the portal.
"disabled": "no"
}
```
### 3. Add a New IP Pool for PPPoE Users
```json
{
"name": "easyfi-ppp-pool-<vlan_id>",
"ranges": "<pppoe_ip_subnet>" // Refer to the general notes.
}
```
### 4. Add a New PPPoE Profile
```json
{
"address-list": "",
"bridge-learning": "default",
"change-tcp-mss": "yes",
"dns-server": "8.8.8.8",
"local-address": "102.210.175.251", // nasIP (MikroTik IP)
"name": "easyfi-ppp-profile",
"only-one": "yes",
"remote-address": "easyfi-ppp-pool-<vlan_id>",
"use-compression": "default",
"use-encryption": "default",
"use-ipv6": "yes",
"use-mpls": "default",
"use-upnp": "default"
}
```
### 5. Add a PPPoE Server
```json
{
"address-list": "",
"bridge-learning": "default",
"change-tcp-mss": "yes",
"default": "false",
"dns-server": "8.8.8.8",
"local-address": "102.210.175.251",
"name": "easyfi-ppp-profile",
"only-one": "yes",
"remote-address": "easyfi-ppp-pool-2001",
"use-compression": "default",
"use-encryption": "default",
"use-ipv6": "yes",
"use-mpls": "default",
"use-upnp": "default"
}
```
### 6. Allowing User Authentication RADIUS Server
```json
{
"accounting": "true",
"interim-update": "3m",
"use-circuit-id-in-nas-port-id": "false",
"use-radius": "true"
}
```
### 7. Add a New RADIUS Server:
```json
{
"accounting-port": "1813",
"address": "<radius_server_ip>", // Received from the portal.
"authentication-port": "1812",
"disabled": "false",
"protocol": "udp",
"secret": "<radius_server_secret>", // Received from the portal.
"service": "ppp,login,hotspot,dhcp",
"timeout": "300ms"
}
```
### 8. Allow Incoming Communication from the RADIUS Server to the MikroTik Device
```json
{
"accept": "yes",
"port": "3799"
}
```
### 9. Add Firewall Rules for NAT-ing
**NOTE:** Looping needed to split the bigger IP subnet into smaller subnets.
```json
{
"action": "src-nat",
"chain": "srcnat",
"disabled": "false",
"src-address": "100.64.0.16/28",
"to-addresses": "111.222.111.111"
}
```
### 10. Add a New SNMP Community
```json
{
"addresses": "::/0",
"authentication-password": "",
"authentication-protocol": "MD5",
"disabled": "false",
"encryption-password": "",
"encryption-protocol": "DES",
"name": "<random_16_chars>",
"read-access": "true",
"security": "none",
"write-access": "false" // ALWAYS FALSE
}
```
---
### General Notes:
- Master Block Private IP series used for Active Customers PPPoE and HotSpot range is 100.64.0.0/10
- - Private IP series used for Active Customers PPPoE and is 100.64.0.0/16
- Private IP series used for Active Customers HotSpot range is 100.65.0.0/16
- Private IP series used for Deactivated Customers PPPoE range is 10.0.0.0/16
---
### Steps for PPPoE:
- Create IP Pool.
- /ip/pool
- Add a new pool with the `"Name"` set to `"permitted"` and `Addresses` set to `100.64.0.0/24`.
- Add a new pool with the `"Name"` set to `"deactived"` and `Addresses` set to `10.0.0.0/16`.
- Create a PPPoE profile.
- /ppp/profiles
- Add a local address (Local Address is the WAN IP of the MikroTik) to the profile.
- Add a remote address to the profile with the `Name` set to `"permitted"`.
- Add a DNS server to the profile.
- Change `TCP MSS` to `"yes"`
- Change `Limits -> Only One` to `"yes"`
- /interface/pppoe-server
- Add a new server.
- Add service name (as per req.)
- Select the interface.
- Select the profile.
- Select authentication mechanism (chap/pap/mschap1/mschap2).
- Keepalive Timeout 900
- /ppp/secret/ppp-authorization and accounting, select use radius and accounting.
- Go to RADIUS
- Add service (select: ppp, login, hotspot, dhcp)
- Put in the RADIUS server's addr in the address col, select UDP as the protocol, put the secret.
- Go to IP firewall.
- NAT
- Create source-map (as per req.)
---
### Steps for HotSpot:
- Create IP Pool.
- /ip/pool
- Add a new pool with the `"Name"` set to `"hotspot"` and `Addresses` set to `100.65.0.0/24`.
- IP -> Hotspot -> Add -> Server Name = "New hotspot" -> Interface -> Pool -> Name = "hotspot" -> Add
- IP -> Addresses -> Add -> Address -> First IP from the Hotspot IP Pool as the gateway (100.65.0.1/24)