Reset TCP/IP Stack without Rebooting?
This is a bit of an unusual question but I have a Mac server that gets hit with a lot of DDoS attacks. Usually my data center's mitigation system catches them but sometimes they slip through. When they do, they often can completely kill my system's TCP/IP. Even accessing localhost does not work. TCP/IP is completely dead. But the system is not frozen. It still runs perfectly fine otherwise. I know this because once I reboot the system, I can see all of the log entries from my scripts from the entire time it was offline. I have screen shots of the desktop from when it was offline.
Rebooting the server in this state returns it to normal. But I'm hoping there's some way I can restart just the TCPIP stack without rebooting the whole OS? That would at least let me regain access to the machine in a way that, while clumsy, would be significantly less so than hard remote reboots via IPMI.
This is all just a band-aide while we work out ways to shore up the DDoS mitigation. But it would be a good band-aide. Also useful, and along similar lines, would be a way to hard flush ALL TCP connections, established, half open, everything including all state information.
Solution 1:
I don't think there is a way to restart the TCP stack, but the question should be why TCP becomes unresponsive, it must be hitting some limits in the stack.
If the service creates new connections to answer incoming requests, it is possible you're hitting the default 16K limit on ephemeral ports and the even more problematic 30s (MSL*2) timeout on TIME_WAIT connections until they can be reused.
You can use sysctl
to tweak those:
sudo sysctl net.inet.tcp.msl=1000 # default 15000
sudo sysctl net.inet.ip.portrange.first=16384 # default 49152
The default TCP queues are also rather small (128 waiting sockets):
sudo sysctl kern.ipc.somaxconn=2048 # default 128
If you are also getting port scans or DoS to unused ports you can reduce backscatter by enabling blackhole mode and limiting ICMP/RST responses:
sudo sysctl net.inet.tcp.blackhole=2 # default 0
sudo sysctl net.inet.udp.blackhole=1 # default 0
sudo sysctl net.inet.icmp.icmplim=50 # default 250
Once you are happy with the sysctls you can persist them in /etc/sysctl.conf
.
Use something like sudo vim /etc/sysctl.conf
to create it.
I would also suggest to install HAProxy on your server in front of your services and use it to apply rate limiting and filtering for backend connections. You can even do packet inspection like dropping connections with invalid SNI headers. The easiest way to install haproxy on the Mac is through Homebrew.