When paramiko's defaults silently get your IP banned — the look_for_keys and allow_agent trap
One day a multi-site administrator reported a strange bug: "After running the app's SSH connection test 2-3 times, my IP can't reach SSH on that server for a long while ." The errors came back as Connection refused or Connection closed by ... . The server wasn't down, and SSH from a different IP worked fine. The source IP was being temporarily banned at the server. Two external investigation reports gave the cause: server-side protection mechanisms ( fail2ban or PerSourcePenalties in OpenSSH 25+) detect short-windowed authentication failure spikes and temporarily ban the source IP. But the user had only clicked the test button 2-3 times — why were failures "spiking"? The answer turned out to be paramiko's default behavior . paramiko's default — trying many keys per connection paramiko.SSHClient.connect() defaults two options to True : client . connect ( ' host ' , pkey = my_key , # The following are True by default: # look_for_keys=True, # also try ~/.ssh/id_* files # allow_agent=True, # also try ssh-agent registered keys ) When the explicitly passed pkey fails, paramiko falls back through ssh-agent registered keys → ~/.ssh/id_* files → password auth in order. Convenient for developers with a single key. Disastrous for a multi-site administrator: The SSH agent has multiple per-site keys registered ~/.ssh/ holds several id_rsa / id_ed25519 files A single connect call ends up trying 5-10 keys in sequence That blows past the server's MaxAuthTries (default 6) on a single connection So what looked to the user like "one connection test" was being seen by the server as " a suspicious IP racking up 5-10 auth failures in a row ." Repeat that 2-3 times and the protection mechanism declares the IP "exceeded threshold" and bans it. The fix — look_for_keys=False and allow_agent=False paramiko exposes options to scope key trial. We set them explicitly in connect_kwargs : connect_kwargs = { ' pkey ' : my_key , ' look_for_keys ' : False , # don't try ~/.ssh/id_* ' allow_agent ' : F