Try connecting to an SSH server for more than a few hours without passing traffic and then have the server be the one to send a message. Oops! Your ISP tore down the NAT association and you have no idea the server isn't sending anything until you try to communicate with the server and get a timeout / RST.
NAT breaks TCP, but at least with consumer NAT you're in control of the timeouts on your router. With CGNAT you're at the mercy of an ISP that likely optimizes for HTTP and has low timeouts that you can't control.
I actually used to have that issue years ago at work. To work around that I just enabled a keepalive (ServerAliveInterval maybe?) setting in my ssh config. I don’t connect to any ssh servers outside my house for long periods of time, so I haven’t encountered that. Thanks for the heads up, good info!
OpenSSH does enable TCP keepalives by default so that it can detect and close dead connections, but the keepalive interval is far too high to work around bad NATs.
Kind of related to the OP, I spent a decent amount of time trying to have my SSH sessions survive a sleep on Windows. With keepalive disabled, proper Wi-Fi adapter sleep behavior and long enough DHCP leases, I was able to put my PC to sleep and come back the next day and still have my sessions active on resume. Unfortunately it wasn't too practical to disable keepalive as sessions that really do crash never get cleaned up.
NAT breaks TCP, but at least with consumer NAT you're in control of the timeouts on your router. With CGNAT you're at the mercy of an ISP that likely optimizes for HTTP and has low timeouts that you can't control.