Skip to content

nSolo

nSolo is the single-IP add-on. We allocate you one IPv4 address from 193.143.16.0/24 and 1:1-NAT it to your Torus tunnel. Available on Plus and Pro, $5/mo (included in Pro). It's the right pick when you want a stable, dedicated public IP — for a webserver, a game server, inbound SSH, a reverse-tunnelled service, anything where a port-forwarded ISP IP is too unstable or too shared.

If you need a whole prefix and want to put many things on the internet at once, you want nColo instead.

This page covers what nSolo is, how packets get from the public internet to a device on your home network through it, and — yes — the fact that there's NAT involved on both ends, including how to make that work when you want services to live on a LAN box rather than on the router itself.


Is it a double NAT? (Yes, honestly)

Worth being upfront about this. Nekotopia advertises nSolo as "1:1 NAT to your Torus IP" and that's accurate from your perspective — every packet to 193.143.16.X lands at your WireGuard IP 10.254.100.Y, with port numbers preserved. But under the hood there are actually three translation layers when traffic reaches a device behind your CPE:

                          translation #1                    translation #2
┌─────────────┐     ┌──────────────────────┐     ┌────────────────────────┐
│ Internet    │ →   │ AWS ENI              │ →   │ NAT-0 MikroTik         │ →
│ 193.143.16.X│     │ rewrites public IP   │     │ rewrites private IP    │
└─────────────┘     │ ↓ secondary private  │     │ ↓ your WG IP           │
                    │   IP on the ENI      │     │   10.254.100.Y         │
                    └──────────────────────┘     └────────────────────────┘

       ↓ WireGuard tunnel ↓

┌────────────────────────────┐         translation #3 (optional, your side)
│ Your CPE (e.g. MikroTik)   │ ──→     ┌────────────────────────────┐
│ receives on 10.254.100.Y   │         │ DSTNAT on your CPE         │
└────────────────────────────┘         │ rewrites to 192.168.x.y    │
                                       └────────────────────────────┘
                                       ┌──────────────────┐
                                       │ LAN device       │
                                       │ 192.168.x.y      │
                                       └──────────────────┘

Translations #1 and #2 are invisible to you — Nekotopia owns both ends and keeps them stateless 1:1. The IP arrives at your CPE intact, with the original source IP and port preserved. If you bind a service directly on the CPE (e.g. on its WG interface), there's no NAT visible on your side at all and it really does behave like a 1:1 NAT.

Translation #3 happens only if you choose to do it — when you want the service to live on a LAN device rather than on the router. That's where you'll be writing DSTNAT rules yourself. The next sections walk through both patterns.

If you need true routed (no-NAT) connectivity to a block of IPs, that's nColo, not nSolo. Different product.


What you get and don't get

You get

  • One public IPv4 address from 193.143.16.0/24, statically assigned
  • Inbound TCP and UDP on all ports, no port-forwarding table to manage on the hub side
  • A return path that preserves source IP — i.e. your service sees the real client IP, not a hub-side proxy IP
  • Outbound traffic that can be made to appear from your nSolo IP (with one extra rule, see below)

You don't get

  • A real /29, /30, /31, /32 block of routed addresses — that's nColo
  • BGP control over your IP — it's announced by us, not by you
  • IPv6 — the BYOIP block is v4-only currently
  • Multiple ports on different LAN devices "automatically" — you write the DSTNAT rules

The simple case: service on the router itself

If the service you want to expose runs on the MikroTik (the box terminating the WireGuard tunnel), there's nothing extra to do. The WG interface already has your 10.254.100.Y/32 address and traffic to the public IP arrives there directly.

