Using SSH Tunneling to play Sid Meier's Alpha Centauri (SMAC) Multiplayer Online

Summary / Background

I am trying to set up online multiplayer for an old TBS from 1999. The multiplayer works with no changes if the host and other pc are on the same LAN, but I am trying to set up the connection over the internet so I can play with my Dad.

Multiple very old forum posts all agree that the game uses ports 2300-2400, 47624 to communicate. Here is an example from one of them:

...ask your firewall administrator to configure the firewall to use the following settings: Allow an initial outbound TCP connection on port 47624 Allow subsequent connections of inbound and outbound TCP and UDP ports 2300-2400. Set appropriate permissions for DirectPlay (Client).

I tried setting up these ports (2300-2400, 47624) on my router to forward to the host PC, but that did not work. The two PCs cannot see each other in game. I know I configured the router correctly since I have port 22 forwarded to the same PC for SSH and that works from any external network location.

My Idea

I then thought that since it works on LAN, if there is a way for me to make the external PC think it is on the same network as the host PC it should work. This is what made me think to use SSH with tunneling.

My thought was: If I can SSH to a machine within the same LAN as the host PC (either the host itself or some other third computer), and forward all the correct ports during initial connection, the game should think the host PC and remote PC are on the same LAN and the game should work as it does on LAN. Is this assumption even valid?

What I Have Tried So Far

  1. I set up SSHD on a Windows 10 PC (Desktop) using OpenSSH.
  2. I host an SMAC game on Desktop. Second PC (Laptop) can connect to this game when on the same LAN as Desktop.
  3. I disconnect Laptop from LAN and connect to my neighbor's WiFi so I can try from outside the LAN (he cleared me to use for test).
  4. I SSH to Desktop from Laptop on neighbors network. Using command ssh Desktop_Username@myHomeIpAddress

The SSH connection goes through but I cannot seem to make the computers see each other in SMAC no matter how many -L and -R options I put on the SSH command. My biggest attempt so far was ssh Desktop_Username@myHomeIpAddress -L 2300:localhost:2300 -R 2300:localhost:2300 -L 2350:localhost:2350 -R 2350:localhost:2350 -L 47624:localhost:47624 (based on my interpretation of the block quote above). The reason I discretely use 2300 and 2350 is because of a post I found that says:

