I am using JSch to deploy various files over multiple VPS’s. I was able to get a working prototype with StrictHostKeyChecking
turned off. I would now like to re-enable host key checking so that I am not vulnerable to MITM attacks. Currently, the client is a Windows machine connecting to a VPS running Debian. Here is what I have done so far:
- Added remote IP address on my local machine (Windows client) using
"ssh-keyscan -t rsa <serverIp> >> ~/.ssh/known_hosts"
- Passed the path to my
known_hosts
file toJSch.setKnownHosts
in my application.
When attempting to establish a connection, the result is
com.jcraft.jsch.JSchException: UnknownHostKey: . RSA key fingerprint is
This is obviously due to my lack of understanding on how host keys work, or cryptography for that matter. From my basic understanding, the known_hosts
file contains a key. That key is used to ensure that the remote IP that we are connecting to is who they say they are, therefore preventing anyone attempting to "spoof" themselves as the server.
My known_hosts
file looks like
184.154.70.174 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDNv4m+tOZUipp8UDGrd+kbtsM5R+tu3ZYZi3p7OTRWUX/Wqy74pONlLqI+/WGu77EHnOfdssJfclgo37vKLRFKneXZNAMXE7FUu5yUNOHlpPwzmvYUT/sp1k9CeNrtJAbkm05pOBIDqDQQGfQ+IAw9zqqo/sqJ6c8NKiVFAt4Ud0msvedb559dhYgcjwb52ABbsJ0mZ8FnU7LKG1592/ZTtYxam+M3qMhtJacrh5gpfZjjx2lGhqpOgvM+xwWeK6DQVn0QyIJd474G3gcm4M43ErRfzXOum3p/0wOw+hL1ora9eWSz2Wf9WuDXf86xkbZPD7Gy6ER5LBhquy331p7X
And my code is (SSH
is an instance of JSch):
try {
SSH.setKnownHosts(new FileInputStream("C:/Users/nvulc/.ssh/known_hosts"));
SSH.addIdentity(keyPath, keyPass);
Session session = SSH.getSession("root", "184.154.70.174", 22);
session.connect();
} catch (Exception e) {
e.printStackTrace();
}
Which results in:
com.jcraft.jsch.JSchException: UnknownHostKey: 184.154.70.174. RSA key fingerprint is b4:79:5a:58:d3:15:ad:a9:c7:af:cc:d7:09:f5:40:62
at com.jcraft.jsch.Session.checkHost(Session.java:805)
at com.jcraft.jsch.Session.connect(Session.java:345)
at com.jcraft.jsch.Session.connect(Session.java:183)
at Main.main(Main.java:40)
2
Answers
Your approach is correct and should work if done correctly. Although FYI it doesn’t entirely protect from MitM —
ssh-keyscan
itself uses an unverified connection and is vulnerable to MitM, although if that connection is legit, checking the key prevents faking on later connections. This is a form/variant of SSH’s common ‘ToFU’ (Trust on First Use) security model.In general,
known_hosts
contains a mapping from host identities (names and/or IP addresses) to keys. But if your file was created only as you show, it has only one mapping entry containing only one key.make sure you pass the correct path to
setKnownHosts
, and run as the correct (same) user. If the path you specify cannot be opened (either does not exist or access not allowed) Jsch does NOT throw any error, it just returns without loading anything. You might instead open the file yourself withnew FileInputStream(pathstring)
and pass to thesetKnownHosts(InputStream)
overload, so you get an exception if the open fails.make sure you are using the same host identity. If e.g. a host has multiple names (like cloud servers often do) and you use one in
ssh-keyscan
but a different one inJSch
then even though this is actually the same host and key it won’t match. But if you are actually using IP addresses in both places, at least if you mean IPv4, this is less likely because very few machines today have multiple public IPv4 addresses. (In the past this was more common and called multihoming.) IPv6 is more possible; most IPv6 machines have both transient and permanent public addresses (as well as local/private ones), and often multiple transients.Your code works for me – https://www.browxy.com/#ALIEN_137442 – It ends with "JSchException: Auth fail" – which means it gets past host key verification.
Make sure the
known_hosts
file is in plain ASCII encoding (or UTF-8 without BOM, which should be identical to ASCII for this kind of contents). But not UTF-8 with BOM, let alone UTF-16 or even worse.Try also Unix line endings. Though line endings should not be an issue.