signalapp / Flock

Private contact and calendar sync for Android.
https://signal.org/blog/flock
358 stars 80 forks source link

Nginx proxy seems to break Flock #91

Closed effigies closed 9 years ago

effigies commented 9 years ago

Running calendarserver (3.2+dfsg-4+deb7u1) on Debian (wheezy), I was able to run through the tests across the local network over HTTP.

Rather than manage SSL directly in calendarserver, I added an Nginx proxy like so:

upstream calendar {
    server 127.0.0.1:8008;
}

server {
    listen 443 ssl;
    ssl on;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers "EECDH:EDH:!MEDIUM:!LOW:!EXP:!DSS:!aNULL:!eNULL:!RC4:!3DES:!SEED:!MD5";
    ssl_certificate /etc/ssl/certs/public.pem;
    ssl_certificate_key /etc/ssl/private/private.key;

    server_name myserver.name;
    root /var/www;

    location / {
        proxy_set_header   X-Real-IP        $remote_addr;
        proxy_buffering off;
        proxy_pass http://calendar/;
    }
}

Flock now fails with "Connection error, please check internet connection."

My initial thought was perhaps the DNS hasn't propagated. (I created a new record for this server.) Adding a hosts file entry does not resolve the issue.

I also considered that perhaps SNI is unsupported or the SSL parameters were invalid. Flock happily connected to another, similarly configured server with Nginx ngx_http_dav_module entry (though of course failed it on CardDAV/CalDAV).

All that remains seems to be the proxying, but it's entirely unclear what parameters should be changed. The same server can be used with Thunderbird/Lightning, so the proxy at least works to the satisfaction of some clients.

jahil commented 9 years ago

How you pass Import Data tests? what url you used and how you add username with '@' with username field.

effigies commented 9 years ago

I don't know. If there's a way to put Flock in debug mode and get the specific commands it tries, I could probably go further in figuring out what's wrong. But this is just the initial behavior of the app, where it tests a server for compatibility.

effigies commented 9 years ago

Just pinging to see if there's anything I can do to give more useful diagnostic info.

effigies commented 9 years ago

Tracked down the issue, finally.

What was happening is that, even though the initial connection succeeded over HTTPS, /.well-known/carddav and /.well-known/caldav redirect to / over HTTP port 8008. Flock was hanging and getting some pretty strange behavior as a result, presumably because that port was filtered and not closed.

My fix ended up being editing the CalendarServer code to redirect these to HTTPS port 443 (calendarserver/tap/util.py):

if config.EnableWellKnown:
    log.info("Setting up .well-known collection resource")

    wellKnownResource = SimpleResource(
        principalCollections=(principalCollection,),
        isdir=True,
        defaultACL=SimpleResource.allReadACL
    )
    root.putChild(".well-known", wellKnownResource)
    for enabled, wellknown_name, redirected_to in (
        (config.EnableCalDAV, "caldav", "/",),
        (config.EnableCardDAV, "carddav", "/",),
        (config.TimezoneService.Enabled, "timezone", "/stdtimezones",),
    ):
        if enabled:
+           scheme = 'https'
+           port = '443'
-            if config.EnableSSL:
-                scheme = "https"
-                port = config.SSLPort
-            else:
-                scheme = "http"
-                port = config.HTTPPort
            wellKnownResource.putChild(
                wellknown_name,
                RedirectResource(scheme=scheme, port=port, path=redirected_to)
            )

This obviously isn't great, but it's not clear how to convince CalendarServer to respect the parameters of the proxy that it shouldn't need to know anything about.

Anyway, putting this up so the solution's searchable.