Hacking SSH servers or how I enabled port forwarding over SSH when the server wouldn't let me

4 min read Original article ↗

At work, I've developing a new website for a client. Complete with a admin panel to make changes to the publicly-visible site. Built with Laravel and Vue.js, it's pretty nice.

I've been testing it locally and everything was fine, and it was time to deploy it to their server. I was given SSH access to the server and all the DNS records were configured, let's do this.

Using rsync, I was able to get everything deployed and running on the server. But, I missed something in the database migrations, and I had to go into the database manually and update a record. I updated the database migration code, so that if I ever deploy again (to another server), then I wouldn't need to access the database.

I have SSH access to the server, so I guess I'll just forward port 3306 and use phpStorm to connect to the database, easy. In fact, phpStorm supports accessing databases over an SSH tunnel built-in!

So, I added the SSH settings and database settings to phpStorm and... it gave me an error! Weird, but ok... let's try it manually from the command line, just make sure I'm not crazy.

In one terminal:

ssh -L 33066:localhost:3306 user@server

Then in another terminal:

mysql -h 127.0.0.1 -P 33066 -u db_user -p db_name

Enter in the password for db_user and I see:

ERROR 2013 (HY000): Lost connection to server at 'handshake: reading initial communication packet', system error: 11

That's weird. Looking at the SSH terminal, I see:

channel 3: open failed: administratively prohibited: open failed

What does administratively prohibited mean? After some searching, I determined that the client's web host (whom I won't name) is blocking port forwarding for some reason. I don't have sudo/root access to this server, so I can't edit the SSH configuration. No idea why they would do this, but they did.

Now I needed another solution. There has to be a way to do this. Maybe instead of forwarding port 3306, I forward the UNIX socket that MySQL is using: /var/lib/mysql/mysql.sock, but I'm sure how to do that.

I kept searching around and I forget what exactly I searched for, but I stumbled upon this question from Server Fault. Specifically, this answer that uses socat.

I've used socat before, but I don't really know everything it can do, so I didn't know it could be used here. So, based on that Server Fault answer, I created a script to "port forward" over SSH using socat1:

#!/bin/bash
SSH_SOCK="/run/user/$(id -u)/server.ssh.sock"

ssh -S "$SSH_SOCK" -qMfnNT user@server

socat \
    TCP-LISTEN:"33066,reuseaddr,fork" \
    EXEC:"ssh -q -S $SSH_SOCK -t user@server 'socat - TCP:localhost:3306'" \
&

disown

I ran this bash script and then I was able to run:

mysql -h 127.0.0.1 -P 33066 -u db_user -p db_name

Yep, now it works and now I was able to connect to the database in phpStorm.

In case you want to stop the port forwarding, use this script:

#!/bin/bash
pkill -15 -f 'socat TCP-LISTEN:*33066'
ssh -q -S "/run/user/$(id -u)/server.ssh.sock" -O exit user@server

Makes me wonder why the web host even decided to block port forwarding over SSH in the first place. Did they think it would improve security? Was this a decision by an engineer/sysadmin or a higher up who knows nothing about technology? Their settings didn't stop me from forwarding a port, just made it slightly more complicated.

This is the type of stuff I love. Spending time trying to solve a problem due to some awkward setting. Hope no one thinks I'm "hacking" their server :)

  1. Oh, socat obviously wasn't available on the server and I don't have access to the package manager, so I just downloaded the precompiled binary of socat from here: https://github.com/3ndG4me/socat/releases