InfinityQuest - Programming Code Tutorials and Examples with Python, C++, Java, PHP, C#, JavaScript, Swift and more

Menu
  • Home
  • Sitemap

Python Programming Language Best Tutorials and Code Examples

Learn Python Right Now!
Home
Bash
Using SSH Without a Password in bash
Bash

Using SSH Without a Password in bash

InfinityCoder April 3, 2017

You need to use SSH or scp in a script and would like to do so without using a password.
Or you’re using them in a cron job and can’t have a password.*

There are two ways to use SSH without a password, the wrong way and the right
way.

The wrong way is to use a public-key that is not encrypted by a passphrase.

The right way is to use a passphrase protected public-key with ssh-agent or keychain.
We assume you are using OpenSSH; if not, consult your documentation (the commands and files will be similar).

First, you need to create a key pair if you don’t already have one.

Only one key pair is necessary to authenticate you to as many machines as you configure, but you may decide to use more than one key pair, perhaps for personal and work reasons.

The pair consists of a private key that you should protect at all costs, and a public key (*.pub) that you can post on a billboard if you like.

The two are related in a complex mathematical way such that they can identify each other, but you can’t derive one from the other.
Use ssh-keygen (might be ssh-keygen2 if you’re not using OpenSSH) to create a key pair. -t is mandatory and its arguments are rsa or dsa. -b is optional and specifies the number of bits in the new key (1024 is the default at the time of this writing) .

-C allows you to specify a comment, but it defaults to user@hostname if you omit it.

We recommend at least using -t dsa -b 2048 and we recommend strongly against using no passphrase.

ssh-keygen also allows you to change your key file’s passphrase or comment.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
$ ssh-keygen
You must specify a key type (-t).
Usage: ssh-keygen [options]
Options:
-b          bits Number of bits in the key to create.
-c          Change comment in private and public key files.
-e          Convert OpenSSH to IETF SECSH key file.
-f filename Filename of the key file.
-g          Use generic DNS resource record format.
-i          Convert IETF SECSH to OpenSSH key file.
-l          Show fingerprint of key file.
-p          Change passphrase of private key file.
-q          Quiet.
-y          Read private key file and print public key.
-t type     Specify type of key to create.
-B          Show bubblebabble digest of key file.
-H          Hash names in known_hosts file
-F hostname Find hostname in known hosts file
-C comment  Provide new comment.
-N phrase   Provide new passphrase.
-P phrase   Provide old passphrase.
-r hostname Print DNS resource record.
-G file     Generate candidates for DH-GEX moduli
-T file     Screen candidates for DH-GEX moduli
 
