SSH VPN

SSH for an encrypted VPN

Leopard to Seequoia (Mac OS X)


Mac OS X, 10.5-15.x

File Sharing, Screen Sharing (or Remote Desktop)

(-using zsh/bash Terminal commands, among other things)

-with thanks to Bob Harris, who generously and patiently helped me through this the first time, on Apple Discussions

I note that some of the details of menus and options vary as we progress through operating systems, but I believe that it's clear enough. Ask if anything is unclear.


What

This is to have Internet access to your base computer (home, office, etc.), one name for which is the "server", from another computer at a different location (different room or different continent), the "client". (In my case, the server is an Apple desktop computer - an "ordinary" desktop computer - and the client is a Mac laptop/notebook computer - which makes sense for me but is not otherwise relevant.)

This access is strongly and securely encrypted, so that no one eavesdropping on a router along the way can decipher your data, and apparently it will often "tunnel" through otherwise difficult outgoing firewalls (from wherever you are with your "client" computer), although I have seen this fail.

There are probably several approaches to this, but the one described here uses an "SSH tunnel" ("SSH" meaning "Secure Shell"), including its optional Public/Private Key feature. No one can reasonably infiltrate your tunnel without both keys, either of which is kept on only one of the two computers, and which are not reverse-decrypt-able in practical terms, and which themselves can be further password-protected for multiple layers of security.

And the wonderful thing about all of this is that it's included in Mac OS X at no extra charge; all you have to do is learn how to do it (which will however require some time)!

Alternatives: there are commercial software programs which will do this for you, but I didn't find them much easier than doing it this way. I have not looked at Apple's own "Remote Desktop" program, which is a bit pricey. I haven't really looked at how iCloud might function in this context. Connecting to a non-Mac computer or to earlier versions of Mac OS X may be possible with further knowledge, which however I do not have. And so on; this is just one approach of many.

Usual disclaimers:

Why

  1. File Sharing over a "VPN" ("virtual private network") - Use data files on your server from wherever else in the world you are. This is exactly like using files on another computer on your private network, except that you've securely extended your network over the Internet. Working while leaving your data on your server can be very convenient, in that you don't have to have multiple copies of files, or remember which one is the most recent, or somehow keep them synchronized. (Alternatively, especially for large files, you could copy a file to your client computer, and when done working with it, copy it back to your server; your call.)
  2. Screen Sharing (aka "Remote Desktop") - Control your server remotely, making keyboard and mouse inputs to it, over your network. You see a copy of your server's monitor on your client computer's monitor. Someone watching your server's monitor would see it doing what it would be doing if you were there, even though you could be half-way around the world (or only across the room). You may have:
    • very large files on your server which could be cumbersome to use over the relatively slow Internet, or
    • software not installed on your client computer, for valid reasons.
    With Screen Sharing, the data which you transmit over the network is usually not much more than just a compressed image of your server's monitor display, which may often be substantially less than actually transferring whole files. (Sound is not transmitted, so you won't hear your server's noises - alarms, music - nothing. [Is that information still correct?])
  3. You can do other things, such as make your server into a private web server, although I have no experience with this.

Update!

Mac Mini 2019, OS X Catalina (10.15)

The following will make more sense perhaps after reading the "How?" section below, but I want to state up here near the top that I have had recent troubles, and that I have solved them.

Upgrading in the Autumn of 2019 to a new Mac Mini, using OS X 10.15 (Catalina): the tunnel crumped. I changed many settings and spent too long peering into help files and user forums, without any joy. The local (client) computer said, "connection refused" at the Remote Login port, and would not budge. This persisted over many days.

One day it suddenly worked again, and all has been well, and ... I'm not quite sure what I did. (Sorry!) Whether this has anything to do with the Mini's new hardware security chip, I do not know. Whether it relates to new features of 10.15, I also do not know. I am not alone in having access challenges, but was unable to locate any information on my exact scenario. But here are a few observations which may help you.

What I Did

The main thing seems to have been converting from AFP to SMB for file-sharing. (But I may be wrong about that.) Apple has recently "deprecated" (what a word the geeks have chosen; dictionary definition: "express disapproval of"!) file-sharing using the AFP protocol, and has joined much of the rest of the (computer) world, as I understand it, by using SMB, and: SMB uses a different port! So everywhere below where you see port 445 (SMB), it used to be 548 (AFP). (No matter that I had the Sharing settings configured to use both - my tunnel suddenly became happy soon after settling on SMB; it took me a while to wonder if that meant using a different port - it did.)

Now ... the "connection refused" message referred to the Remote Login port, not the File Sharing port, so ... go figure.

