# MikroTik (PPPoE) Configuration Steps for 1,000 Clients
#### 20250210 / Khushal P S  
We need to configure MikroTik servers for the end use case of "PPPoE". Here are the steps to achieve it through 
MikroTik's REST API facility. Use the `MiktoTik (EasyFi)` Postman collection for this.

---

## Before We Begin

MikroTik allows access via REST API using Basic-Auth headers which take a `username` and a `password`. The base path 
would look something like `http://<ip-addr>/rest`. You may need to mention a port no. if the default has been changed. 

You must also know what are "Private" and "Public" IP addresses in the context of an ISP. For an ISP, every IP that he
gives to his client is "Private" to his network, and every IP that he uses to connect his client to the broader internet
is a "Public" IP. Typically, many private IPs use the same public IP to connect to the internet. You will configure this
ratio in the NAT-ing step.

### Broad Steps

- We first select a physical interface.
- Then we create all the needed VLANs and point them to the physical interface. Let's say this no. is 'n'.
- Then we cut up the full private IP block into 'n' pools.
- Then we create 'n' no. of PPPoE profiles such that each profile gets one private IP pool. 
- Then we create 'n' no. of PPPoE servers such that each server gets one IP pool (through a profile), and one VLAN interface.
- Set up AAA such that we use RADIUS.
- Then we add the given RADIUS server's config.
- Then we allow incoming traffic from RADIUS servers.
- Then we populate the NAT table with rules.
- Then we add a new SNMP community.

---

## Steps for PPPoE

### 1. Select a Physical Interface

In this step you must pick the first available interface that is not being used elsewhere. Mind you that this interface 
is an actual physical connectivity interface (typically ethernet) on the MikroTik device.

- Enlist the available interfaces using the listing API on the `/interface` path using `GET` method.
- Select the first one that has field `"running"` set to `"false"`, and pick its `".id"` value.
- Rename it to `"easyfi-pppoe"` by its `".id"` on the `/interface/<.id>` path using `PATCH` method.

**ROLL-BACK:** Save the original configuration as a JSON string in the `comment` field.

### 2. Create VLAN Interfaces

You will be given a range of VLAN interfaces like `"2001-2010"`. Create on VLAN for each id such that the value of the
name of the `"interface"` that you set for it is set to `"easyfi-pppoe"` (the name of the physical interface). 

Use `PUT` or `PATCH` method on the path `/interface/vlan`. Consider to the following example JSON:
```json
{
    "name": "easyfi-vlan-2001",  // .... Use the VLAN id in the name.
    "interface": "easyfi-pppoe",  // ... The h/w interface that you prepared in the prev. step.
    "vlan-id": "2001",  // ............. The VLAN id.
    "disabled": "false",  // ........... To ensure it is enabled by default.
    "comment": "{...}"  // ............. The JSON string to indicate automated config. 
}
```

**NOTE:** Looping needed.

**ROLL-BACK:** Save the original configuration as a JSON string in the `comment` field. If there was no original 
configuration, simply delete your record.

### 3. Create Private IP Subnets (a.k.a. Pools/Ranges)

You will receive the Private IP range in either CIDR notation or as a hyphen-separated string. You need to cut up this
larger IP pool into subnets that you will eventually assign to each VLAN (by way of creating PPPoE servers).

**WARNING:** It is possible to have IP pools in a MikroTik device with overlapping IP addresses. It is not recommended, 
though, because it may lead to conflicts that could be hard to trace back.

Use `PUT` or `PATCH` method on the path `/ip/pool`. Consider to the following example JSON:
```json
{
    "name": "easyfi-pppoe-pool-2001",  // ... Use the VLAN id in the name.
    "ranges": "100.64.0.0/24",  // .......... The subnet for the associated VLAN id.
    "comment": "{...}"  // .................. The JSON string to indicate automated config.
}
```

**NOTE:** Looping needed.

**ROLL-BACK:** Identify your entry from the `name` field (contains 'easyfi') or from the contents of the `comment` field
and remove it.

### 4. Create PPPoE Profiles

Now we are ready to create PPPoE profiles. A profile is like a blueprint for the servers we will create later. It 
defines the rules that the server must follow. For now, our major focus is on telling the server which private IP pool
to use. We create the same no. of PPPoE profiles as we have created VLANs.

Use `PUT` or `PATCH` method on the path `/ppp/profile`. Consider to the following example JSON:
```json
{
    "name": "easyfi-pppoe-prf-2001",  // .............. Use the VLAN id in the name.
    "local-address": "192.168.10.1",  // .............. The IP address of the MikroTik device itself (NAS IP). 
    "remote-address": "easyfi-pppoe-pool-2001",  // ... Use the VLAN id in the name.
    "comment": "{...}"  // ............................ The JSON string to indicate automated config.
}
```

**NOTE:** Looping needed.

**ROLL-BACK:** Save the original configuration as a JSON string in the `comment` field. If there was no original 
configuration, simply delete your record.

### 5. Create PPPoE Servers

Here's where we tie up ALL the steps we've done so far!

In this step we spin up actual server instances (software) that handle the PPPoE traffic. On one hand we have virtual
sub-blocks of our private IP pool, and on the other we have VLANs that point to the physical interfaces. Here we spin
up servers that use one VLAN and one private IP sub-pool to actually handle the traffic.

