Hello !

When someone connects to my instances communities, but from another instance, how do I know it’s no spoofing involved?

Cheers

  • Loulou@lemmy.mindoki.comOP
    link
    fedilink
    arrow-up
    2
    ·
    edit-2
    1 year ago

    Okay so it’s the lemmt server running my instance that checks it is the right user. Do you know how it is done ?

    I reread your post, so it’s a signature in the http call?

    • mo_ztt ✅@lemmy.world
      link
      fedilink
      English
      arrow-up
      3
      ·
      1 year ago

      Here’s quite a good overview. The short answer, I think, is that the signature is embedded into the JSON object representing the post / upvote / whatever, which then gets passed around server-to-server (and each server checks the signature against the original server’s TLS certificate). It’s not something you can get your head around just by asking a couple simple questions but it’s a pretty fascinating design when you get your head around it.

      • Loulou@lemmy.mindoki.comOP
        link
        fedilink
        arrow-up
        1
        ·
        1 year ago

        Ha ha yeah it’s not easy peasy when you start with these kind of things for sure, thanks for the link! It seems it shows the day to say stuff (and the pubkey embedded in the json) thanks again.

        So if I want to validate a user outside of the Lemmy service (the one that runs in a docker on my lemmy-box), I “just” have to get the public key from the Lemmy database and validate the digest/signature?

        Cheers!

        • mo_ztt ✅@lemmy.world
          link
          fedilink
          English
          arrow-up
          1
          ·
          1 year ago

          You shouldn’t have to… as I understand it, if it’s showing up on your server, that means your server authenticated it. Given the general flakiness of all this software and Lemmy in particular, I wouldn’t put too much reliability on that, but that’s the theory.

          If you do want to double-check it yourself, I know partially how to do it. You don’t have to get the key from the database; it’s probably simpler and safer to get it from your user’s JSON. Here’s a super-basic script to dump a fediverse endpoint’s contents:

          import requests
          import json
          import sys
          
          def fetch_and_pretty_print(url, headers=None):
              # If headers are not provided, set default to fetch ActivityPub content
              if headers is None:
                  headers = {
                      'Accept': 'application/activity+json',
                      'User-Agent': 'Fediverse dump tool via @[email protected]'
                  }
              
              try:
                  response = requests.get(url, headers=headers)
                  response.raise_for_status()  # Raise an exception for HTTP errors
          
                  # Try to parse JSON and pretty print it
                  parsed_json = response.json()
                  print(json.dumps(parsed_json, indent=4, sort_keys=True))
                  
              except requests.RequestException as e:
                  print(f"Error fetching the URL: {e}")
              except json.JSONDecodeError:
                  print("Error decoding JSON.")
          
          if __name__ == '__main__':
              fetch_and_pretty_print(sys.argv[1])
          

          If I want to validate your comment, I would start by getting your public key via your user’s endpoint on your home server. I could save that script up above as fetch, then run python fetch https://lemmy.mindoki.com/u/Loulou, and in among with a bunch of other stuff I would see:

              "publicKey": {
                  "id": "https://lemmy.mindoki.com/u/Loulou#main-key",
                  "owner": "https://lemmy.mindoki.com/u/Loulou",
                  "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArRwWZneP9efCrsymHDE2\nsJAHojjxE4A2Q3Hquwt7s/HPTAi3gKP7NKCRSH7XVPtGhieJdtDeoLMkitvZXCUX\nS1pZArTYihuLeOwbB+JrAHZpWr1sYpazspUPvl3MhDAOOCCAnSeqsMNPNd8QX1Tf\nN/3Bp4PRVmp9E968L61h93L5N3B7VxZ37kbzKFXrhmU6qFQbAoVQvHtojCD6WqR2\nMb84eJy5QBN+0SjvGR8LRE0iJZiwYvVXKNoEyOqr4Fw8YnELi3TYbfxX++0uXw97\ne+/rFgaa/QVCSopUbHkuX/ZfjzCdBAI+aqXsbmYLgdxdRDHur0k53aCh3u0t/IDL\nHQIDAQAB\n-----END PUBLIC KEY-----\n"
              },
          

          I don’t know off the top of my head how you could navigate your way to the fediverse JSON for your comment, or how to verify its signature once you find it (I tried to get the post by dumping your user’s outbox and the lemmy_support community’s outbox, but neither of those worked the way I expected it to), but that all might be a helpful starting point. I know that according to the docs, anything that was created by your user and then federated is supposed to be signed with that key so that other servers can authenticate it.

    • Wander@yiffit.net
      link
      fedilink
      arrow-up
      3
      ·
      1 year ago

      It should be a signature that is sent together with the ActivityPub Object. Yes, if the signature doesn’t match, the content, whether a post, comment, favorite, upvote, etc… should be dropped.

      Here is the source code of the library that lemmy uses to handle incoming objects and you can see that it does a call to verify the signature of the actor:

      https://docs.rs/activitypub_federation/latest/src/activitypub_federation/actix_web/inbox.rs.html#18-54