bluelinklabs / ctzn

[DEPRECATED] An open social network built on the Hypercore Protocol data mesh.
https://ctzn.network
MIT License
286 stars 25 forks source link

Use x-forwarded-for in ws client header for reverseDns in community remoteJoin #40

Closed saimonmoore closed 3 years ago

saimonmoore commented 3 years ago

Why?

For ctzn servers behind reverse proxies using the remote address from the ws client socket does not usually reflect the actual ip of the host but rather the loopback address (and so it's considered a private ip and disallowed).

Fix

For those ctzn servers behind a reverse proxy we can workaround this by:

  1. ensuring the reverse proxy is properly configured to send along the x-forwarded-for header
  2. saving the header in the ws request on the ws client
  3. using the header as the client remote address within the the reverseDns function.

Test

  1. Configure x-forwarded-for header on your reverse proxy (nginx example in PR) and restart
  2. Apply patch and restart server
  3. You can use https://ctznry.com/debugctzn@ctzn.politis.network to test this against as the ctzn.politis.network host has already been patched and is properly configured.

fun fact: "politis" means citizen in greek :) so ctzn.politis.network sounds very redundant but I like it.

Setting up local testing

This is the procedure I followed to allow testing remote joining to communities between two ctzn instances, in case it's useful for someone:

  1. Setup two custom hosts pointing to local ip 192.168.1.41:

~ /etc/hosts

192.168.1.41 ctzn1.test.network
192.168.1.41 ctzn2.test.network
  1. Setup two virtual servers in nginx pointing to these hosts and using ports 3000, 3001 respectively.

~ /etc/nginx/sites-enabled/default

server {
    listen 80 ;
    listen [::]:80 ;
    server_name ctzn1.test.network;

    location / {
      proxy_pass http://localhost:3000;
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "upgrade";
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

server {
    listen 80 ;
    listen [::]:80 ;
    server_name ctzn2.test.network;

    location / {
      proxy_pass http://localhost:3001;
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "upgrade";
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
  1. Temporary patch ctzn & ctznry to ignore ssl (https => http, wss => wss) Should maybe have used debug mode but seems coupled to loopback and wanted to avoid special behaviour associated with loopback)

  2. Setup TOS & privacy policy txt files (maybe some default ones could be setup)

  3. In two separate shells, start 2 instances of ctzn:

~ node bin.js --domain ctzn1.test.network --port 3000 --configDir ./tmp/config/ctzn1 start

~ node bin.js --domain ctzn2.test.network --port 3001 --configDir ./tmp/config/ctzn2 start

  1. Checkout ctznry, patch again for http/https ws/wss (again debug mode would be handy), yarn build and start it via node bin.js start
  2. In 2 separate browser sessions sign up as users, one in each server
  3. For each user create a community
  4. Attempt to join community created by other user.
  5. Go to http://localhost:4000/signup
pfrazee commented 3 years ago

Absolutely excellent PR, thank you @saimonmoore. Published 0.17.2, will deploy on ctzn.one now.