228 Followers
0 Following
6 Posts

Lately, not an hour goes by without someone asking me about what infosec.exchange is “doing about Threads”. There’s a lot of mis- and dis-information running around the fediverse as of late about Threads beginning to federate, along with some legitimate concerns. This post is not about my personal views, but rather my plans for Threads and some instructions.

At the moment, Threads.net is silenced (aka limited) on infosec.exchange. That means that infosec.exchange accounts won’t see threads.net posts or accounts, and threads.net accounts can’t follow infosec.exchange accounts without approval of the person being followed. This gives people the ability to search for a threads.net account and bypass the warning to follow them. From there, it is like interacting with any other fediverse account. That works fine for now as there are not many threads.net accounts exposed to the fediverse, but it doesn’t scale very well for people who want to interact with threads.net accounts in the future.

The big picture plan for threads.net on infosec.exchange is this:

  • Silence threads.net – done
  • Enable the authorized_fetch feature on infosec.exchange to prevent the normal flow of posts from accounts blocking threads.net to Threads’ users and systems – done (note: this in no way prevents people, including Threads, from accessing your public posts. Public posts are public and can be accessed via the web site directly, RSS, and and so on.)
  • Encourage people who do not want to interact with threads.net or have their posts visible to Threads’ users to block the domain threads.net. – This post is kicking off that campaign. See below for instructions.
  • Create a new instance (name will either be infosec.space or infosec.cafe, still deciding) that will fully block threads.net. This should be completed by Jan 1, 2024
  • Encourage infosec.exchange members who are not comfortable with other infosec.exchange users interacting with threads.net to migrate to the new instance or to some other instance that fully blocks theads.net. This campaign will start once the new instance is available.
  • Remove the threads.net silence/limit on infosec.exchange. This will happen 60 days after step 5.
  • Q&A

    Q: I think you are a terrible person not blocking threads.

    A: I am sorry it didn’t work out between us. I am but an imperfect human trying my best to navigate a complicated world. There are other instances that may be more to your liking.

    Q: Will the new instance block instances that don’t block threads.net?

    A: I do not currently see value in this beyond being punitive to other instances, so no, there are no current plans to do that.

    Q: I’ve been told that instances will collapse once threads starts federating. Aren’t you worried about that?

    A: I worry about many things. This isn’t one of them. For sound technical reasons.

    Q: What if no one wants to use your new instance or what if everyone leaves infosec.exchange due to your poor decision making?

    A: I save a lot of time and money.

    Q: What happens when $terribleaccount on threads.net starts harassing people?

    A: I will block the account, just like I do today.

    Q: Aren’t you worried about the moderation of threads.net?

    A: Not really. I get to deal with problematic instances and problematic people all day, every day. If it gets to be too much, I’ll reassess.

    Q: How do I block threads.net on my account?

    A: This is how:

    These instructions are how to block threads.net via a web browser. Some mobile apps also expose this feature and some don’t, and I don’t really have the ability to create instructions for the 20+ different mobile apps.

    Step 1 – search for threads.net

    Step 2 – Select a threads.net account:

    Step 3 – Click on the menu next to the account name in the profile view:

    Step 4 – block the domain

    That’s it.

    https://blog.infosec.exchange/2023/12/27/threads-and-infosec-exchange/

    Threads and Infosec.Exchange

    Lately, not an hour goes by without someone asking me about what infosec.exchange is “doing about Threads”. There’s a lot of mis- and dis-information running around the fediverse …

    Infosec Exchange Blog

    It’s been nearly 2 months since E-Day, when the mass migration of people from Twitter to the fediverse started in earnest. At the time, infosec.exchange was humming along well on an AX101 (AMD 5950, 128GB RAM, 4TB NVME ssd) server from Hetzner in Germany.

    I spent a lot of time tuning, tweaking, and making mistakes. I am going to spare you the details of the many of the experiments that led to this. The instance currently has close to 43000 accounts and about 6000 peak active connections during the day, with about 20000 accounts active within the past week. Make no mistake: this is crazy overkill. I set this up at a time that infosec.exchange was adding 1500-3000 new accounts per day, and had no idea when it would stop. So, consolidation and simplification lay ahead, if things slow down.

    This diagram is roughly what infosec.exchange looks like today.

    All these systems are Ubuntu 22.04 LTS. For those that are not redundant, I have purchased a subscription to Ubuntu’s pro service that enables live patching.

    I’ll go from top to bottom with the customizations I’ve made and a bit of the why.

    Load balancer

    The load balancer is nginx. The first modification I needed to make was to increase the open files available to nginx. After I got above a thousand or so concurrent connections, I nginx started running out of open files. Do not waste your time editing /etc/security/limits.conf or sysctl.conf. They don’t actually fix the problem. The fix is adding this line to the /etc/systemd/system/multi-user.target.wants/nginx.service file, under the [Service] section:

    LimitNOFILE=1000000

    Note: there is no science behind 1000000. I grew tired of running out of open files and so picked a big number. One million seemed nice and round.

    Next, we have to increase the number of connections that nginx can handle. We do this in /etc/nginx/nginx.conf. This is what works well for me:

    user www-data;worker_processes 24;pid /run/nginx.pid;include /etc/nginx/modules-enabled/*.conf;events { worker_connections 16384; multi_accept on; use epoll; epoll_events 512;}

    http {

    …..

    Next, is the nginx site file (/etc/nginx/sites-enabled/mastodon in my case):

    map $http_upgrade $connection_upgrade {default upgrade;” close;}

    upstream backend {ip_hash;server 192.168.100.1:3000;server 192.168.100.2:3000;

    }

    upstream streaming {ip_hash;server 192.168.100.20:4000;server 192.168.100.21:4000;server 192.168.100.22:4000;}

    proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=CACHE:10m inactive=7d max_size=1g;

    server {if ($host = infosec.exchange) {return 301 https://$host$request_uri;} # managed by Certbot

    listen 80;listen [::]:80;server_name infosec.exchange;root /home/mastodon/live/public;location /.well-known/acme-challenge/ { allow all; }location / { return 301 https://$host$request_uri; }

    }server {listen localhost:81;location /metrics {stub_status on;}}

    server {listen 443 ssl http2;listen [::]:443 ssl http2;server_name infosec.exchange;

    ssl_protocols TLSv1.2 TLSv1.3;ssl_ciphers HIGH:!MEDIUM:!LOW:!aNULL:!NULL:!SHA;ssl_prefer_server_ciphers on;ssl_session_cache shared:SSL:10m;ssl_session_tickets off;

    # Uncomment these lines once you acquire a certificate:ssl_certificate /etc/letsencrypt/live/infosec.exchange/fullchain.pem; # managed by Certbotssl_certificate_key /etc/letsencrypt/live/infosec.exchange/privkey.pem; # managed by Certbot

    keepalive_timeout 70;sendfile on;client_max_body_size 80m;

    root /home/mastodon/live/public;

    gzip on;gzip_disable “msie6”;gzip_vary on;gzip_proxied any;gzip_comp_level 6;gzip_buffers 16 8k;gzip_http_version 1.1;gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml image/x-icon;

    location / {try_files $uri @proxy;}

    # If Docker is used for deployment and Rails serves static files,# then needed must replace line try_files $uri =404; with try_files $uri @proxy;.location = /sw.js {add_header Cache-Control “public, max-age=604800, must-revalidate”;add_header Strict-Transport-Security “max-age=63072000; includeSubDomains”;# try_files $uri =404;try_files $uri @proxy;}

    location ~ ^/assets/ {add_header Cache-Control “public, max-age=2419200, must-revalidate”;add_header Strict-Transport-Security “max-age=63072000; includeSubDomains”;#try_files $uri =404;try_files $uri @proxy;}

    location ~ ^/avatars/ {add_header Cache-Control “public, max-age=2419200, must-revalidate”;add_header Strict-Transport-Security “max-age=63072000; includeSubDomains”;#try_files $uri =404;try_files $uri @proxy;}

    location ~ ^/emoji/ {add_header Cache-Control “public, max-age=2419200, must-revalidate”;add_header Strict-Transport-Security “max-age=63072000; includeSubDomains”;#try_files $uri =404;try_files $uri @proxy;}

    location ~ ^/headers/ {add_header Cache-Control “public, max-age=2419200, must-revalidate”;add_header Strict-Transport-Security “max-age=63072000; includeSubDomains”;#try_files $uri =404;try_files $uri @proxy;}

    location ~ ^/packs/ {add_header Cache-Control “public, max-age=2419200, must-revalidate”;add_header Strict-Transport-Security “max-age=63072000; includeSubDomains”;#try_files $uri =404;try_files $uri @proxy;}

    location ~ ^/shortcuts/ {add_header Cache-Control “public, max-age=2419200, must-revalidate”;add_header Strict-Transport-Security “max-age=63072000; includeSubDomains”;#try_files $uri =404;try_files $uri @proxy;}

    location ~ ^/sounds/ {add_header Cache-Control “public, max-age=2419200, must-revalidate”;add_header Strict-Transport-Security “max-age=63072000; includeSubDomains”;#try_files $uri =404;try_files $uri @proxy;}

    location ~ ^/system/ {add_header Cache-Control “public, max-age=2419200, immutable”;add_header Strict-Transport-Security “max-age=63072000; includeSubDomains”;#try_files $uri =404;try_files $uri @proxy;}

    location ^~ /api/v1/streaming {proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;proxy_set_header Proxy “”;

    proxy_pass http://streaming; proxy_buffering off; proxy_redirect off; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade;add_header Strict-Transport-Security "max-age=63072000; includeSubDomains";tcp_nodelay on;

    }

    location @proxy {proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;proxy_set_header Proxy “”;proxy_pass_header Server;

    proxy_pass http://backend; proxy_buffering on; proxy_buffer_size 8k; proxy_buffers 32 8k;proxy_redirect off; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade;proxy_cache CACHE; proxy_cache_valid 200 7d; proxy_cache_valid 410 24h; proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504; add_header X-Cached $upstream_cache_status;tcp_nodelay on; error_page 404 500 501 502 503 504 /500.html;

    It’s largely the same as the sample nginx config file that comes with mastodon. Note the multiple IP addresses which relate to the PUMA nodes and the streaming nodes. Also, there is “try_files $uri @proxy;” under each location, rather than the default “try_files $uri =404;”

    Finally, we have to create a copy of /home/mastodon/live/public from a system running PUMA. Do not include or later remove /home/mastodon/live/public/system. This is important for certain system files, emojis, js, and so on. After I run a pre-compile on the puma nodes, I have to sync this again.

    To make this more manageable, I’m breaking this up into parts:

    Part 2: PUMA configuration

    Part 3: Streaming configuration

    Part 4: Redis and Elasticsearch configuration

    Part 5: Sidekiq configuration

    Part 6: Postgres configuration

    https://blog.infosec.exchange/2022/12/22/scaling-mastodon-part-1/

    Scaling Mastodon – Part 1 – Infosec Exchange Blog