How can you SSH to an unknown host name with a known key?

4

I have a machine that connects to a corporate network over VPN. When I connect to the VPN, it always gives me a different hostname and ip address. The hostname is always remote-[last octet of ip address]. Whenever I want to SSH into my machine, I first have to run "hostname -A" to see what the hostname is. The problem is, I don't always know what my hostname is when I need to access the computer. (If I go to where the computer is physically located to find the hostname, it defeats my need to SSH.)

Could I use SSH and try each hostname/ip in the subnet until it finds one that matches the correct key file?


I am using a windows laptop (also connected via vpn) with cygwin to ssh to a Ubuntu 12.04 machine. I am not sure why I get a different hostname when I connect to the vpn, but it's a corporate network, so they get to do whatever they want.

user229010

Posted 2013-06-04T17:44:35.573

Reputation: 43

2I'm not sure I understand, is this a virtual machine or a physical one? Why will the hostname change? OK for the IP, but the hostname? In any case, is running a script on the remote machine that queries its hostname and posts it somewhere an option? – terdon – 2013-06-04T18:03:13.597

You can do a broadcast ping (ping -b in Linux, not sure in Windows), and identify your machine via its MAC adress by displaying the ARP table (arp in Linux, arp -a in Windows). – mpy – 2013-06-04T18:07:25.113

@mpy he'll still need to be connected to the remote machine for that right? – terdon – 2013-06-04T18:08:15.793

@terdon: I thought the broadcast would be enough to populate the arp table. A quick test was successful to identify some machines, but not for all... don't see a pattern, there is a explanation for sure, but I'm no network expert. – mpy – 2013-06-04T18:19:09.613

1@mpy he is connected via a VPN. If the VPN is routed, and not bridged, then a broadcast ping won't be possible. Broadcasts don't cross routers typically. Also, Linux hosts are often configured to not respond to broadcast pings. – Zoredache – 2013-06-04T18:22:06.313

I tried "arp -a" and unfortunately it looks like all machines that are connected over the vpn show the same mac address. – user229010 – 2013-06-04T18:57:36.133

Answers

2

This is not portscan

Here we are going to use only basic ssh utilities ssh-keyscan and ssh-keygen for network connections / key conversion.

If you know server fingerprint

and want to search for it then you can do:

for x in {1..254}; do ssh-keyscan 10.0.0.$x > /tmp/ssh-scan.log 2> /dev/null; cat /tmp/ssh-scan.log; ssh-keygen -lf /tmp/ssh-scan.log | grep -v 'not a public key file' ; done

and it will print fingerprints for all hosts found. Above line will go through 10.0.0.1 - 10.0.0.254, tries to get public keys from every host and at last converts public key to fingerprint and displays it. Most common error messages are redirected to black hole found from /dev.

Or maybe search for public key

Then same thing without fingerprint converter, displays public keys for all hosts between 10.0.0.0 and 10.0.0.255:

for x in {1..254}; do ssh-keyscan 10.0.0.$x 2> /dev/null; done

Final answer, ssh seek'n'connect script

Originally posted by user229010 as comment, i've only cleaned it up :-)

for i in {1..255}; do 
    echo trying remote-$i
    ping -w 1 -c 1 remote-$i > /dev/null
    if [ $? -eq 0 ]; then
        # this is a live ip
        echo remote-$i is up
        if ssh-keyscan remote-ca$i | grep $expected_key -m1 -c > /dev/null; then
            # this is my machine
            ssh remote-$i
            exit 0
        fi
    fi
done

Sampo Sarrala - codidact.org

Posted 2013-06-04T17:44:35.573

Reputation: 2 268

Perfect, this is what I was trying to figure out how to do. I added a ping to see if I could speed it up a little:

for i in {1..255} ; do
echo trying remote-$i
ping -w 1 -c 1 remote-$i > /dev/null
if [ $? -eq 0 ]; then
# this is a live ip
echo remote-$i is up
if ssh-keyscan remote-ca$i | grep $expected_key -m1 -c > /dev/null; then
# this is my machine
ssh remote-$i
exit 0
fi
fi
done – user229010 – 2013-06-05T15:45:31.057

I apologize for the messy comment... I was trying to edit it, but then my 5 minute editing window expired and it wouldn't let me fix it. – user229010 – 2013-06-05T15:52:18.063

@user229010 Thank you for sharing your own part, i've edited it in... – Sampo Sarrala - codidact.org – 2013-06-05T17:35:41.250

This is a pretty good solution assuming your pool of possible ip addresses is small, and your company's intrusion detection software doesn't boot you immediately. – MattPark – 2013-06-05T18:08:28.823

4

You have a few options here, listed from simplest to most complicated. Unsurprisingly this goes good, better, best.

  1. Use a crontab to update a file on a remote system with your hostname at some interval.
    Create/Edit Crontab: crontab -e
    Add Crontab Entry: To create a job that updates a file every hour during the workday only on weekends use this example:

    00 09-18 * * 1-5 ssh usr@example.com "echo $(hostname -A) > ubuntuhost.name"

  2. Use a crontab to email your hostname to yourself at some interval.
    Install Mailutils: sudo apt-get update && sudo apt-get install mailutils Note: choose 'internet connection' if propted by mailutils install, should be the first option.
    Create/Edit Crontab: crontab -e
    Add Crontab Entry: To create a job that emails you every hour during the workday only on weekends, with a subject line of the hostname, use this example:

    00 09-18 * * 1-5 mail -s "Ubuntu $(hostname -A)" you@you.com < /dev/null 

  3. Use the NetworkManager Dispatcher to email your current hostname whenever the connection changes.
    Put this script in /etc/NetworkManager/dispatcher.d, name it "50emailhostname"

