Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

*BSD blocklist support #198

Open
schmonz opened this issue Dec 9, 2020 · 4 comments
Open

*BSD blocklist support #198

schmonz opened this issue Dec 9, 2020 · 4 comments

Comments

@schmonz
Copy link
Member

schmonz commented Dec 9, 2020

NetBSD and FreeBSD have a blocklist daemon and associated library (formerly blacklist) that provide a sensible alternative to fail2ban. Given a network service that's been adapted to invoke the library on both successful and failed logins, the sysadmin can configure blocklistd policy to dynamically block source-IP/dest-port combinations at the OS firewall when enough failed logins have happened quickly enough, and then unblock when it's been long enough.

It's a very easy API to integrate iff you can pass it the listening network socket. This probably works under tcpserver and probably doesn't work under TLS-enabled analogues, especially if they support delayed encryption, because the file descriptors they provide are pipe ends.

Talked it through with the blocklist author. The API needs to be this way for security reasons. If we want to integrate blocklist support for e.g. authenticated mail submission, two options (both involving patching the various UCSPI server programs and trying to get the changes upstreamed) are:

  • Share the listening socket with the child program, as a predictably numbered fd or otherwise
  • Link with libblocklist themselves and provide some small API for the child program to invoke it
@schmonz
Copy link
Member Author

schmonz commented Dec 10, 2020

@skarnet offers a third option:

  1. Have an fd-holder daemon running (example: s6-fdholder-daemon)
  2. In your command chain, right after tcpserver and before the TLS part, store the socket in the fd-holder, with a short timeout and a long-and-random-enough identifier
  3. Pass that identifier in the environment
  4. In your command chain, after the TLS part and right before (or in) the program that calls blocklist(), use the identifier to retrieve the socket
  5. On AUTH success or failure, pass the socket to blocklist()

For opportunistic TLS, it could be a while before we can retrieve the right socket in the right state. Say we set a 30-second timeout on the fd-holder; if an initially unencrypted connection finally establishes TLS 31 seconds later, the fd-retriever program (example: s6-fdholder-retrieve) will fail and the connection will close. We can, of course, set a longer timeout on the socket-holder. (The longer the timeout, the easier it is to DoS the fd-holder by creating lots of connections.)

Alternatively, blocklist_sa() may not need the socket to be in any particular state. The manual page says "blocklist_sa() can be used with unconnected sockets, where getpeername(2) will not work". In which case the application can retrieve the socket immediately and have it available in case AUTH happens.

@skarnet
Copy link

skarnet commented Dec 10, 2020

Note that on opportunistic TLS, you already have the network socket (it's the plaintext one that you're not supposed to use anymore once you activate TLS, but you still have a fd to it), so you don't need that workaround.
The fd-holding dance is only necessary if you're going to tlsify the connection from the get go.

@schmonz
Copy link
Member Author

schmonz commented Jan 9, 2021

Remembered that a user has requested this.

@schmonz
Copy link
Member Author

schmonz commented Apr 12, 2021

I'd been thinking about this for the case of "too many" failed authentication attempts on a port 587 service, but after seeing a particularly intent dictionary-attack spammer I'm thinking sysadmins might also want this for the case of "too many" rejected recipients on a port 25 service.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants