Rickstodon

Probably earlier than 2020-04-23

Rickroll Your Friends (or Foes) With A Fake Mastodon Registration Page

-- Introducing a new way to present an old prank

screenshot with most of the buttons and links on the page pointing to the signature rickroll cover image on youtube

See video demo; hosted on social.fkfd.me; see Codeberg repo

Edit 2022-01-07: social.fkfd.me is now defunct.

How to host it?

Because Mastodon is licensed under AGPL, and the frontend is not explicitly excluded, I doubt the legitimacy to redistribute it unlicensed. Therefore, this repo only contains a guide to make your own Rickstodon in N easy steps. You need either a working nginx, or python+pyramid.

Prepare a place for your prank

Get a domain. If you already have one, you can always add a subdomain record into its DNS settings, typically available in the registrar's web panel. For example, social.[your.domain] is a subdomain that seems totally legit. Set up an A/AAAA record pointing to your server IP. Let's call this domain social.legit.website throughout the tutorial.

Capture the Mastodon

Go to a Mastodon instance you are logged out of. You will be redirected to its about page, which looks like the screenshot above. Download the page using your browser, including the files. Chromium seemed to be unable to fetch the files? idk. Firefox works fine. Press ctrl+s to save about.html, as well as its embedded files into a directory called about_files.

You will see your files in a structure like:

about.html
about_files/
    common-9fa4342b.css
    d96d39a0abb45b92.png                   # admin avatar
    f6a76f37d508b407.png                   # user avatar
    fc87edd00a925e4c.png                   # user avatar
    56270e3bbd5ef1a4.png                   # user avatar
    vlcsnap-2018-08-27-16h43m11s127.png    # the mastodon-paper planes-trumpet picture
    common-a45d1c15f1388e6b8338.js
    default-78232038.css
    favicon.ico
    locale_en-0b1defbea6f42c8f057f.js
    public-5e7c276e9e232153d9c4.js

Open about.html in your browser. The files should load in their respective place because the filepaths are substituted with /about_files/xxx, except for external links, which are retained, e.g. Documentation links to https://docs.joinmastodon.org/ unchanged.

Now that you've shut the mastodon in the cage, this is where the fun begins.

Teaching the Mastodon to rickroll

Open and edit about.html. It is quite large for some text editors (~25 KiB). It's unindented by default. Format it using a code formatter to save your eyes from burning.

Remember the site you fetched the page from? Change all occurrences of that site (for example, mastodon.social to yours: social.legit.website. For example, in <head></head>, you may see the following:

<link href="https://mastodon.social/about" rel="canonical" />
<meta
  content="Server run by the main developers of the project  It is not focused on any particular niche interest - everyone is welcome as long as you follow our code of conduct!"
  name="description"
/>
<meta content="Mastodon hosted on mastodon.social" property="og:site_name" />
<meta content="https://mastodon.social/about" property="og:url" />
<meta content="website" property="og:type" />
<meta content="Mastodon" property="og:title" />
<meta
  content="Server run by the main developers of the project  It is not focused on any particular niche interest - everyone is welcome as long as you follow our code of conduct!"
/>

Edit the URL's, edit meta content, you name it. The meta content also goes into the visible <div class="hero-widget">; search for it and replace its text.

Done? Good! Now when you check out your site, it has your domain on it. But things are not right! People won't believe that this instance, unexpectedly under Eugen's administration, could attract 503k users in two short days. You need to modify those data as well. Search for Administered by: and Server stats:. These data are right under them. A value like 41 users/32 MAU is adequately deceiving.

But waaaaait. You still have Eugen's avi beside your name. This is easy: get your avi, place it under about_files, change those filenames in about.html accordingly. Same for other people's avis you wish to show. Under the Administered by: there is:

<div
  class="account__avatar"
  style="width: 36px; height: 36px; background-size: 36px 36px; background-image: url('/about_files/d96d39a0abb45b92.png')"
></div>

Replace d96d39a0abb45b92.png with your image, under the same directory. Alternatively, just name your avi d96d39a0abb45b92.png, overwriting the original.

Find an element called <div class="directory">. Below are at most three user avatars. You can modify their avis if you wish. Perhaps include yours in them. It's like this:

<div class="directory">
  <div class="directory__tag">
    <a href="/explore">
      <h4>
        <i class="fa fa-address-book fa-fw"></i>
        Discover users
        <small>Browse a profile directory and filter by interests</small>
      </h4>
      <div class="avatar-stack">
        <img
          alt=""
          class="account__avatar"
          src="about_files/d96d39a0abb45b92.png"
          width="48"
          height="48"
        />
        <img
          alt=""
          class="account__avatar"
          src="about_files/f6a76f37d508b407.png"
          width="48"
          height="48"
        />
        <img
          alt=""
          class="account__avatar"
          src="about_files/fc87edd00a925e4c.png"
          width="48"
          height="48"
        />
      </div>
    </a>
  </div>
  <!--other stuff-->
</div>

Yeah, it's literally just all the *.pngs.

Now for the final step tampering the frontend, we need to reconfigure the buttons so they take unsuspecting visitors to the classic music video for a classic song. Search for the button called Sign up. It is in an HTML form, so clicking it will take us to /auth; no good! We want to rickroll the visitors, not sign up an account for them. Scroll up till you meet with this line:

<form
  class="simple_form new_user"
  id="registration_new_user"
  novalidate="novalidate"
  action="/auth"
  accept-charset="UTF-8"
  method="post"
></form>

You see, the action="/auth" is the command that takes us to /auth. Remove it, along with novalidate="novalidate" and accept-charset="UTF-8" method="post", because we're making it no longer a real form that sends requests. Keep the class, for it is used by stylesheets. Without it the form will look primitive, and people will find out. Then, find the </form> after it. It shouldn't be far away. Change <form ...> to <div ...>, </form> to </div>. This prevents form submission from being invoked when the button is clicked. Find another form below, with a button called Log in. Do the same to it. An example:

<div class="simple_form new_user" id="login_new_user">
  <input name="utf8" type="hidden" value="&#x2713;" /><input
    type="hidden"
    name="authenticity_token"
    value="..."
  />
  <div class="fields-group">
    <div class="input email optional user_email">
      <!--email-->
    </div>
    <div class="input password optional user_password">
      <!--password-->
    </div>
  </div>
  <div class="actions">
    <button name="button" type="submit" class="btn button button-primary">
      Log in
    </button>
  </div>
  <p class="hint subtle-hint">
    <a href="/auth/password/new">Trouble logging in?</a>
  </p>
</div>

Remember the buttons? Yes, the Sign up and Log in. We need them to, when clicked, rickroll the visitors. Therefore, add an onclick action to both of them:

<button name="button" <!--add this line below-->
  onclick="window.location.replace('https://www.youtube.com/watch?v=dQw4w9WgXcQ')"
  class="btn button button-primary"> Sign up
</button>

Done! Now we've officially set up the frontend to rickroll visitors if they ever try to sign up or log in. You can test it in a browser. But waaaaaiit. What if they clicked on stuff like "Discover users" or the admin's profile? We need to set up redirections; they are called 301's, taken from their HTTP response code. I will introduce two ways to do it: nginx and python+pyramid. Feel free to fork and add stuff like python+flask, node.js+express, apache, etc.

Pretending innocent (2 methods)

nginx

  1. Check out nginx.config. What you see here is a server block for nginx. Place it either in your existent config file (typically in /etc/nginx/sites-available), or alongside with it renamed as something else.

  2. Look into the file:

# ...
# redirect the following paths to rickroll video
# the tilde (~) means regex; vertical bar (|) means 'or'.
# add more user names if necessary.
location ~ (/terms|/about/more|/public|/explore|/@USERNAME|/auth/password/new) {
    return 301 https://www.youtube.com/watch?v=dQw4w9WgXcQ;
}

The chain of paths catch all the links visitors will likely take a peek at. Replace USERNAME with your own username.

  1. symlink this file to /etc/nginx/sites-enabled: ln -s /etc/nginx/sites-available/FILENAME /etc/nginx/sites-enabled

  2. Check if there are any blatant problem.

  3. Restart nginx: nginx -s restart

  4. Go to your prank domain/subdomain to check result. Click on links to see if it works.

"it doesn't work... why?" Look, I'm not an nginx expert. Maybe you can try using python+pyramid?

python+pyramid (plus a little nginx reverse proxy)

  1. Install python3 and pyramid (pip3 install pyramid). If pip says requirements are satisfied, but anything goes wrong later, run this with --upgrade to see if it's because of an ancient version.

  2. Put web.py in the same directory as about.html.

  3. Open and edit the file, just like the nginx one.

  4. Run web.py as a background process. Use a screen, tmux etc session or a process manager for it. This is out of scope.

  5. You still need to configure nginx for a bit. Sure, there are other reverse proxies but nginx is the only one I possess knowledge of. Add this block to your nginx config file:

server {
        server_name [host];  # [host] is the domain of your rickstodon page, e.g. social.legit.website

        root /var/www/html;  # whatever
        index index.html;  # whatever

        location / {
                # if port 3904 is already taken, change this value both here and in web.py
                # if so, re-run the modified python script
                proxy_pass http://localhost:3904;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection 'upgrade';
                proxy_set_header Host $host;
                proxy_cache_bypass $http_upgrade;
        }
}
  1. Restart nginx: nginx -s restart

  2. Go to your prank domain/subdomain to check result. Click on links to see if it works.

Additional steps

  1. Use HTTPS on your website for best deception. A mastodon instance without it is bound to raise suspicion. Use Let's Encrypt to generate a certificate for your (sub)domain. Sorry, LE.

Drawbacks and vulnerabilities

  1. If you have set up Rickstodon with nginx, the browser may make a GET request to youtube.com that reveals your intention. Like this:

screenshot of a GET request to https://www.youtube.com/watch?v=dQw4w9WgXcQ in devtools

If the user's network is slow, they may notice youtube.com loading in the bottom bar in a desktop browser.

Summary

By now you should have already be savoring the joy from imaginary scenarios where people shout "whoa what the fuck" at a dancing dude. I have played this trick on my mastodon account this April Fool's day. It went... nicely. This repo is unlicensed, so you are always welcome to try and improve, and invent better ways to rickroll people. Thank you for coming to my TED talk.