SSH GatewayPorts setting only for particular port - ssh

I'm trying to establish a reverse ssh tunnel with GatewayPorts set to no for all ports apart from a particular port (e.g 2222)
I have tried the following setting in sshd_config
Match LocalPort 2222
GatewayPorts yes
I have verified the config using
sshd -T -C lport=2222 | grep -i 'gateway'
> gatewayports yes
sshd -T -C lport=3333 | grep -i 'gateway'
> gatewayports no
While ports other than 2222 get established with the expected setting, reverse tunnel using port 2222 still binds to localhost instead of 0.0.0.0
The ssh version I am using is
ssh -V
> OpenSSH_8.2p1 Ubuntu-4ubuntu0.3, OpenSSL 1.1.1f 31 Mar 2020
Any help regarding this will be much appreciated
Thanks in advance

Related

Connection to Redis through SSH tunnel: reset by peer

My Redis instance is installed and run at VIRTUAL_MACHINE. I connect to VIRTUAL_MACHINE via SSH tunnel through TUNNEL_SERVER to work from my local machine.
Tunnel string is the following:
ssh -L 0.0.0.0:10011:VIRTUAL_MACHINE:22 -L 0.0.0.0:10004:VIRTUAL_MACHINE:6379 -o ExitOnForwardFailure=yes -o ServerAliveInterval=15 -o ServerAliveCountMax=3 username#TUNNEL_SERVER
The issue is I can't connect to Redis instance from the local machine:
redis-cli -h 0.0.0.0 -p 10004
0.0.0.0:10004> ping
Error: Connection reset by peer
telnet 0.0.0.0 10004
Trying 0.0.0.0...
Connected to 0.0.0.0.
Escape character is '^]'.
Connection closed by foreign host.
On the remote machine (VIRTUAL MACHINE):
redis-cli -h localhost -p 6379
localhost:6379> ping
PONG
netstat -an | grep 6379
tcp 0 0 0.0.0.0:6379 0.0.0.0:* LISTEN
redis.conf
bind 127.0.0.1
bind 0.0.0.0
protected-mode no
port 6379
timeout 60
tcp-keepalive 600
daemonize no
Because of Redis, I can't also connect to Flower (Celery).
If you have any idea about possible reasons, please help me to figure it out.
Thanks!
Only just saw this,
Can you SSH to 0.0.0.0:10011 and have access to the VIRTUAL_MACHINE?
Also are your auth creds for the TUNNEL_SERVER the same as for the VIRTUAL_MACHINE?
Forgive me if you already have, but, I would get SSH working to the VIRTUAL_MACHINE first via the TUNNEL_SERVER and then rework that to tunnel REDIS

How to remotely capture traffic across multiple SSH hops?

I want to debug another machine on my network but have to pass through one or more SSH tunnels to get there.
Currently:
# SSH into one machine
ssh -p 22 me#some_ip -i ~/.ssh/00_id_rsa
# From there, SSH into the target machine
# Note that this private key lives on this machine
ssh -p 1234 root#another_ip -i ~/.ssh/01_id_rsa
# Capture debug traffic on the target machine
tcpdump -n -i eth0 -vvv -s 0 -XX -w tcpdump.pcap
But then it's a pain to successively copy that .pcap out. Is there a way to write the pcap directly to my local machine, where I have wireshark installed?
You should use ProxyCommand to chain ssh hosts and to pipe output of tcpdump directly into wireshark. To achieve that you should create the following ssh config file:
Host some_ip
IdentityFile ~/.ssh/00_id_rsa
Host another_ip
Port 1234
ProxyCommand ssh -o 'ForwardAgent yes' some_ip 'ssh-add ~/.ssh/01_id_rsa && nc %h %p'
I tested this with full paths, so be carefull with ~
To see the live capture you should use something like
ssh another_ip "tcpdump -s0 -U -n -w - -i eth0 'not port 1234'" | wireshark -k -i -
If you want to just dump pcap localy, you can redirect stdout to filename of your choice.
ssh another_ip "tcpdump -n -i eth0 -vvv -s 0 -XX -w -" > tcpdump.pcap
See also:
https://serverfault.com/questions/337274/ssh-from-a-through-b-to-c-using-private-key-on-b
https://serverfault.com/questions/503162/locally-examine-network-traffic-of-remote-machine/503380#503380
How can I have tcpdump write to file and standard output the appropriate data?

