Commit graph

3 commits

Author SHA1 Message Date
Kamron Batman
50c8287c7e
refactor(network): move Firewall to UOContent; core keeps only the filter seam
Core now owns the question -- "should this socket be denied?" -- and none of the
answers. The firewall was the last implementation left in core, and the reasons
to keep it did not survive scrutiny: it is not extended downstream, and a shard
running bare core has no way to populate it anyway, since the admin gump and
the commands that mutate it are both content. Larger shards front the server
with an upstream proxy or edge scrubbing and never use it; it survives as the
fallback an admin reaches for over a single player, which is squarely content's
concern.

Nothing about the firewall changes for operators: same Server.Network namespace,
same Configuration/firewall.json, same gump and commands, same legacy .cfg
migration. It reaches the accept path through ConnectionFilters like any other
filter, and registers itself first because an empty set is the cheapest gate.

Untangling core from the firewall entry types first:

- NetworkUtilities built its reserved-network tables out of CidrFirewallEntry,
  which made core depend on the firewall for something with nothing to do with
  banning. Those are constant CIDR blocks answering "is this address in one of
  these ranges?", so they are now a SortedRangeIndex<UInt128> -- the same
  primitive the firewall and blocklist already share. Same semantics, same
  public API, one linear scan replaced by a binary search.
- The CIDR -> normalized range parse those tables needed is now
  IPAddressUtility.TryParseCidrRange, and CidrFirewallEntry drops its private
  copy of that logic in favor of it.

Core no longer references IFirewallEntry or Firewall anywhere. 1344 tests pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-25 01:18:42 -07:00
Kamron Batman
e1e1a7c640
fix: Bumps deps. Updates copyrights (#2353) 2026-03-05 19:36:54 -08:00
Kamron Batman
4cd668ef61
feat: Moves TcpServer to another thread. Rewrites Firewall (#1660)
## Breaking Changes
* The Firewall and IP Limiter have been rewritten. Please read the notes carefully!
* `TcpServer.Instances` moved back to `NetState.Instances` - sorry - it was stupid to move it to begin with.

> [!Note]
> Sockets that fail the IP Limiter or Firewall will be immediately and forcibly disconnected.
> This means they will be stuck at "Verifying account..." if it was a real client.

### Summary
- Removes firewall wildcard support.
- Removes `AccessRestrictions`.
- Moves Firewall/IPLimiter to the core.
- Moves `TcpServer` to its own thread.
- Removes the `SocketConnect` and `SocketDisconnect` event sinks.
- Moves `Instances` back to `NetState.Instances`.
- Fixes a long standing bug with bad handling of duplicate listener addresses.

#### Firewall
The firewall has been completely rewritten. There is now an "Admin Firewall" which saves to the config file. Secondarily, there is an internal firewall used exclusively by the TcpServer while processing sockets. The Admin firewall mirrors it's additions/deletions to the internal firewall by adding requests to a queue.

> [!IMPORTANT]  
> **Wildcard firewall entries, such as `X`, `*`, `?` are not allowed.**
> **Ranges in between IP classes or sextets are not allowed.**
> **Please make sure to use one of the following:**
> * IP Address - `192.168.1.1`
> * CIDR - `192.168.1.0/24`
> * Range - `192.168.1.1-192.168.1.100`

#### IP Limiter
The IP Limiter has been completely rewritten. The available configurations are:
```json
"ipLimiter.enable": "True",
"ipLimiter.maxConnectionsPerIP": 10,
"ipLimiter.clearConnectionAttemptsDuration": "00:00:00:10",
"ipLimiter.clearThrottledDuration": "00:00:02:00",
```

The IP Limiter is set up to prevent spamming connections from the same IP. Every time an IP connects, it is added to a connection list. After 10 attempts, the IP is added to the throttle list. To keep the system fast, the connection list is entirely wiped every 10 seconds, and the throttle list is entirely wiped every 2 minutes.
2024-01-20 14:25:12 -08:00