This is the right pattern for:

  • A web admin UI on the router (e.g. RouterOS webfig — though don't expose that publicly!)
  • A reverse-tunnelled service running on the same box
  • An OpenVPN/L2TP/IPsec listener you want public

Bind your service to 10.254.100.Y or to all interfaces (0.0.0.0) — either works. Add a firewall input rule:

/ip firewall filter
add chain=input action=accept \
    in-interface=wg-routed \
    protocol=tcp dst-port=80 \
    comment="nSolo: accept HTTP to router"

(wg-routed is the typical interface name we hand out; adjust if you renamed yours.)


The common case: forwarding to a LAN device

This is the pattern most members want — public IP routes to a Raspberry Pi, vintage Mac, NAS, or some other LAN host. You use a DSTNAT rule on your CPE.

The auto-generated portion of your WireGuard config (look for SECTION 10 if you read the .rsc file we hand out) includes commented-out examples for this. Here's the same idea in clean form, forwarding inbound web traffic to a server at 192.168.1.100:

/ip firewall nat
add chain=dstnat action=dst-nat \
    in-interface=wg-routed \
    dst-address=10.254.100.Y \
    protocol=tcp dst-port=80 \
    to-addresses=192.168.1.100 to-ports=80 \
    comment="nSolo: forward HTTP to internal web server"

add chain=dstnat action=dst-nat \
    in-interface=wg-routed \
    dst-address=10.254.100.Y \
    protocol=tcp dst-port=443 \
    to-addresses=192.168.1.100 to-ports=443 \
    comment="nSolo: forward HTTPS to internal web server"

Replace 10.254.100.Y with your actual WG IP (you can find it in the Address= field of the WG config we generated) and 192.168.1.100 with your LAN server.

Then permit the forwarded traffic through the filter chain:

/ip firewall filter
add chain=forward action=accept \
    in-interface=wg-routed \
    dst-address=192.168.1.100 \
    connection-state=new \
    protocol=tcp dst-port=80,443 \
    comment="nSolo: allow HTTP/HTTPS forward to web server"

add chain=forward action=accept \
    connection-state=established,related \
    comment="Accept return traffic"

That's it. From the internet, curl http://193.143.16.X/ will land on your LAN host's port 80.

Common ports

Mostly it's pattern-substitution. A few sane defaults:

Service Protocol Port
HTTP tcp 80
HTTPS tcp 443
SSH tcp 22
Telnet (retro BBS, etc.) tcp 23
Minecraft Java tcp 25565
VNC tcp 5900–5901
WireGuard (server) udp 51820
Game traffic (varies) tcp/udp varies

Forcing outbound traffic to leave from your nSolo IP

By default, a LAN device making outbound connections to the internet uses your ISP's WAN IP — not your nSolo IP. NAT-state for inbound (replies to traffic that arrived on the nSolo IP) is handled by conntrack and works without extra config. But for originating connections to come from 193.143.16.X, you need three pieces:

  1. A routing mark on traffic from the LAN device (so MikroTik knows to send it via the WG tunnel rather than the WAN)
  2. A policy route that uses that mark to choose the WG interface as the next hop
  3. An SNAT rule that rewrites the source from the LAN device's IP to your WG IP — once that arrives at NAT-0 our hub rewrites it again to your nSolo IP

Worked example: force 192.168.1.100 to egress via nSolo for all outbound traffic.

# 1. Mark outbound packets from the LAN host
/ip firewall mangle
add chain=prerouting action=mark-routing \
    src-address=192.168.1.100 \
    new-routing-mark=via-nsolo \
    comment="Force 192.168.1.100 via nSolo"

# 2. Policy route — when the mark is set, gateway = WG IP of the hub
/ip route
add dst-address=0.0.0.0/0 \
    gateway=10.254.100.1 \
    routing-mark=via-nsolo \
    comment="nSolo egress"

# 3. SNAT outbound so the packet leaves with your WG IP as source
/ip firewall nat
add chain=srcnat action=src-nat \
    src-address=192.168.1.100 \
    out-interface=wg-routed \
    to-addresses=10.254.100.Y \
    comment="nSolo: SNAT outbound to WG IP"

After this, the LAN host's outbound traffic exits on 193.143.16.X and return traffic arrives via the same path automatically.

Only mark what you want to leave via nSolo

The mangle rule above applies to all traffic from 192.168.1.100, including its DNS, NTP, and OS updates. If the LAN device occasionally talks to services that geofence (and ours is labelled DE — see below), narrow the mark rule by dst-port or dst-address.


The MaxMind "DE" gotcha

MaxMind currently labels the entire 193.143.16.0/24 block as Germany in their GeoIP database, even though we announce it from London. Some services geofence on MaxMind data — most commonly streaming, banking, or services with deliberately narrow region locks. If a service you're trying to reach via nSolo blocks or behaves oddly, this is the usual cause.

It's not specific to your IP — every nSolo IP gets tagged the same way; reallocating won't help. The real fix is updating the MaxMind feed, which is on the backlog. Workaround: route the affected traffic through your WAN (don't mark it for nSolo egress) and keep nSolo for the inbound case where geo doesn't matter.


Firewall — what you must do before exposing anything

A public IP attracts opportunistic scanning within minutes. Don't expose anything you wouldn't put on your home WAN. Minimum baseline before you start forwarding to LAN:

/ip firewall filter

# Drop invalid early — saves CPU
add chain=forward action=drop \
    connection-state=invalid \
    comment="nSolo: drop invalid"

# Accept return traffic
add chain=forward action=accept \
    connection-state=established,related \
    comment="nSolo: accept return"

# Default-deny new inbound from the WG interface
# (Place this AFTER your specific accept rules)
add chain=forward action=drop \
    in-interface=wg-routed \
    connection-state=new \
    comment="nSolo: default-deny new inbound"

Then explicitly accept only the specific services you've decided to publish, by port + destination LAN IP. Order matters — the default-deny goes at the bottom of the chain.


Verifying nSolo is working

After allocation:

  1. Public DNS / ICMP reachability. From outside your network, ping 193.143.16.X should respond. If it doesn't, the allocation didn't land — message the admin.
  2. Inbound port to router. Bind a temporary listener on the MikroTik (e.g. RouterOS has a tool fetch server; or run nc -l 12345 on a host behind a temporary DSTNAT). Connect from the internet to 193.143.16.X:12345. You should land on the service.
  3. DSTNAT to LAN device. Set up one DSTNAT (HTTP is easiest) and confirm curl http://193.143.16.X/ reaches the LAN box. Check /ip firewall nat print stats — packet counters should increment on the rule.
  4. Outbound from LAN egressing via nSolo. If you set up the mangle + SNAT chain above, hit https://api.ipify.org from the LAN box. The returned IP should be 193.143.16.X, not your ISP's IP.

Troubleshooting

Symptom Likely cause
ping 193.143.16.X works but TCP services don't answer Firewall on your CPE blocking forward — check /ip firewall filter print, look for unexpected drops on wg-routed
Connections to your service show source IP = 10.254.100.1 (the hub WG IP) NAT-0 SNAT is misconfigured — should be passing client IP intact. Message the admin
Outbound from a LAN device still leaves via WAN even after the mark Mangle rule isn't matching — verify with /ip firewall mangle print stats. Common cause: src-address typo
Service appears reachable from inside the LAN but not from internet "Hairpin NAT" issue — your CPE is short-cutting LAN→LAN. Fine; test from a cellular hotspot to confirm true external reachability
Allocation succeeds but ping 193.143.16.X times out NAT-0 didn't install rules cleanly. Force-release from the dashboard and reallocate; if it still fails, admin needs to manually clean the NAT-0 NAT chain
Worked yesterday, broken today, no config change Check whether your WG tunnel is up. If your CPE rebooted and didn't re-establish a handshake, everything is offline until it does. /interface wireguard peers print stats

Pricing & lifecycle

  • $5/mo, billed alongside your Torus subscription. Included in Pro tier — no extra line item.
  • One nSolo per member. To swap to a different IP, release the current one and allocate a new one from the picker.
  • Release is instant. Once released, the IP goes back into the pool and may be re-allocated to another member within seconds. Don't release casually if you depend on stable DNS pointing at the IP.
  • Tier downgrade releases automatically. If you drop from Plus → Basic, your nSolo IP is released within the change-tier transaction.

  • Torus tiers — how nSolo fits across Plus and Pro
  • nColo — when you need a routed prefix instead of a single 1:1-NAT'd IP
  • nSolo Inbound — for forwarding individual ports without taking a full IP
  • Jumphost tunnel — for exposing a service when you don't have a stable IP at all

Admin-side ops view: see admin/nsolo.md for the pool layout, NAT-slot accounting, and recovery procedures when an allocation gets stuck.