ssh port forward to access my home machine from anywhere

I'll start with the raw facts :

  1. You have: A - your FreeBSD box, B - your router and C - some machine with Internet access. This is how it looks like:

    .-----.      .-----.                        .-----.
    |  A  |  ==  |  B  |  - - ( Internet ) - -  |  C  |
    '-----'      '-----'                        '-----'
    \_________ ________/
              v
               `- this is your LAN
    

    Notice how your router normally works: it allows connections from machines on your LAN to the Internet (simply speaking). So if the A (or any other machine on LAN) wants to access the Internet, it will be allowed (again, just talking about basic understanding and configuration) :

    .-----.      .-----.                        .-----.
    |  A  |  ==  |  B  |  - - ( Internet ) - -  |  C  |
    '-----'      '-----'                        '-----'
          `-->----'  `--->--->---^  
    

    And the following is not allowed by default:

    .-----.      .-----.                        .-----.
    |  A  |  ==  |  B  |  - - ( Internet ) - -  |  C  |
    '-----'      '-----'                        '-----'
          `--<----'  `---<--- - - - - --<---<-----'
    

    (That is, the router protects the machines on your LAN from being accessed from the Internet.) Notice that the router is the only part of your LAN that is seen from the Internet1).

  2. Port forwarding is what allows the third schema to take place. This consists in telling the router what connection from C2) should go to which machine on the LAN. This is done based on port numbers - that is why it is called port forwarding. You configure that by instructing the router that all the connections coming on a given port from the Internet should go to a certain machine on LAN. Here's an example for port 22 forwarded to machine A:

    .------.     .-------.                        .-----.
    |  A   | ==  |   B   |  - - ( Internet ) - -  |  C  |
    |      |     |       |                        '-----'
    '-|22|-'     ',--|22|'                          |
        `--<-22---'    `---<---- - - - - - --<-22---'
    
  3. Such connections through the Internet occur based on IP addresses. So a bit more precise representation of the above example would be:

    .------.      .-------.                                .-----.
    |  A   |  ==  |   B   | - - - - - ( Internet ) - - - - |  C  |
    |      |      |       |                                '-----'
    '-|22|-'      ',--|22|'                                   |
        `--<-A:22--'    `--<-YourIP:22 - - - - --<-YourIP:22--'
    

    If you do not have an Internet connection with a static IP, then you'd have to somehow learn what IP is currently assigned to your router by the ISP. Otherwise, C will not know what IP it has to connect to in order to get to your router (and further, to A). To solve this in an easy way, you can use a service called dynamic DNS. This would make your router periodically send information to a special DNS server that will keep track of your IP and provide you with a domain name. There are quite a few free dynamic DNS providers. Many routers come with configuration options to easily contact with those.

1) This is, again, a simplification - the actual device that is seen to the Internet is the modem - which can often be integrated with the router, but might also be a separate box.
2) or any other machine with Internet connection.


Now for what you want:

  1. Simply allowing ssh access to your machine from the Internet is a bad idea. There are thousands of bots set up by crackers that search the Internet for machines with open SSH port. They typically "knock" on the default SSH port of as many IPs as they can and once they find an SSH daemon running somewhere, the try to gain bruteforce access to the machine. This is not only a risk of potential break-in, but also of network slow-downs while the machine is being bruteforced.

  2. If you really need such access, you should at least

    • assure that you have strong passwords for all the user accounts,

    • disallow root access over SSH (you can always log in as normal user and su or sudo then),

    • change the default port on which your SSH server would run,

    • introduce a mechanism of disallowing numerous SSH login attempts (with icreasing time-to-wait for subsequent attempts - I don't remember how exactly this is called - I had it enabled some time ago on FreeBSD and I recall it was quite easy - try searching some FreeBSD forums etc. about securing SSH an you'll find it.)

    • If possible, try to run ssh daemon only when you know you will be accessing the machine in near future an turn it off afterwards

  3. Get used to going through your system logs. If you begin noticing anything suspicious, introduce additional security mechanisms like IP tables or port knocking.


There are a couple of ways to accomplish this.  The easiest is probably to set up what's known as a DMZ.  The more secure way, however, is on your router to set up a static route on port 22 to your server's IP.

Resources:

  • How is Port Forwarding Configured? (archived copy of NETGEAR page)
  • How to port forward for a faster internet (current, but incomplete, copy of the above, at TechRadar)
  • VPN Case Study FAQ