1

I have 3 Servers, A is a public accessable Server in the Internet. B Hosts a Webservice I want to access. C has access rights to connect to A and B.

Now i want that if a Client D tries to access a special Port on A that he gets forwarded to B.

IP's and Ports

A:

  • 1.0.0.1:22 SSHD Server
  • 1.0.0.1:443 Public Port which i want to use

B:

  • 1.0.0.2:23 SSHD Server
  • 1.0.0.2:444 Webservice I want to access

C:

  • 1.0.0.3

D:

  • 1.0.0.4

Diagram:

  +------------+        +------------+
  | Client (D) +--------> Public (A) |
  +------------+        +-----^------+
                              |
  +----------------+    +-----------+
  | Webservice (B) <----+ Proxy (C) |
  +----------------+    +-----------+

Question:

What ssh tunnel Commands do i need to execute on C so that if i try to open 1.0.0.1:443 on D i get the service hosted on 1.0.0.2:444 ?

  • I think i got half of it working by creating an ssh Relay with the following command: ssh -R 443:1.0.0.2:444 user@1.0.0.1 -p 22 This way, any connection from A to localhost:443 will return 1.0.0.2:444. However It is not possible to access yet from Client D – mac.1 May 21 '17 at 8:30
  • What you search is something like SSH VPN startpage.com/do/search?query=ssh+vpn – Aleksandar May 21 '17 at 10:58
  • You need to allow remote connects with the -o GatewayPorts yes option – eckes May 29 '17 at 9:59
1

On C you can run

ssh -fNR 1.0.0.1:443:1.0.0.2:444 root@1.0.0.1

It will only work if you login as root user because 443 is a privileged port. Moreover it only works if sshd on A is configured with GatewayPorts set to yes or clientspecified. (The default is no and using yes cannot be recommended, so if you want to do it this way I recommend clientspecified).

  • You could avoid all the problems using socat and sudo. e.g: ssh 1.0.0.1 "sudo -b socat tcp-l:443,fork,reuseaddr tcp:1.0.0.2:444 2>/dev/null 2>&1". – rudimeier May 29 '17 at 13:18
  • @rudimeier You are assuming there is a route between A and B. The question sort of implies there isn't any such route. – kasperd May 29 '17 at 13:55
  • 1
    Ah, ok. Anyways, in this case (and if C is reachable by A) I would run one socat on A (forward A to C) and another socat on C (forward C to B). The advantage is that it's more easy to start the tunnels onboot on A and C independently without any auto-ssh-login involved. – rudimeier May 29 '17 at 15:18
1

This is not quite how SSH tunnels work.You can get near to what you describe, but not exactly in the way you draw it up.

2 options are available to you:

  1. use Local port forwarding
  2. use Dynamic port forwarding

1) Local port forwarding

This requires you to change your approach: the tunnel needs to be opened from the client, from D in your diagram. it is easy to achieve, on the client (D) just do a

ssh -L 443:1.0.0.2:444 user@1.0.0.3

of course that requires you to:

  • have shell access or a putty client on D
  • have a user on the proxy (C) that D can login to
  • be able to connect from D to C via ssh
  • have the X11Forwarding and AllowTcpForwarding set to yes in the server config on C

I will explain Dynamic port forwarding in a moment

  • Between D and A ist the Internet and between A and C is the Internet. Only B and C are in the same network. So i don't think i can do local port forwarding. I will take a look at dynamic port forwarding – mac.1 May 20 '17 at 18:01
  • local port forwarding would still work for you, if you can reach C from D, and C can reach B. But you really need to be able to start the tunnel from a shell or a putty on D, the client. If you cannot do this, your only options is Dynamic port forwarding. – AndreasPolzInfonova May 20 '17 at 18:22
0

Edit:

@kasperd mentioned that you can set GatewayPorts for the user to you don't have to use nginx. I leave the workaround here for others.

Add this to /etc/ssh/sshd_config

Match User <username>
   GatewayPorts yes

Original Answer:

I found a solution achieving this with ssh and nginx. It is not perfect because i have to install a nginx server on A with a proxy. I had to enable ssl and give this nginx instance a own ssl certificate.

So the Solution will look like this: C will execute the following command to create a Relay between A and B:

ssh -R 445:1.0.0.2:444 user@1.0.0.1 -p 22

This will cause any input on Port 445 on 1.0.0.1 to be redirected to 1.0.0.2:444. So a local user on A can now executewget https://localhost:445 --no-check-certificate to get the index page of your webservice. However it is not public available yet. (in case you wonder: Port 445 is correct, i must use some unused port yet for the next part)

So i created a nginx server on A which will redirect any traffic from Port 443 to port 445. And used the following config:

server {
        listen 443 ssl default_server;
        listen [::]:443 ssl default_server;
        ssl on;

        ssl_certificate /etc/nginx/ssl/server.crt;
        ssl_certificate_key /etc/nginx/ssl/server.key;

        server_name proxy.<your-domain>.com;

        location / {
          proxy_pass        https://127.0.0.1:445;
          proxy_set_header  X-Real-IP  $remote_addr;
          proxy_set_header  Host $host;
        }
}

Now you can use your webbrowser (in incognito mode on Firefox to prevent issues with the certificate) to suft to https://proxy..com:443 and get the result from your Webservice. The IP of proxy..com must be 1.0.0.1.

What i dislike here is that i have to create a new webserver which will create a new encrypted session instead of just redirecting the one of my webservice located on B. However this is a good workaround till i find a better solution.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.