Scp through ssh tunnel opened

I want to send files from machineA which has opened a reverse tunnel with a server. The reverse tunnel connects port 22 on machineA with port 2222 on the server:
autossh -M 0 -q -f -N -o "ServerAliveInterval 120" -o "ServerAliveCountMax 1" -R 2222:localhost:22 userserver#server.com
If I do:
scp file userserver#server.com:.
then SCP sends the file with a new login over SSH, in my case using public/private key.
But if I do:
scp -P 2222 file userserver#localhost:.
I get a "connection refused" message. The same happens if I replace 2222 above with the port found with:
netstat | grep ssh | grep ESTABLISHED
How I can send files without opening a new ssh connection (without handshake)?
You can use ControlMaster option in your ssh_config (~/.ssh/config), which will create persistent connection for further ssh/scp/sftp sessions. It is easy as pie:
Host yourhost
Hostname fqdn.tld
Port port_number # if required, but probably yes, if you do port-forwarding
ControlMaster auto
ControlPath ~/.ssh/master-%r#%h
ControlPersist 5m

CentOS 6.3. SSH. Bind to port xxx on 0.0.0.0 failed: Permission denied

CentOS 6.3 Minimal Configuration. Installed SSH Server, port 22. All works correctly.
I change port 22 on 777 and restart sshd and see in logs:
Jul 26 01:01:07 myserver sshd[1590]: error: Bind to port 777 on 0.0.0.0 failed: Permission denied.
Jul 26 01:01:07 myserver sshd[1590]: error: Bind to port 777 on :: failed: Permission denied.
Jul 26 01:01:07 myserver sshd[1590]: fatal: Cannot bind any address.
/etc/sysconfig/iptables contains:
-A INPUT -m state --state NEW -m tcp -p tcp --dport 777 -j ACCEPT
netstat -tulpn | grep :22 and netstat -tulpn | grep :777 return nothing
Centos uses SELinux by default and I don't think Ubuntu does (or least I've not seen it). Have a look for SElinux permission errors in your logs too.
SELinux does not allow sshd to be run on another port on a default install of CentOS 6.3. Follow -> https://blog.tinned-software.net/change-ssh-port-in-centos-with-selinux/ :
dig a hole into your firewall (you already did that)
add a rule for SELinux to allow sshd to be run on port 777: sudo semanage port -a -t ssh_port_t -p tcp 777
you can disable selinux with command sudo setenforce 0.
sudo setenforce 0
firewall-cmd --add-port=777/tcp --permanent
firewall-cmd --reload
Port 777 is dedicated for Multiling HTTP and even though not in use you can't bind to it. If you try for example to bind to port 8777 it will work just fine.
The problem is informing SELinux, but I think there are two cases:
the port is not already allocated for a built-in service, in such case, this may work:
sudo semanage port -a -t ssh_port_t -p tcp 22777
the port is overwriting some existing service (don't ask me why); in this case this slightly different syntax is necessary:
sudo semanage port --modify -t ssh_port_t -p tcp 777
Of course, such ports should be then made available by updating the firewall:
sudo firewall-cmd --add-port=22777/tcp --permanent
or
sudo firewall-cmd --add-port=777/tcp --permanent
and then:
sudo firewal-cmd --reload

ssh: check if a tunnel is alive

I have written a small bash script which needs an ssh tunnel to draw data from a remote server, so it prompts the user:
echo "Please open an ssh tunnel using 'ssh -L 6000:localhost:5432 example.com'"
I would like to check whether the user had opened this tunnel, and exit with an error message if no tunnel exist. Is there any way to query the ssh tunnel, i.e. check if the local port 6000 is really tunneled to that server?
Netcat is your friend:
nc -z localhost 6000 || echo "no tunnel open"
This is my test. Hope it is useful.
# $COMMAND is the command used to create the reverse ssh tunnel
COMMAND="ssh -p $SSH_PORT -q -N -R $REMOTE_HOST:$REMOTE_HTTP_PORT:localhost:80 $USER_NAME#$REMOTE_HOST"
# Is the tunnel up? Perform two tests:
# 1. Check for relevant process ($COMMAND)
pgrep -f -x "$COMMAND" > /dev/null 2>&1 || $COMMAND
# 2. Test tunnel by looking at "netstat" output on $REMOTE_HOST
ssh -p $SSH_PORT $USER_NAME#$REMOTE_HOST netstat -an | egrep "tcp.*:$REMOTE_HTTP_PORT.*LISTEN" \
> /dev/null 2>&1
if [ $? -ne 0 ] ; then
pkill -f -x "$COMMAND"
$COMMAND
fi
Autossh is best option - checking process is not working in all cases (e.g. zombie process, network related problems)
example:
autossh -M 2323 -c arcfour -f -N -L 8088:localhost:80 host2
This is really more of a serverfault-type question, but you can use netstat.
something like:
# netstat -lpnt | grep 6000 | grep ssh
This will tell you if there's an ssh process listening on the specified port. it will also tell you the PID of the process.
If you really want to double-check that the ssh process was started with the right options, you can then look up the process by PID in something like
# ps aux | grep PID
Use autossh. It's the tool that's meant for monitoring the ssh connection.
We can check using ps command
# ps -aux | grep ssh
Will show all shh service running and we can find the tunnel service listed
These are more detailed steps to test or troubleshoot an SSH tunnel. You can use some of them in a script. I'm adding this answer because I had to troubleshoot the link between two applications after they stopped working. Just grepping for the ssh process wasn't enough, as it was still there. And I couldn't use nc -z because that option wasn't available on my incantation of netcat.
Let's start from the beginning. Assume there is a machine, which will be called local with IP address 10.0.0.1 and another, called remote, at 10.0.3.12. I will prepend these hostnames, to the commands below, so it's obvious where they're being executed.
The goal is to create a tunnel that will forward TCP traffic from the loopback address on the remote machine on port 123 to the local machine on port 456. This can be done with the following command, on the local machine:
local:~# ssh -N -R 123:127.0.0.1:456 10.0.3.12
To check that the process is running, we can do:
local:~# ps aux | grep ssh
If you see the command in the output, we can proceed. Otherwise, check that the SSH key is installed in the remote. Note that excluding the username before the remote IP, makes ssh use the current username.
Next, we want to check that the tunnel is open on the remote:
remote:~# netstat | grep 10.0.0.1
We should get an output similar to this:
tcp 0 0 10.0.3.12:ssh 10.0.0.1:45988 ESTABLISHED
Would be nice to actually see some data going through from the remote to the host. This is where netcat comes in. On CentOS it can be installed with yum install nc.
First, open a listening port on the local machine:
local:~# nc -l 127.0.0.1:456
Then make a connection on the remote:
remote:~# nc 127.0.0.1 123
If you open a second terminal to the local machine, you can see the connection. Something like this:
local:~# netstat | grep 456
tcp 0 0 localhost.localdom:456 localhost.localdo:33826 ESTABLISHED
tcp 0 0 localhost.localdo:33826 localhost.localdom:456 ESTABLISHED
Better still, go ahead and type something on the remote:
remote:~# nc 127.0.0.1 8888
Hallo?
anyone there?
You should see this being mirrored on the local terminal:
local:~# nc -l 127.0.0.1:456
Hallo?
anyone there?
The tunnel is working! But what if you have an application, called appname, which is supposed to be listening on port 456 on the local machine? Terminate nc on both sides then run your application. You can check that it's listening on the correct port with this:
local:~# netstat -tulpn | grep LISTEN | grep appname
tcp 0 0 127.0.0.1:456 0.0.0.0:* LISTEN 2964/appname
By the way, running the same command on the remote should show sshd listening on port 127.0.0.1:123.
#!/bin/bash
# Check do we have tunnel to example.com server
lsof -i tcp#localhost:6000 > /dev/null
# If exit code wasn't 0 then tunnel doesn't exist.
if [ $? -eq 1 ]
then
echo ' > You missing ssh tunnel. Creating one..'
ssh -L 6000:localhost:5432 example.com
fi
echo ' > DO YOUR STUFF < '
stunnel is a good tool to make semi-permanent connections between hosts.
http://www.stunnel.org/
If you are using ssh in background, use this:
sudo lsof -i -n | egrep '\<ssh\>'