Found out that both the people hosting and joining need to forward ports 2300-2400 TCP/UDP (if you can't forward ranges try just 2300 TCP and 2350 UDP), and the host needs to forward port 47624 TCP. This is the same as ALL directplay games.

My Questions

  • Is there a way to make SSH tunnel all port traffic such that it would simulate the PCs being on the same network? Almost like a VPN into my home network (maybe I should just set one of those up independent of SSH?). I think this would solve my problem immediately, but not sure if it's possible.
  • If not, am I interpreting the first block quote correctly? I set up 2300 and 2350 as -L and -R since it says "inbound and outbound TCP and UDP"
  • Is it even possible to send UDP traffic over SSH? I've read that SSH is TCP and I really don't get how they are different. If TCP is better and lossless, why can't UDP be used over it?

Extra Weirdness

When I have the computers connected over LAN in SMAC as in Step 2. of What I Have Tried So Far and then use a port tracking software CurrPorts on both Desktop and Laptop to see how they are connected, they don't seem to be communicating on the ports everyone says they should be. They do use ports 2300 and 2350 but they also seem to use port 2301, port 5000, and ports in the range 10000-70000 periodically. I haven't seen port 47624 used ever.

Below are screenshots of the active ports on CurrPorts while PCs are connected with LAN (terran.exe is SMAC):

Active ports on Desktop

Active ports on Laptop

Given that the Local and Remote ports don't match for these rows, it makes me worried that I would need to forward all possible combinations of ports in the SSH command with -L and -R options, which is obviously not feasible.

Final Notes

I have seen the guides online about using Hamachi or GameRanger to get online play working. I have seen many people in those forums say that it doesn't work, so please don't refer me to those posts. I want to find a solution that simulates LAN play without that kind of extra software. It would be best if I could find a solution that only requires my Dad to copy and paste some lines I send him into his CMD or WSL shell. I haven't had much luck in the past getting him to install software correctly.

Thanks for your help in advance!


Solution 1:

Is there a way to make SSH tunnel all port traffic such that it would simulate the PCs being on the same network? Almost like a VPN into my home network (maybe I should just set one of those up independent of SSH?). I think this would solve my problem immediately, but not sure if it's possible.

No. You really should just use a VPN.

One of the reasons is that actual VPN software works at IP layer (and sometimes even at Ethernet layer) – an actual network is created between the participating hosts, with each of them having an IP address within the VPN and being able to simply send any IP packets to any other host.

Depending on VPN software being used, it might even support broadcasts to the entire "LAN" which are often used for automatic discovery, although this isn't needed if the game lets you enter the "game host's" IP address manually.

If not, am I interpreting the first block quote correctly? I set up 2300 and 2350 as -L and -R since it says "inbound and outbound TCP and UDP"

I think you're interpreting it correctly, but you're using the SSH tunneling incorrectly.

First, SSH can only tunnel TCP streams, not UDP. Unlike VPNs, SSH tunneling happens slightly above TCP layer; it is not at all like "port forwarding" in routers. It specifically works only with direct TCP connections, and those connections aren't actually end-to-end.

That is, you cannot tell the game to directly connect to the server, instead you must tell it to connect to "localhost" where your SSH client picks the connection up, relays data over an SSH channel, and the SSH server establishes a whole new connection to the target.

Keeping that last paragraph in mind, your -L and -R usage would be alright if you used one or the other, but when both are combined this way you're essentially making an endless loop – the -L listens on client:2300 and connects to server:2300, while -R listens on server:2300 and connects to client:2300... the result is that your SSH client and server end up making tunnels to each other's tunnels infinitely, without ever touching the game.

Even if the infinite loop weren't a problem, there is also the issue that both your game and your SSH client (due to -L) are trying to listen on the same port on the same system (i.e. they both are trying to occupy localhost:2300), the same happening on the server-side as well.

Is it even possible to send UDP traffic over SSH? I've read that SSH is TCP and I really don't get how they are different.

The fact that SSH itself is TCP-based doesn't have much effect on what can be tunnelled over it. Plenty of VPNs transport whole IP packets, UDP included, over a TCP-based tunnel (although not necessarily with good results).

However, the "stream tunneling" feature in SSH specifically was made to work with TCP connections only.

If TCP is better and lossless, why can't UDP be used over it?

Sometimes, "lossless" is in fact the reason. (It is more of a problem with audio/video streams where "real-time" is more important, but may also affect gameplay as well.)

(Note: The next two paragraphs are where I mostly just parrot off something I've previously read on the internet, due to actually not having any personal experience with VoIP software myself – although I suppose MS Remote Desktop comes close, as in recent versions it is essentially a video stream that runs over UDP.)

In something like a video call, if the physical connection is lost for a few seconds, most people would expect the stream to return to what it's currently supposed to be showing – just like if an analog stream was interrupted. Signal got weak, some packets carrying video frames got lost, it's perfectly fine to forget about them – by the time the connection is repaired, they'll be out of date anyway.

With the same data being sent over TCP, it would instead focus on trying to get those lost packets retransmitted before anything else and even though packets can get through again, you'd wait for TCP to reach the retransmit timer, then wait for all the old video frames to go through (probably appearing as if the video is being fast-forwarded), and only then normal data can resume.

So it's possible to tunnel UDP over TCP, but it's often not desirable. When programs use UDP they typically implement their own reliability and flow-control features, similar to those of TCP's, but built to suit their specific needs.

I want to find a solution that simulates LAN play without that kind of extra software

The simplest solution, really, is a VPN. Yes, it's "extra software". However, it can transport any kind of packet directly from one player to another without any additional work (that's literally the one job of a VPN); there is usually no extra configuration ike "port forwarding" needed on the client side (neither internally to the VPN, nor externally); and most people are roughly familiar with commercial VPNs and may be more comfortable installing OpenVPN than running mysterious console command.

(Also, I don't know about GameRanger, but Hamachi is in fact just a VPN program! Or at least, it was a VPN program the last time I tried it. It used to work simply by connecting all users to one large VPN network, so that each player had a VPN-issued 5.x.x.x IP address for connecting to other players.)