In the Privacy panel of the Security & Privacy settings, I have added Terminal under Accessibility and under Full Disk Access. Here and there around yer InterWeb I have found suggestions for many other settings, none of which have been helpful nor necessary for me.

I adjusted users, in Sharing, under Screen Sharing, File Sharing, and Remote Login, first of all separating out another account so that I'm not logging into an administrator account (safer that way, apparently), but I don't think that's the answer. Nonetheless, both the "Standard" and "Admin" users are included. There is no way I found to include the user from the local client computer, and it is working without that. Specifying, where possible, "All users" did not help, and I have reverted to "Only these users:".

It didn't appear to have anything to do with replacing the Airport Extreme Router - no longer available from Apple or from anyone - with a LinkSys router; that worked fine for months until I got the 2019 Mini with OS X 10.15. However, I did rearrange the order of port-forwardings to put 22 - Remote Login - first.

The old section on this page about how to configure an Airport Extreme has therefore been removed. Every router will be different. Read your help files. (If you can't read your help files, then you possibly shouldn't be reading this page.)

On my new Linksys, I needed to assign at least one permanent IP to the remote host, and that is at Connectivity, Local Network, DHCP Reservations. I put my static ports inside the dynamic range - a change from my older (now broken) Airport wireless router. I needed to forward three ports - more below - and that is at Security, Apps and Gaming, Single Port Forwarding.

During the somewhat random debugging of my SSH tunnel failure, I used a port-testing website to see what was open (and/or visible) and closed. I rather doubt that the resulting information contributed, but there it is in case you might find it helpful. The redirected ports, by the way, all seemed to be working as specified, and the native ports - 22, 445 and 5900 - could not even be seen (good!).

I tried disabling the Firewall on the remote host, and it didn't help. I have re-enabled it. All remains well. Under Advanced, I find that my three sharing services are there, as well as one other, and ... I didn't do any of that. The OS did it by itself. Obviously (I think), I have not selected "Block all incoming connections", and I have not selected "Enable stealth mode", and the other settings as found are fairly liberal.

OS X 10.15 in Terminal now uses, by default, zsh instead of bash. I have tried it using both, and that didn't seem to be a factor either.

At various points, if making substantial settings changes, then I of course rebooted both computers and the wireless router.


How?

