anhedonic

dynamic soap bubbles

Mar 01, 2024

finger webfinger

Berend De Schouwer

Finger and Webfinger

Finger and Webfinger answer the same question: “what information is available about this user?”

This blog was written because both were harder to get going than necessary.

Webfinger

Webfinger does something similar. Query my mastodon handle, @berend@emptybox.deschouwer.co.za, and you should get something like

{
    "aliases": [
        "https://emptybox.deschouwer.co.za/nextcloud/index.php/index.php/apps/social/@berend",
        "https://emptybox.deschouwer.co.za/nextcloud/index.php/u/berend"
    ],
    "links": [
        {
            "href": "https://emptybox.deschouwer.co.za/nextcloud/index.php/u/berend",
            "rel": "http://webfinger.net/rel/profile-page",
            "type": "text/html"
        }
    ],
    "subject": "berend@emptybox.deschouwer.co.za"
}

It’s a good API to find more information about a specific user.

Finger

Finger is old. It’s from 1991, 5 years before http.

You can see it in action by running

finger berend@berend.deschouwer.co.za

The original finger server was horribly insecure. This server is not running that.

Webfinger Back

The Webfinger backend is provided by the Social app on Nextcloud.

I’m going to document some of the pitfalls here, since:

  • An installation step isn’t documented
  • Some of the error reporting is misleading.
  • All of the official help is “configure your webserver/proxy”, even when the answer isn’t that.
  • google-ing this doesn’t help, since everything redirects you back to webserver configuration help.

Configure your webserver

Once, for Nextcloud

Yes, you do need to configure your webserver.

Under your nextcloud instance, when logged in as admin, navigate to security.

If Nextcloud Admin Security Check complains with a similar message

Your web server is not configured correctly to resolve “/.well-known/caldav”. More information can be found on our documentation. Your web server is not configured correctly to resolve “/.well-known/carddav”. More information can be found on our documentation.

You need to fix your webserver or proxy. Follow Google. The solutions are complete.

Configuring Nextcloud

Twice, for the Social App in Nextcloud

Nope, you don’t need to do it twice.

If the Social App complains with a similar message

.well-known/webfinger isn’t properly set up!

Social needs the .well-known automatic discovery to be properly set up. If Nextcloud is not installed in the root of the domain, it is often the case that Nextcloud can’t configure this automatically

The problem is not your webserver. It’s the Social App

Configuring the App (the missing installation step)

You will need the CLI occ from Nextcloud.

You may have used it to perform backups or upgrades. It’s in the webroot, and you will usually run it something like:

sudo -u www /var/www/nextcloud/occ backup

First, look at the config. Run:

cd /var/www/nextcloud/
sudo -u www occ config:list

Look for the Social app.

"social": {
     "address": "https:\/\/emptybox.deschouwer.co.za\/",
     "enabled": "yes",
     "url": "https:\/\/emptybox.deschouwer.co.za\/nextcloud\/index.php\/apps\/social\/",
     "social_url": "https:\/\/emptybox.deschouwer.co.za\/nextcloud\/index.php\/index.php\/apps\/social\/",
     "cloud_url": "https:\/\/emptybox.deschouwer.co.za\/nextcloud\/"
},

Ensure that these values are OK. If they are not, run

sudo -u www php ./occ config:app:set --value https://emptybox.deschouwer.co.za/overthere social url

Three, misleading errors

Webfinger not supported

Now you get to try:

http --follow 'https://emptybox.deschouwer.co.za/.well-known/webfinger?resource=acct%3Aberend'

If you get 404 and

{
    "message": "webfinger not supported"
}

Don’t panic! It doesn’t mean webfinger isn’t supported, it means the account specified isn’t a valid account.

You didn’t specify a domain. Add a domain.

Webfinger is empty and 404

http --follow 'https://emptybox.deschouwer.co.za/.well-known/webfinger?resource=acct%3Aberend%40example.com'

If you get 404 and

""

Dont panic! It means that the specified acocunt (berend@example.com) is not on this server.

Your Nextcloud instance isn’t example.com, so you should specify an account you are authoritive for.

Finger Back

The backend for 1991 finger is a simple script that serves my whoami page.

Since the actual finger servers are insecure, I decided to re-implement it again. Since that means even more insecure, I simplified everything.

systemd to the rescue

This is the reason for writing this section. systemd can really help us locking it down.

[Unit]
Description=Finger Per-Connection Server

[Service]
ExecStart=/usr/.../.py # Keep some things secret
StandardInput=socket
# Send errors to the logs, instead of to the caller
StandardError=journal
SyslogIdentifier=finger
# Don't run as root
DynamicUser=yes
# Don't read /tmp, /dev, /home
PrivateTmp=true
PrivateDevices=true
ProtectHome=true
# Restrict for DoS
MemoryMax=100M
Nice=19
IOSchedulingClass=best-effort
IOSchedulingPriority=7
CPUQuota=50%
IOWeight=25
# Restrict OS calls
SystemCallFilter=@system-service
SystemCallErrorNumber=EPERM
ProtectSystem=strict
RestrictSUIDSGID=true
MemoryDenyWriteExecute=true
# Don't load calls that are frequently used by exploits
InaccessiblePaths=/usr/bin/at
InaccessiblePaths=/usr/bin/bash
InaccessiblePaths=/usr/bin/sh
InaccessiblePaths=/usr/bin/wget
InaccessiblePaths=/usr/bin/curl
InaccessiblePaths=/usr/bin/ssh
InaccessiblePaths=/usr/bin/scp
InaccessiblePaths=/usr/bin/perl

User

The first level of security, is do not run as root.

No public directories

No public /tmp or any such directory. If you do hack it, your in a sandbox.

Limited Access

Then we lock it down a bit for DoS reasons. We run it low priority, with limited RAM, so you don’t take down the entire machine.

Too many details

Then we lock up some other processes. Some of these are for example purposes.

It’s really, really nice that systemd allows us to lock it down like this.

Multiple users? Nope

The original finger backend allows you to query any user that exists, and changes the output based on whether they are logged in.

Not for me. I give you the same answer, no matter what.

Redirects? Nope

You could query users on another server. Connecting to example.com, you could ask it about joe@smith.com. Not on my server.

Memory Leaks? Nope

You could send very large user names. On my server, you get 512 bytes, then I disconnect.

Since we don’t care about the data, we discard it.

discard = os.read(0, 512)

DoS? Nope

You can’t keep the finger socket open for very long. If it doesn’t receive data very soon, it will disconnect.

def timeout(signum, frame):
    raise Exception("Timed out")

signal.signal(signal.SIGALRM, timeout)
signal.alarm(3)

DDoS? Yep

DDoS is always a “yep”.

More details

I’d give you more details, but here aren’t. We timeout after 3 seconds, we read a maximum of 512 bytes of data, and we always give the exact same response.