Use `PUT` or `PATCH` method on the path `/interface/pppoe-server/server`. Consider to the following example JSON:
```json
{
    "interface": "easyfi-vlan-2001",  // ........... The VLAN interface you had created earlier.
    "profile": "easyfi-pppoe-prf-2001",  // ........ The PPPoE profile you created earlier.
    "service-name": "easyfi-pppoe-srv-2001",  // ... Use the VLAN id in the name.
    "comment": "{...}"  // ......................... The JSON string to indicate automated config.
}
```

**NOTE:** Looping needed.

**ROLL-BACK:** Save the original configuration as a JSON string in the `comment` field. If there was no original 
configuration, simply delete your record.

### 6. Set up AAA to use RADIUS

Now we need to tell the MikroTik device to use a RADIUS server for AAA.

Use `POST` method on the path `/ppp/aaa/set`. Use the following JSON as is:
```json
{
    "accounting": "true",
    "interim-update": "3m",
    "use-circuit-id-in-nas-port-id": "false",
    "use-radius": "true"
}
```

**ROLL-BACK:** Not known.

### 7. Set up the given RADIUS Server

We configure the MikroTik to use the given Radius Server for its AAA activities.

Use `PUT` or `PATCH` method on the path `/radius`. Consider to the following example JSON:
```json
{
    "name": "easyfi-radius",  // ............... Use this value.
    "address": "<radius_server_ip>",  // ....... The IP address of the RADIUS server.
    "secret": "<radius_server_secret>",  // .... The "password" of the RADIUS server. 
    "accounting-port": "1813",  // ............. Port of the RADIUS server.
    "authentication-port": "1812",  // ......... Port of the RADIUS server.
    "disabled": "false",  // ................... Use this value.
    "protocol": "udp",  // ..................... Use this value.
    "service": "ppp,login,hotspot,dhcp",  // ... Use this value.
    "timeout": "300ms",  // .................... Use this value.
    "comment": "{...}"  // ..................... The JSON string to indicate automated config.
}
```

**ROLL-BACK:** Enlist the RADIUS servers in the system and remove the one with your name (`easyfi-radius`) in it. You 
may also use some other identifier like the IP address of the RADIUS server or the contents of the `comment` field.

### 8. Allow Incoming Traffic from RADIUS Servers

In some cases the RADIUS server needs to be able to initiate the communication. We allow that in this step.

Use `POST` method on the path `/radius/incoming/set`. Consider to the following example JSON:
```json
{
    "accept": "yes", // ... Enable incoming RADIUS handling
    "port": "3799"  // .... Port of the MikroTik server for RADIUS authentication.
}
```

**ROLL-BACK:** Not known.

### 9. NAT Table Setup

We now add IP mapping rules to the NAT table. Any ISP is expected to have more private IPs than public IPs. The ISP will
assign private IPs to his clients such that multiple private IPs will use the same public IP to connect to the internet.
In this step we are effectively assigning one slice of the ISP's private IP to one of his public IPs. A known good 
sharing ratio is 16:1, but we split it equally.

In the following example, all the traffic from all the IPs in the `src-address` will be sent out to the open internet as
if it were being sent from the IP mentioned in the `to-addresses`.

Use `PUT` method on the path `/ip/firewall/nat`. Consider to the following example JSON:
```json
{
    "name": "easyfi-pppoe-nat-0000",  // ..... A name to later identify the rules created by the automated script.
    "action": "src-nat",  // ................. To indicate that we are translating a private IP to a public IP.
    "chain": "srcnat",  // ................... To indicate that we are translating a private IP to a public IP.
    "disabled": "false",  // ................. To enable the rule immediately.
    "src-address": "100.64.0.16/28",  // ..... One of your private IP subnets. 
    "to-addresses": "111.222.111.111",  // ... One of your public IPs.
    "comment": "{...}"  // ................... The JSON string to indicate automated config.
}
```

**ROLL-BACK:** Identify entries from their `name` field (contains 'easyfi') or from the contents of the `comment` field
and remove them.

### 10. Add the SNMP Community

This is needed by the Network Management System (NMS). I don't know much about it, but it is a very straight-forward 
step.

Use `PUT` or `PATCH` method on the path `/snmp/community`. Consider to the following example JSON:
```json
{
    "name": "easyfi-snmp",  // .............. A name to later identify the entry created by the automated script.
    "addresses": "::/0",  // ................ Use this value.
    "authentication-password": "",  // ...... Use this value.
    "authentication-protocol": "MD5",  // ... Use this value.
    "disabled": "false",  // ................ Use this value.
    "encryption-password": "",  // .......... Use this value.
    "encryption-protocol": "DES",  // ....... Use this value.
    "read-access": "true",  // .............. Use this value.
    "security": "none",  // ................. Use this value.
    "write-access": "false",  // ............ Use this value.
    "comment": "{...}"  // .................. The JSON string to indicate automated config.
}
```

**ROLL-BACK:** Identify your entry from the `name` field (contains 'easyfi') or from the contents of the `comment` field
and remove it.

---

*End of Document.*