Files

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.