$ ssh-keygen -t dsa -b 2048 -C 'This is my new key'
Generating public/private dsa key pair.
Enter file in which to save the key (/home/jp/.ssh/id_dsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/jp/.ssh/id_dsa.
Your public key has been saved in /home/jp/.ssh/id_dsa.pub.
The key fingerprint is:
84:6f:45:fc:08:3b:ce:b2:4f:2e:f3:5e:b6:9f:65:63 This is my new key
 
$ ls -l id_dsa*
-rw------- 1 jp jp 1264 Dec 13 23:39 id_dsa
-rw-r--r-- 1 jp jp 1120 Dec 13 23:39 id_dsa.pub
 
$ cat id_dsa.pub
ssh-dss
AAAAB3NzaC1kc3MAAAEBANpgvvTslst2m0ZJA0ayhh1Mqa3aWwU3kfv0m9+myFZ9veFsxM7IVxIjWfAlQh3jp
lY+Q78fMzCTiG+ZrGZYn8adZ9yg5/
wAC03KXm2vKt8LfTx6I+qkMR7v15NI7tZyhxGah5qHNehReFWLuk7JXCtRrzRvWMdsHc/
L2SA1Y4fJ9Y9FfVlBdE1Er+ZIuc5xIlO6D1HFjKjt3wjbAal+oJxwZJaupZ0Q7N47uwMslmc5ELQBRNDsaoqF
RKlerZASPQ5P+AH/+Cxa/fCGYwsogXSJJ0H5S7+QJJHFze35YZI/
+A1D3BIa4JBf1KvtoaFr5bMdhVAkChdAdMjo96xhbdEAAAAVAJSKzCEsrUo3KAvyUO8KVD6e0B/NAAAA/3u/
Ax2TIB/M9MmPqjeH67Mh5Y5NaVWuMqwebDIXuvKQQDMUU4EPjRGmS89Hl8UKAN0Cq/C1T+OGzn4zrbE06CO/
Sm3SRMP24HyIbElhlWV49sfLR05Qmh9fRl1s7ZdcUrxkDkr2J6on5cMVB9M2nIl90IhRVLd5RxP01u81yqvhv
E61ORdA6IMjzXcQ8ebuD2R733O37oGFD7e2O7DaabKKkHZIduL/zFbQkzMDK6uAMP8ylRJN0fUsqIhHhtc//
16OT2H6nMU09MccxZTFUfqF8xIOndElP6um4jXYk5Q30i/CtU3TZyvNeWVwyGwDi4wg2jeVe0YHU2Rh/
ZcZpwAAAQEAv2O86701U9sIuRijp8sO4h13eZrsE5rdn6aul/mkm+xAlO+WQeDXR/
ONm9BwVSrNEmIJB74tEJL3qQTMEFoCoN9Kp00Ya7Qt8n4gZ0vcZlI5u+cgyd1mKaggS2SnoorsRlb2Lh/
Hpe6mXus8pUTf5QT8apgXM3TgFsLDT+3rCt40IdGCZLaP+UDBuNUSKfFwCru6uGoXEwxaL08Nv1wZOc19qrc0
Yzp7i33m6i3a0Z9Pu+TPHqYC74QmBbWq8U9DAo+7yhRIhq/
fdJzk3vIKSLbCxg4PbMwx2Qfh4dLk+L7wOasKnl5//W+RWBUrOlaZ1ZP1/azsK0Ncygno/0F1ew== This is
my new key

Once you have a key pair, add your public key to the ~/.ssh/authorized_keys file in your home directory on any other machines to which you wish to connect using this key pair.

You can use scp, cp with a floppy or USB key, or simple cut-and-paste from terminal sessions to do that.

The important part is that it all ends up on a single line.
While you can do it all in one command (e.g., scp id_dsa.pub remote_host:.ssh/
authorized_keys), we don’t recommend that even when you’re “absolutely sure” that authorized_keys doesn’t exist.

Instead, you can use a slightly more complicated but much safer command, shown in bold:

1
2
3
4
5
6
7
8
9
10
11
12
$ ssh remote_host "echo $(cat ~/.ssh/id_dsa.pub) >> ~/.ssh/authorized_keys"
jp@remote_host's password:
 
$ ssh remote_host
Last login: Thu Dec 14 00:02:52 2006 from openbsd.jpsdomai
NetBSD 2.0.2 (GENERIC) #0: Wed Mar 23 08:53:42 UTC 2005
 
Welcome to NetBSD!
 
-bash-3.00$ exit
logout
Connection to remote_host closed.

As you can see, we were prompted for a password for the initial scp, but after that ssh just worked.

What isn’t shown above is the use of the ssh-agent, which cached the passphrase to the key so that we didn’t have to type it.
The command above also assumes that ~/.ssh exists on both machines.

If not, create it using mkdir -m 0700 -p ~/.ssh.

Your ~/.ssh directory must be mode 0700 or OpenSSH will complain.

It’s not a bad idea to use chmod 0600 ~/.ssh/authorized_keys as well.

It’s also worth noting that we’ve just set up a one-way relationship.

We can SSH from our local host to our remote host with no password, but the same is not true in reverse, due to both lack of the private key and lack of the agent on the remote host.
You can simply copy your private key all over the place to enable a “web of passwordless SSH,” but that complicates matters when you want to change your passphrase and it makes it harder to secure your private key.

If possible, you are better off having one well protected and trusted machine from which you ssh out to remote hosts as needed.
The SSH agent is clever and subtle in its use. We might argue it’s too clever.

The way it is intended to be used in practice is via an eval and command substitution: eval ssh-agent.

That creates two environment variables so that ssh or scp can find the agent and ask it about your identities.

That’s very slick, and it’s well documented in many places.

The only problem is that this is unlike any other program in common use and
is totally obtuse to a new or uninformed user.
If you just run the agent, it prints out some details and looks like it worked.

And it did, in that it’s now running. But it won’t actually do anything, because the necessary environment variables were never actually set.

We should also mention in passing that the handy -k switch tells the agent to exit.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# The Wrong Way to use the Agent
 
# Nothing in the environment
$ set | grep SSH
$
$ ssh-agent
SSH_AUTH_SOCK=/tmp/ssh-bACKp27592/agent.27592; export SSH_AUTH_SOCK;
SSH_AGENT_PID=24809; export SSH_AGENT_PID;
echo Agent pid 24809;
 
# Still nothing
$ set | grep SSH
$
# Can't even kill it, because -k needs $SSH_AGENT_PID
$ ssh-agent -k
SSH_AGENT_PID not set, cannot kill agent
 
# Is it even running? Yes
$ ps x
PID TT   STAT     TIME COMMAND
24809 ?? Is     0:00.01 ssh-agent
22903 p0 I      0:03.05 -bash (bash)
11303 p0 R+     0:00.00 ps -x
 
$ kill 24809
 
$ ps x
PID TT   STAT     TIME COMMAND
22903 p0 I       0:03.06 -bash (bash)
30542 p0 R+      0:00.00 ps -x
 
# Still the Wrong Way to use the Agent
This is correct
$ eval `ssh-agent`
Agent pid 21642
 
# Hey, it worked!
$ set | grep SSH
SSH_AGENT_PID=21642
SSH_AUTH_SOCK=/tmp/ssh-ZfEsa28724/agent.28724
# Kill it - The wrong way
$ ssh-agent -k
unset SSH_AUTH_SOCK;
unset SSH_AGENT_PID;
echo Agent pid 21642 killed;
 
# Oops, the process is dead but it didn't clean up after itself
$ set | grep SSH
SSH_AGENT_PID=21642
SSH_AUTH_SOCK=/tmp/ssh-ZfEsa28724/agent.28724
 
# The Right Way to use the Agent
$ eval `ssh-agent`
Agent pid 19330
 
$ set | grep SSH
SSH_AGENT_PID=19330
SSH_AUTH_SOCK=/tmp/ssh-fwxMfj4987/agent.4987
 
$ eval `ssh-agent -k`
Agent pid 19330 killed
 
$ set | grep SSH
$

Intuitive isn’t it? Not. Very slick, very efficient, very subtle, yes. User friendly, not so much.
OK, so once we have the agent running as expected we have to load our identities
using the ssh-add command.

That’s very easy, we just run it, optionally with a list of key files to load.

It will prompt for all the passphrases needed.

In this example we did not list any keys, so it just used the default as set in the main SSH configuration file:

1
2
3
$ ssh-add
Enter passphrase for /home/jp/.ssh/id_dsa:
Identity added: /home/jp/.ssh/id_dsa (/home/jp/.ssh/id_dsa)

So now we can use SSH interactively, in this particular shell session, to log in to any machine we’ve previously configured, without a password or passphrase.

So what about other sessions, scripts, or cron?
Use Daniel Robbins’ keychain (http://www.gentoo.org/proj/en/keychain/) script, which:

1
2
3
4
5
6
7
8
9
[acts] as a front-end to ssh-agent, allowing you to easily have one long-running sshagent
process per system, rather than per login session. This dramatically reduces the
number of times you need to enter your passphrase from once per new login session to
once every time your local machine is rebooted.
 
[...]
 
keychain also provides a clean, secure way for cron jobs to take advantage of RSA/DSA
keys without having to use insecure unencrypted private keys.

keychain is a clever, well-written and well-commented shell script that automates and manages the otherwise tedious process of exporting variables
we discussed above into other sessions.

It also makes them available to scripts and cron.

But you’re probably saying to yourself, wait a second here, you want me to leave all my keys in this thing forever, until the machine reboots?

Well, yes, but it’s not as bad as it sounds.
First of all, you can always kill it, though that will also prevent scripts or cron from using it.

Second, there is a –clean option that flushes cached keys when you log in.
Sound backward? It actually makes sense.

Here are the details, from keychain’s author (first published by IBM developerWorks at http://www.ibm.com/ developerworks/, seehttp://www.ibm.com/developerworks/linux/library/l-keyc2/):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
I explained that using unencrypted private keys is a dangerous practice, because it
allows someone to steal your private key and use it to log in to your remote accounts
from any other system without supplying a password. Well, while keychain isn’t vulnerable
to this kind of abuse (as long as you use encrypted private keys, that is), there
is a potentially exploitable weakness directly related to the fact that keychain makes it
so easy to “hook in” to a long-running ssh-agent process. What would happen, I
thought, if some intruder were somehow able to figure out my password or passphrase
and log into my local system? If they were somehow able to log in under my
username, keychain would grant them instant access to my decrypted private keys,
making it a no-brainer for them to access my other accounts.
 
Now, before I continue, let’s put this security threat in perspective. If some malicious
user were somehow able to log in as me, keychain would indeed allow them to access
my remote accounts. Yet, even so, it would be very difficult for the intruder to steal my
decrypted private keys since they are still encrypted on disk. Also, gaining access to my
private keys would require a user to actually log in as me, not just read files in my
directory. So, abusing ssh-agent would be a much more difficult task than simply stealing
an unencrypted private key, which only requires that an intruder somehow gain
access to my files in ~/.ssh, whether logged in as me or not. Nevertheless, if an
intruder were successfully able to log in as me, they could do quite a bit of additional
damage by using my decrypted private keys. So, if you happen to be using keychain on
a server that you don’t log into very often or don’t actively monitor for security
breaches, then consider using the --clear option to provide an additional layer of
security.
 
The --clear option allows you to tell keychain to assume that every new login to your
account should be considered a potential security breach until proven otherwise.
When you start keychain with the --clear option, keychain immediately flushes all your
private keys from ssh-agent’s cache when you log in, before performing its normal
duties. Thus, if you’re an intruder, keychain will prompt you for passphrases rather
than giving you access to your existing set of cached keys. However, even though this
enhances security, it does make things a bit more inconvenient and very similar to running
ssh-agent all by itself, without keychain. Here, as is often the case, one can opt for
greater security or greater convenience, but not both.
 
Despite this, using keychain with --clear still has advantages over using ssh-agent all by
itself; remember, when you use keychain --clear, your cron jobs and scripts will still be
able to establish passwordless connections; this is because your private keys are
flushed at login, not logout. Since a logout from the system does not constitute a
potential security breach, there’s no reason for keychain to respond by flushing sshagent’s
keys. Thus, the --clear option is an ideal choice for infrequently accessed servers
that need to perform occasional secure copying tasks, such as backup servers, firewalls,
and routers.

To actually use the keychain-wrapped ssh-agent from a script or cron, simply source the file keychain creates from your script.

keychain can also handle GPG keys:

1
2
[ -r ~/.ssh-agent ] && source ~/.ssh-agent \
|| { echo "keychain not runnin" >&2 ; exit 1; }

When using SSH in a script, you don’t want to be prompted to authenticate or have
extraneous warnings displayed.

The -q option will turn on quiet mode and suppress warnings, while -o ‘BatchMode yes’ will prevent user prompts.

Obviously if there is no way for SSH to authenticate itself, it will fail, since it can’t even fall back to prompting for a password.

But that shouldn’t be a problem since you’ve made it this far in this recipe.
SSH is an amazing, wonderful tool and there is a lot to it, so much that it fills another book about this size.

We highly recommend SSH, The Secure Shell: The Definitive Guide by Richard E. Silverman and Daniel J. Barrett (O’Reilly) and for everything you ever wanted to know (and more) about SSH.
Using public keys between OpenSSH and SSH2 Server from SSH Communications
Security can be tricky; see Chapter 6 in Linux Security Cookbook by Daniel J. Barrett et al. (O’Reilly).
The IBM developerWorks articles on SSH by keychain author (and Gentoo Chief
Architect)

Daniel Robbins are also a great reference (http://www.ibm.com/ developerworks/linux/library/l keyc.htmhttp://www.ibm.com/developerworks/linux/
library/l-keyc2/, http://www.ibm.com/developerworks/linux/library/l-keyc3/).
If keychain doesn’t seem to be working, or if it works for a while then seems to stop,
you may have another script somewhere else re-running ssh-agent and getting things out of sync.

Check the following and make sure the PIDs and socket all agree.

Depending on your operating system, you may have to adjust your ps command; if
-ef doesn’t work, try -eu.

1
2
3
4
5
6
7
8
9
10
$ ps -ef | grep [s]sh-agent
jp       17364 0.0 0.0 3312 1132 ?    S     Dec16      0:00 ssh-agent
 
$ cat ~/.keychain/$HOSTNAME-sh
SSH_AUTH_SOCK=/tmp/ssh-UJc17363/agent.17363; export SSH_AUTH_SOCK;
SSH_AGENT_PID=17364; export SSH_AGENT_PID;
 
$ set | grep SSH_A
SSH_AGENT_PID=17364
SSH_AUTH_SOCK=/tmp/ssh-UJc17363/agent.17363

 

Share
Tweet
Email
Prev Article
Next Article

Related Articles

Removing Duplicate Lines in bash
After selecting and/or sorting some data you notice that there …

Removing Duplicate Lines in bash

Splitting Output Only When Necessary in bash
You want to split output only if the input exceeds …

Splitting Output Only When Necessary in bash

About The Author

InfinityCoder
InfinityCoder

Leave a Reply

Cancel reply

Recent Tutorials InfinityQuest

  • Adding New Features to bash Using Loadable Built-ins in bash
    Adding New Features to bash Using Loadable …
    June 27, 2017 0
  • Getting to the Bottom of Things in bash
    Getting to the Bottom of Things in …
    June 27, 2017 0

Recent Comments

  • fer on Turning a Dictionary into XML in Python
  • mahesh on Turning a Dictionary into XML in Python

Categories

  • Bash
  • PHP
  • Python
  • Uncategorized

InfinityQuest - Programming Code Tutorials and Examples with Python, C++, Java, PHP, C#, JavaScript, Swift and more

About Us

Start learning your desired programming language with InfinityQuest.com.

On our website you can access any tutorial that you want with video and code examples.

We are very happy and honored that InfinityQuest.com has been listed as a recommended learning website for students.

Popular Tags

binary data python CIDR convert string into datetime python create xml from dict python dictionary into xml python how to create xml with dict in Python how to write binary data in Python IP Address read binary data python tutorial string as date object python string to datetime python

Archives

  • June 2017
  • April 2017
  • February 2017
  • January 2017
  • December 2016
  • November 2016
Copyright © 2021 InfinityQuest - Programming Code Tutorials and Examples with Python, C++, Java, PHP, C#, JavaScript, Swift and more
Programming Tutorials | Sitemap