For illustration purposes only:
  1. Let's give the server (the "remote") a computer name of "YourServer", with a user-account which you wish to access called "ServerAcct".
  2. We'll call the client ("local") computer "YourClient", with an account called "ClientAcct".
  3. For many of us, our server's address, its "IP", changes from time to time, under the control of our ISP ("Internet Service Provider"). This makes the server impossible to find over the Internet, so to get around this we need a "Dynamic Domain Name Server" service (DDNS) .
    • I was using Dyn, formerly free, and as the price went up I have switched to Dynu (but there are others), which as of January of 2021 is working well and required very little re-configuration.
    • At whatever DDNS you have chosen, create a hostname (I'll use "soulmate" only for purposes of illustration), and follow the instructions, and you'll end up with an address such as "soulmate.ddnsservice.yup".
    • Download their "DNS Updater" app (from your server, not from your client computer), install and run it. I believe that it needs to be running on your server all the time when you're using your SSH connection.
    This means that wherever you are, you can use that address to find your server, even if the server's address (its "IP") changes. (Don't worry - your computer will still be "closed" for all practical purposes to the outside world, presuming that you have a login password and don't go around advertising your "soulmate" name.) The Updater on your server keeps the DDNS server aware of your server's current IP and translates your "soulmate" address into that IP.

    Bonus!: apparently, and to the best of my understanding, the DNS Updater only needs to be running on one account on one computer, anywhere on the remote (host) network. (Better yet, apparently, is to run the updater on your remote/host router, but mine cannot do that.) Make sure that the chosen computer and account are running!

    Less Bonus: Although you only need the DNS Updater running in one place somewhere on the host network, if there is more than one host-network server you're accessing, each needs its own port-forwarding router-configuration. E.g., one may forward port 22 twice, once for each of the two servers (hosts, remotes) on your network, something like this (depending on your router):
    Internal port: 22
    External port: 12345
    Device IP#: 192.168.1.x
    
    Internal port: 22
    External port: 12346
    Device IP#: 192.168.1.a
    
  4. To make things more stable, I assign static network IPs to all of the involved computers. This is done on your router, and the details vary.
    • Find and note the DHCP Beginning Address and the DHCP Ending Address - you'll need this "dynamic address range" in a moment.
    • I reserve these IPs by MAC Address", and I find the MAC address by ...
    • ... (and this has varied a bit as the OS updates over the years) opening About This Mac from the Apple menu (upper left), go to System Report, Network, Wi-Fi, and in there is MAC Address. It uses a format like this: 10:AB:23:DE:45:F6.
    • In the router's DHCP Static IP settings, enter that MAC number, and choose an IP address. It will usually be 10.0.1.x (or 192.168.1.x, or for a second server I could say 192.168.1.a), and choose numbers for x and a. See the Update! section above. Let's similarly call the client computer's address 10.0.1.y. (Doing this for both computers makes things easier for one step coming up.)
    • You may close System Information.
    Critical Sequoia Update, OS X 15.0

    Possibly long in the making, my SSH tunnel failed quite spectacularly after updating from OS X 14.x to 15.0. As usual, I checked many settings, changed some, rebooted the router and the host (remote) computer many times, and it took a while for things to stick, but now that it's solid, it's holding over several days.

    What seems new is a thing called Private Wi-Fi address, and as of now (early October 2024) you get at this through System Settings (on the host [remote] computer). Right up near the top on the left, click on Wi-Fi, and the name of your remote's network (i.e. the host's) will appear at the top of that panel. Click the Details... button.

    A new panel opens, with the network name (of the host or remote computer) as the top item of 7 in a list on the left. And this only changes the settings for that specific network, i.e. shouldn't change anything if you move that computer to a new network, but it's the host (the remote), so in my case is stays physically in the same place all the time, always connected to the same network. It's the client (local) computer which moves, in this case my laptop, but we only need to change these settings on the host. One of the options is Private Wi-Fi address, and this must be set to Off.

    The deal is a that, no matter what other security measures you have enacted, the MAC of your computer's network card (as we used to call it), e.g. Ethernet or Wi-Fi (whichever you use) is (essentlly) physically unchangeable. So, some nefarious entity out there could track you across various networks by your MAC, and build up a profile on you. So, to combat this, you have the option of spoofing the physical address into a virtual address, which changes from time to time.

    But your various port-redirection settings (below) excpect a stable MAC, and that's why you have to turn Private Wi-Fi address to Off. The physical MAC address is shown, and that's the one which your router needs to know.

    Incidentally, in the 7-item list on the left, the next option below the local network is TCP/IP, and this will show the (host) computer's IP, so this is an easy place to check that it also always stays the same.

    This theoretically shouldn't matter if the host (remote) computer is always at home or in the office, never moves, and always stays on the same network, and that network is secure from outside predators, properly password-protected with a strong password, and all of the other things which I get into below. But whether it matters or not, this is the only way I can now get my SSH tunnel to work.

    Small terminology issue: the MAC is what we call the unique number which a computer's network card address has, and has nothing to do with the fact that, in this case, it's on a Mac computer.

  5. For added security, here is an optional step to reassign your SSH-Login port number, so that hackers going around looking for "standard" ports won't find yours in the usual place, and are unlikely to go looking any further. This done in your router settings - see again the "Update!" section above. (Don't worry about what "ports" are - just carry on.)
    • Port 22 is the Remote Login port, used by the SSH function. Forward port 22 to a 5-digit port, not over 65535(?). Five-digit ports are generally unassigned as defaults for anything, so are safe to use. (Some rare exceptions may apply.) In the examples below, I use "12345". (Don't use that!) The IP you will associate with this MAC number is the private IP which you assigned to the remote host above ("x"). Keep a record of these numbers in some secure place.
    • Similarly forward port 445 (SMB File-sharing) and 5900 (screen-sharing); the examples below use "23456" and "34567", but choose something more random of your own. These will also both go to IP "x".
  6. We're going to set certain settings in System Preferences, under Sharing.
    • On your server, make sure that you turn on "Remote Login", "File Sharing", and "Screen Sharing". (And leave them on forever - or at least when you're going to be away, if you can organize that.)
    • Similarly, on your client computer, make sure that "File Sharing" and "Remote Login" are turned on. There, you'll be able to turn them both off later.
  7. Now we're going to generate our "keys" - the things which give us encrypted security.
    • On the "client" computer, open a program called "Terminal". This provides a "command line" interface which can do many things not possible otherwise. The "command prompt" will look something like:
      	YourClient:~ ClientAcct$ 
      You're going to type (or safer would be to copy and paste) this command, then press the Enter key:
      	ssh-keygen -t rsa
      You will be asked for a password, so as usual it should be a strong password, and something which you can remember. (Again, by using a password here, you foil someone even if they somehow stole both of your keys.) You will then see a "key fingerprint" and "randomart" which I store somewhere secure (in an encrypted text file), but I'm not sure that I will ever need them.
      This command also creates a new folder in your home folder (which is "ClientAcct") called ".ssh" (the period starting a file or folder name means that it's invisible, or "hidden" to use Mac OS X terminology, so you can't see them in Finder), with two files inside it, id_rsa and id_rsa.pub. These are the private and "pub"-lic keys.
    • You can check this at the Terminal command prompt by looking inside the .ssh folder for files, and the command line for that could look like this:
      	ls .ssh
  8. scp ("Secure Copy") command

    N.B. I have trouble getting the "scp" command to work consistently. Recently I first connected the two computers, just on the same private network, using Finder, so that ClientAcct shows up on ServerAcct and vice versa, and then the "scp" command worked. There are several ways to do this connection, and most readers of this page will already know how: "File Sharing" is already enabled (above). Find "Network" or "Shared" in Finder and go from there. You'll need to know the name and passwords for what we're calling here "ClientAcct" and "ServerAcct". Terminal's "scp" command (from ClientAcct) will also then ask you for the ServerAcct password - not your "SSH key" password" - in order to perform its function. "ssh" will ask for the same type of information, in the next step.

    Now, the private key stays on the client computer, but we've got to move the public key to the server. The command line for that will look like this:
    	scp .ssh/id_rsa.pub ServerAcct@10.0.1.x:id_rsa.pub
    (You will of course throughout the following instructions substitute your own names and numbers for "ServerAcct", "x", "ClientAcct", "y", "soulmate.ddnsservice.yup", etc.) This command copies the public file to the server's account's "Home" folder (i.e. "ServerAcct"), plainly visible (temporarily). On the server, you'll be able to see it in Finder. At this point or later, if you're sure that the file transfer worked, delete the public key from the client computer. The command will be:
    	rm .ssh/id_rsa.pub
    Check it again as above with the "ls .ssh" command - it should be gone. It's important to delete it or someone stealing your laptop could figure out how to access your home computer (although the key itself is also password-protected).
  9. Switch to working on the server. Open Terminal. The command prompt, using our illustration-names, will be:
    	YourServer:~ ServerAcct$ 
    The first command will look like this:
    	ssh ClientAcct@10.0.1.y
    This creates a hidden folder (.ssh) on the server (like the one we made earlier on the client computer), inside your home folder (ServerAcct). (At this point, Terminal, despite that we're still working on the server, switches to a prompt indicating that it's working on the client. I just close the Terminal window and open a new one to get back to the server prompt.) Now, still on the server, we are going to insert or add the public key into a file called "authorized_keys", which will be created or appended to, and which resides inside the .ssh folder.
    	cat $HOME/id_rsa.pub >>$HOME/.ssh/authorized_keys
    Be very careful about the exact command, without altering the spacing, etc. It can be copied and pasted from here into Terminal. Then, if you wish to be really compulsive, you can check this process by looking at the key itself and then at the authorized_keys file and see if they look the same, or at least if authorized_keys contains the same character sequence.
    	cat id_rsa.pub
    	cat .ssh/authorized_keys
  10. Delete the file on the server, id_rsa.pub. You can do this from Finder (or from Terminal, using "rm id_rsa.pub", which does not put it in the Trash, but deletes it immediately). Empty the Trash; you need to make that public key as hard to find as possible. The only copy of it now resides inside the "authorized_keys" file, inside the hidden folder ".ssh". Un-share each computer from the other. Turn off File Sharing and Remote Login on the client.
  11. We're close to being able to use our encrypted SSH tunnel.
    • Make sure that the server won't go to sleep or that if it does it can be awakened by "network access" (System Preferences -> Energy Saver). Have the DDNS Updater or facsimile running properly.
  12. Here we go.
    • From the client computer - and you can test this even if you're at your home or office, on the same private network with your server (although then make sure that each computer has "ejected" the other's "account" so that you're sure that it's going to be the SSH tunnel which you're tesing) - open the Terminal program. Presuming that both computers have network connections of some kind, including Internet connections, type a command like this (substituting your own data, of course):
      	ssh -p 12345 -L 23456:localhost:445 -L 34567:localhost:5900 ServerAcct@soulmate.ddnsservice.yup
      If you require access to more than one server on the host network (see Less Bonus above), then other similar commands will be necessary for each one, e.g.:
      	ssh -p 12346 -L 23457:localhost:445 -L 34568:localhost:5900 OtherServerAcct@soulmate.ddnsservice.yup
      When you do this, you may be asked on occasion for your key's password. You may occasionally get notices about "authorized keys" and such, but they don't seem to disturb the process.

      You'll notice the "12345" from resetting the SSH Login port in your router earlier. The SSH "request" comes in from the client computer on that port number, and is then sent from the router to the server with the standard number. (Don't worry; it just works.) With the other numbers, "23456" and "34567" (examples only - use other "random" numbers when you do this yourself!), you're doing something similar for the standard ports for File Sharing and Screen Sharing, for added security.
    • And we get at those ports like this:
      From the client (local) computer, when the active menu is "Finder", type "Command-K" to get the "Connect to Server" function (or get it from the Go menu).
    • For File sharing, enter:
      	smb://localhost:23456
      substituting whatever you chose for your port number. (Thereafter, "Connect to Server" can save and remember your command so you can reuse it without typing.) For Screen Sharing, type:
      	vnc://localhost:34567
      again substituting your own number.
      You may be asked each time for your SSH key password and/or your server's account name and password; or you may not be! (One of them echoes in the Terminal window, and one does not, i.e. you will not see your typing as you do it.)

We're (almost) done!

And that's it! Your encrypted SSH tunnel is up and functioning, and you can use File Sharing and Screen Sharing immediately.

It won't be as nearly fast over the Internet as on a private network, but it will work.

Sometimes, however, my tunnel collapses and I have to restart it. Rarely, it just doesn't work, and then two hours later, it may suddenly cooperate. If the server locks up, you're out of luck. I have mine to set to power back on automatically after a power failure (cool!).

Screen Sharing is faster if you "Turn Scaling On" (View menu) and also use "Adaptive" video resolution. You can copy and paste back and forth between the server and client computer from the Screen Sharing Edit menu, or from buttons in the Screen Sharing Toolbar.

Things which you will need to remember:
  1. your key's password;
  2. Your SSH "Public TCP Port" number ("12345" in this example);
  3. the internal network address of your server ("10.0.1.x" in this example);
  4. the port you've chosen for File Sharing ("23456" in this example), the port you've chosen for Screen Sharing ("34567" in this example), and ports for other functions which you may use such as "Web server";
  5. your "Account" name on your server ("ServerAcct" in this example) and its password (the same one you use for a usual, local login);
  6. your DDNS address ("soulmate.ddnsservice.yup" in this example);
  7. ensure that your server won't "sleep" or that it awakes properly from sleep;
  8. leave the DDNS Updater (or equivalent) running on the server.

(I remember all of the numbers by keeping them in a password-protected virtual disk on my computer[s], but that's another story.)

Prevent Tunnel Collapse

This didn't seem to happen as often in the past as it does now, that the tunnel collapses, with the message: "Write failed: Broken pipe". Sometimes that's because the server times out after some undetermined period of inactivity. There are several places around the Web which discuss options to tame this behaviour, but the best option for me seemed to be to place a file called "config" (with very restrictive permissions) inside the .ssh folder on the client. That file on my client computer contains exactly this:

	Host * 
	 ServerAliveInterval 300

Apparently, indenting the second line matters(?!). Anyway, this sends a tiny confirmation (i.e. low overhead) every 300 seconds to the server, more or less saying, "I'm still here. Keep the tunnel open!" You'll need to know how to use the move ("mv") or copy ("cp") command if you use TextEdit to make the file, and how to do the addressing. For example, from your client account "Home" folder, presuming that you've created "config" there:

	mv config .ssh/config

The restrictive permissions could be like this:

	cd ~/.ssh
	chmod -N config
	chmod 600 config
	ls -lea
	cd ..

These five commands i) change to the .ssh folder, ii) remove "ACL permissions" (if any), iii) limit use of the config file to the owner only, iv) show the permissions of all the files in the folder, and v) change back to the "Home" folder. The listing for the config file on my computer looks like this:

	-rw-------@  1 ClientAcct  staff    32 10 Feb 21:22 config

I like lots of password protection, but haven't quite deduced why, when I occasionally have to re-initialize my SSH files, they vary. Recently, I was asked for no passwords at all. Using this commands on the client, starting from the home folder:

	chmod 700 .ssh
	cd .ssh
	chmod -N *
	chmod 600 *

resulting in being asked for the private (client) key password (but I had to reboot the computer first before that happened).

Interesting: having redone the entire procedure from scratch (because replaced internal hard drive), all of the permissions presumably went back to default, and my Client now logs in with no password requests. So, will update the permissions of course (on both computers?).

Addendum

A few things have come up, as of 2015 February, so here they are:


Conclusion

So, having written it down, no wonder it took a while the first time. There's a lot to it.

Enjoy! Questions, comments and suggestions always welcome, but remember that this isn't my "area".

Charles T. Low

Top

-OS X SSH from 2011
© #ctLow #CharlesTLow -updated: 2024-10-17