147 lines
6.7 KiB
Markdown
147 lines
6.7 KiB
Markdown
# MikroTik Router Security Hardening
|
|
|
|
A repeatable security audit and hardening procedure for RouterOS 7.x routers. Run when onboarding a new router or performing a periodic security review.
|
|
|
|
## Audit checklist
|
|
|
|
### 1. IP Services — Restrict listening addresses
|
|
|
|
Check current state: `/ip/service/print`
|
|
|
|
Default state exposes SSH (22), API (8728), Winbox (8291), and API-SSL (8729) to `0.0.0.0/0` (any IP). Tighten each:
|
|
|
|
```
|
|
/ip/service/set ssh address=10.1.0.0/24,10.1.1.0/24,192.168.88.0/24,10.77.0.0/24
|
|
/ip/service/set api address=10.1.0.0/24,10.1.1.0/24
|
|
/ip/service/set winbox address=<subnets-needed> # Keep open if user needs Winbox from anywhere
|
|
/ip/service/disable api-ssl
|
|
```
|
|
|
|
**CRITICAL: Include 10.77.0.0/24 in SSH's allowed-address list when WireGuard tunnel is used for remote management.** If you forget, you will lock yourself out and need WinBox access to recover.
|
|
|
|
**RECOVERY from lockout:** SSH to the router fails with "Connection closed by remote host". The fix via WinBox terminal: `/ip/service/set ssh address=10.77.0.0/24`. Always include this in the set command the first time.
|
|
|
|
### 2. Firewall — Remove duplicate rules
|
|
|
|
RouterOS config accumulates duplicate rules over time (especially WG tunnel rules). Audit:
|
|
|
|
```
|
|
/ip/firewall/filter/print detail
|
|
```
|
|
|
|
Look for:
|
|
- Multiple rules with identical comments and action
|
|
- Rules that are redundant (e.g., same port/protocol accepted more than once)
|
|
- Orphaned rules with no action (missing `action=accept/drop`)
|
|
|
|
Remove duplicates by matching the comment text and removing all but one:
|
|
|
|
```
|
|
/ip/firewall/filter/remove [find where comment="allow WG tunnel (ITPP)"]
|
|
/ip/firewall/filter/remove [find where comment="allow ITPP tunnel"]
|
|
```
|
|
|
|
Then re-count: `/ip/firewall/filter/print count`. A clean home router has ~26 rules.
|
|
|
|
### 3. L2TP/IPsec — Disable weak authentication methods
|
|
|
|
Check current: `/interface/l2tp-server/server/print`
|
|
|
|
Default enables PAP, CHAP, MSCHAP1, MSCHAP2. PAP sends passwords in cleartext. MSCHAP1 is weak. Keep only CHAP + MSCHAP2:
|
|
|
|
```
|
|
/interface/l2tp-server/server/set authentication=chap,mschap2
|
|
```
|
|
|
|
### 4. Remove obsolete PPP secrets
|
|
|
|
When WireGuard replaces L2TP for remote management, the `shonuff` user's PPP secret is obsolete. Remove it:
|
|
|
|
```
|
|
/ppp/secret/remove [find where name=shonuff]
|
|
```
|
|
|
|
Leave `gadmin` (the user's primary VPN account) intact.
|
|
|
|
### 5. Stale user accounts
|
|
|
|
Check: `/user/print`
|
|
|
|
Remove any users that haven't logged in recently or belong to decommissioned services (e.g., a Remote Winbox SSTP user from a defunct third-party service):
|
|
|
|
```
|
|
/user/remove [find where name=<stale-username>]
|
|
```
|
|
|
|
Also check for orphaned SSTP/L2TP client interfaces: `/interface/sstp-client/print` — disable or remove interfaces pointing to dead services.
|
|
|
|
### 7. SMTP Configuration for Scheduled Emails
|
|
|
|
If the router sends scheduled email backups (logs, config, backup files), these settings are specific to this netcup KVM infrastructure:
|
|
|
|
- **Port: 2525** (NOT 465). Port 465 times out from netcup infrastructure. Only 2525 works.
|
|
- **TLS: starttls** (NOT yes). Port 465 uses SSL/TLS; port 2525 uses STARTTLS.
|
|
- **DNS servers:** Must be set explicitly. AT&T DHCP leases don't resolve `mail.germainebrown.com`. Set to internal AdGuard:
|
|
```
|
|
/ip/dns/set servers=10.1.1.14,10.1.1.10
|
|
```
|
|
|
|
Apply settings:
|
|
```
|
|
/tool/e-mail/set port=2525 tls=starttls password="<current-password>"
|
|
```
|
|
|
|
**Diagnostic chain for SMTP failures:**
|
|
1. `DNS resolve failed` → check `/ip/dns/set servers=` — AT&T gateway can't resolve MXroute
|
|
2. `timeout occured` → missing established/related input rule (see §8). Also check if the port in use is actually open from the server's IP — try `nc -zv mail.germainebrown.com 2525` from the management box.
|
|
3. `AUTH failed` → check password in `/tool/e-mail/print` against current mail provider creds. The mail password may have been changed since the router was configured.
|
|
4. `succeeded` → test with `/tool/e-mail/send to="test@domain" subject="test" body="test"`
|
|
|
|
Check status: `/tool/e-mail/print` — look for `last-status: succeeded`.
|
|
|
|
**Known quirk:** When changing SMTP settings or password on RouterOS, the previous error entries in the log buffer (`e-mail,error`) persist — the new test may have succeeded even though old errors are still visible. Always check `last-status` on `/tool/e-mail/print` rather than scroll-back logs.
|
|
|
|
Also fix the scheduler scripts: the filenames created by `/log print file=<name>` and `/export file=<name>` auto-append extensions (.txt / .rsc). Ensure the email `file=` parameter matches what's actually created:
|
|
|
|
| Scheduler creates | Email attaches | Match? |
|
|
|---|---|---|
|
|
| `logs.txt` | `home-rtr-logs.txt` | ❌ Fix: use same filename on both sides |
|
|
| `export.rsc` | `home-rtr-config.rsc` | ❌ Fix: use same filename on both sides |
|
|
|
|
### 8. Firewall INPUT chain — Add established/related rule
|
|
|
|
RouterOS forwards typically have `connection-state=established,related` but the INPUT chain may lack it. Without this rule, outgoing connections initiated by the router itself (SMTP, DNS) have their return traffic blocked by WAN-DROP.
|
|
|
|
**Symptom:** SMTP shows `timeout occurred` or DNS shows `DNS resolve failed` even though DNS servers are correct and ports are open.
|
|
|
|
Add at position 1 (before WAN-DROP):
|
|
```
|
|
/ip/firewall/filter/add chain=input action=accept connection-state=established,related place-before=1 comment="Allow established/related input"
|
|
```
|
|
|
|
Verify with: `/ip/firewall/filter/print count where chain=input`
|
|
|
|
## L2TP server IPSec secret
|
|
|
|
The L2TP server's IPsec PSK (`ipsec-secret`) is in cleartext in the config. Ensure it:
|
|
- Is a strong random string (12+ characters)
|
|
- Is stored in the password manager / recovery bundle
|
|
- Is NOT shared across routers (unique per router)
|
|
|
|
## Common failure: WireGuard public key mismatch
|
|
|
|
This is the most common cause of "tunnel configured correctly but 0 B received". The router's config export (`/export show-sensitive`) includes the WireGuard private key, but RouterOS may have **regenerated** it since that export was saved. The public key in the export is now stale.
|
|
|
|
**Diagnosis:** Server `wg show` shows TX counts increasing but RX stays at 0, even though the router pingable on WAN IP and UDP port is accessible.
|
|
|
|
**Fix:** Read the router's ACTUAL public key directly:
|
|
```
|
|
/interface/wireguard/print detail where name=wg-itpp
|
|
```
|
|
Compare `public-key=` from that output with the server's `wg show` peer public key. If mismatched:
|
|
1. Update the server's `/etc/wireguard/wg0.conf` [Peer] section with the correct public key
|
|
2. Restart `wg-quick@wg0`
|
|
3. Verify handshake appears within seconds
|
|
|
|
**Prevention:** Never trust `public-key=` from a config export file. Always verify against the live router's interface. The export captures the key at export time; it can go stale if the router regenerates its WG keys during a config reset or manual rekey.
|