#!/bin/sh -e
#make sure I'm executable (chmod 775)

echo "interface: $1, action: $2" >> /tmp/interface.log #debug

if [ "$1" = "eth0" ] && [ "$2" = "up" ]
then
  mail -s "Ubuntu $(hostname -A)" you@you.com > /tmp/interface.log #debug
else
  echo "false" >> /tmp/interface.log #debug
fi

exit

Notes:

  • You may need to change "eth0" in the script to "vpn0" or something depending on your client
  • You may need to change "up" to "vpn-up"
  • Use the debug statements to get the desired behavior!
  • tail -f /tmp/interfaces.log in a separate window to see what it's doing
  • Restart the network service as needed with service network-manager restart
  • Comment out the debug statements when done
  • You could get ip address instead of hostname with something like
    $(ifconfig | awk -F':' '/inet addr/&&!/127.0.0.1/{split($2,_," ");print _[1]}')

MattPark

Posted 2013-06-04T17:44:35.573

Reputation: 1 061

I think the email solution is safer than trying to update a file. His host machine is also connected via VPN, so, (without knowing for sure) there is a good chance that its hostname/IP are subject to the same vagaries as the remote. – Kent – 2013-06-04T22:12:15.173

nice, +1. Why are you taking /dev/null as input for mail? Or was < supposed to be >? – terdon – 2013-06-05T01:50:54.100

@terdon Thanks! I'll admit I'm proud of this one and have already thought of some alternate uses for the script I wrote for number 3. I actually tested all of this too. As for using /dev/null as input for mail, it asks for the body of the message if you don't provide it one, and since we put the host name in the subject line, a null body is ideal. There may be a better way to do it but I knew this one worked. – MattPark – 2013-06-05T03:33:17.480

+1 This is great way to keep out of lost my host? situation, proven to work well ... if you remember to do this before address has changed :) – Sampo Sarrala - codidact.org – 2013-06-05T17:41:49.803

You could also edit this to send the ip address vs. hostname – MattPark – 2013-06-05T18:05:14.150

1

It would make much more sense to have the remote machine report its IP somewhere. For example by running a crontab thaat connects to your local machine over ssh and writes the hostname to a file. If you update your question with more details (what OS? Is your local machine accessible over the network?) I can tell you how to do this.

Anyway, to try all the IPs in the subnet, assuming you have arp installed, you can do something like this:

for ip in `arp | grep -v Add | awk '{print $1}'`; do ssh $ip; done

terdon

Posted 2013-06-04T17:44:35.573

Reputation: 45 216

3iterating on the arp table won't be very useful if he is remotely connected via a VPN that offers a layer 3 connection (routed) instead of a layer 2 connection (bridged). – Zoredache – 2013-06-04T18:19:45.133

My arp (Linux/Debian/OpenSuSE) does neither have a parameter -e, nor does arp show a Add to grep for. What OS are you using? – mpy – 2013-06-04T18:21:37.950

Forget that part with "Add". I overlooked the -v... Add is short for Address. – mpy – 2013-06-04T18:29:33.907

Looping ssh to a sequence of IPs may get you on friendly terms with the corporate network admins; depending on what is at the other end of the IP, etc... – Kent – 2013-06-04T22:15:41.627

@mpy Debian, sorry the -e is something I remember from another OS, you're quite right it doesn't exist. – terdon – 2013-06-05T01:48:12.837

0

You could speed things up by exposing some service that's easily queried and no other machine is likely to have (of course SSH will also do, but checking with ssh is longer, and portscanning for ssh is understandably frowned upon).

Use a configurable port scanner to scan the whole subnet looking for that one service. The machine that has that service is the one you're looking for.

However, the best solution would be to talk with the network administrators and have the DNS update upon VPN connection.

LSerni

Posted 2013-06-04T17:44:35.573

Reputation: 7 306

0

If you like to bruteforce which IP is used by your ubuntu machine, OpenSSH has a tool called ssh-keyscan to scan the network for ssh host keys:

for ((a=0;a<255;a++)); do echo 198.51.100.$a; done | ssh-keyscan -f -H > ssh_id_list

You just need to know which one is your server. You can either get it directly from your server, or you can use the fact that your client stores them the first time it connects, into ~/.ssh/known_hosts :

ssh-keygen -F last_ip_you_used_to_connect -l

Then just grep ssh-keyscan with it.


Another possibility is to use mDNS: This is a distributed DNS solution that works well under the condition that the VPN allows multicast traffic. This is installed by default on Ubuntu desktops (if hostname -A displays yourhostname.local, it's good). If by any chance, iTunes (or any other Apple software that installs Bonjour) is installed in windows, then you can simply connect to yourhostname.local and it will work out of the box. Otherwise, if you have another Ubuntu machine laying around with a known ip address and a mDNS responder installed, just connect to it and ask it to resolve or ping yourhostname.local

BatchyX

Posted 2013-06-04T17:44:35.573

Reputation: 1 836