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

IP-based bans #122

Closed
stapelberg opened this issue Jun 8, 2015 · 3 comments
Closed

IP-based bans #122

stapelberg opened this issue Jun 8, 2015 · 3 comments
Milestone

Comments

@stapelberg
Copy link
Contributor

This feature request is two-fold:

  1. We need a way to mark a bridge as trusted and respect the X-Forwarded-For header it sets.
  2. We need to implement IP-based bans (gline).

In the case where a bridge is non-trusted and serves multiple users, that means all users behind that bridge will be banned. While this is a bit unfortunate from a user experience view, it’s similar to what IRC in general has today (overly broad ban masks affect multiple users in the same network).

One caveat that comes to mind is that it is possible for people to change their IP address while keeping the same RobustSession running. We can either make bans apply only to the IP address with which a RobustSession was created, or to all addresses that are used. I’m inclined to try the former first.

@stapelberg
Copy link
Contributor Author

Making bridges trusted could possibly be done by using TLS client certificates.

@stapelberg
Copy link
Contributor Author

Here are the remains of an attempt at implementing this from a while ago:

--- a/robustirc.go
+++ b/robustirc.go
@@ -527,6 +527,12 @@ func main() {
    // Manually create the net.TCPListener so that joinMaster() does not run
    // into connection refused errors (the master will try to contact the
    // node before acknowledging the join).
+
+   // If a client (most likely a robustirc-bridge) provides a TLS client
+   // certificate, verify it and trust the X-Forwarded-For header it sends.
+   srv.TLSConfig.ClientAuth = VerifyClientCertIfGiven
+   // TODO: set up ClientCAs
+   // TODO: verify (http.Request).TLS.VerifiedChains to see if a client certificate was presented
    srv.TLSConfig.Certificates = make([]tls.Certificate, 1)
    srv.TLSConfig.Certificates[0], err = tls.LoadX509KeyPair(*tlsCertPath, *tlsKeyPath)
    if err != nil {

Maybe we can use cfssl for more convenient management of certificates? See e.g. https://github.com/kelseyhightower/kubernetes-the-hard-way/blob/master/docs/02-certificate-authority.md

@stapelberg
Copy link
Contributor Author

stapelberg commented Aug 21, 2016

We’d need to create a CA that can be used as the TLSConfig’s ClientCA: Certificates from LetsEncrypt or StartSSL cannot be used as CA (they have the CA flag set to false and don’t include “Certificate Sign” in their key usage field.

Given that we’d also need to implement CRL verification ourselves (as per http://stackoverflow.com/a/37072590/712014), I’m not sure anymore whether TLS client certification actually makes sense.

Rather, it seems to me that we’d get the same benefits (without the clumsy certificate handling) by using a list of passwords: on the network side, the config would be extended to contain a list of passwords, and the bridge would send the password along with all requests. If and only if a valid password is present, the X-Forwarded-For header is trusted.

Here’s the list of steps to implement the “trusted bridges” concept using passwords:

  • Add a new flag to the bridge to specify the filename of an auth password file (enforce minimum length and file permissions). Document that this file should be unique, provide a oneliner to create.
  • Have the bridge send the auth password along with each request.
  • Add trusted bridges to the network configuration
  • Expose the X-Forwarded-For header in the GetMessages status section

For smooth UI in bigger networks, the following would also be beneficial (but will not be implemented until it becomes necessary):

  • Have the RobustIRC server keep track of all bridges sending requests within the last 10m.
  • Expose the bridges in the HTTP status UI sessions section (display sessions as children of their bridges to increase confidence of authenticating the right one), provide an authenticate button, which will apply() a config update adding the password (with a name) to authenticate the bridge.

Once the above is done, we have accurate IP addresses for GetMessages requests, but not yet for PostMessage requests. Since GetMessages requests are local to an individual node, we cannot implement glines or bans until PostMessage requests carry the IP address.

stapelberg added a commit to robustirc/bridge that referenced this issue Dec 8, 2016
If specified, the file will be searched for a <network>:<secret-key>
line matching the network the bridge is about to connect to. If such an
entry is found, the X-Bridge-Auth header will contain the secret key.

You can create such a file using:

    touch /var/lib/bridge.auth
    chmod o-rwx /var/lib/bridge.auth
    echo "robustirc.net:$(openssl rand -base64 32)" >> /var/lib/bridge.auth

For more details, see robustirc/robustirc#122
stapelberg added a commit that referenced this issue Dec 11, 2016
For more details and corresponding changes in the bridge, please see
#122
@stapelberg stapelberg added this to the v0.6 milestone Jun 6, 2017
stapelberg added a commit that referenced this issue Jun 7, 2017
stapelberg added a commit that referenced this issue Jun 7, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant