SSH
Secure Shell is a command line login service typically used for command line programs communicating with remote servers such as. A common use case is git communicating with GitHub. It is an alternative to using HTTPS. Rather than saving a basic password to windows credential manager, you instead save a private-key and public-key text file to the ~\.ssh
directory(i.e. the C:\Users\<username>\.ssh
directory).
The public key; you copy-paste onto the server website via the browser. The private-key, is used by the ssh-agent program, almost always OpenSSH, to gain access to the server. This system is more secure than HTTPS as it does not require user input to enter a password and the pre-generated password is mathematically un-crackable.
But unlike HTTPS, an SSH key pair is only used for authentication during the initial handshake, not to encrypt and decrypt incoming and outgoing data. OpenSSH is integrated into Windows, Mac and Linux.
Everyone is familiar with HTTP URLs such as:
https://github.com/user/repo.git
- in the format:
<protocol>://<nth-level-domain>….<2nd-level-domain>.<top-level-domain>/<file_path or query or fragment>
,
But, SSH URLs are simpler and less flexible. They only find a use in the command line. They can also only include a file-path, not queries and fragments, like in HTTP URLs. This is the sort of SSH URL you will need to add to a git repository:
git@github.com:user/repo.git
- in the format
<User>@<Host>/<file_path>
Unfortunately, knowledge of SSH is assumed and it is generally poorly explained.
Getting SSH on Windows
OpenSSH is an ‘optional feature’ in Windows 10. Check there is a path assigned in Powershell with the command: (gcm ssh).path
. It should be in: C:\WINDOWS\System32\OpenSSH
.
Under this folder, in addition to ssh.exe
, there should also be :
scp.exe
- remote copy over port 22 - faster but cannot pause and resume.sftp.exe
- remote copy, view, create, and delete over port 22 -equal securityssh-add.exe
andssh-agent.exe
- holds keys ready for use.ssh-keygen.exe
- generates the private and public keys used in SSH.ssh-keyscan.exe
- scans a list of hosts from the config file and collects the public keys.
If you don’t have these OpenSSH programs aleady, search Manage optional features
from the start menu and make sure you have Open SSH Client
in the list. If not, you should be able to add it.
Automatic ssh-agent activation
Git windows installation also installs start-ssh-agent.cmd
and start-ssh-pageant.cmd
following to C:\Program Files\Git\cmd
. Git should use these to start the ssh-agent
each time a git remote command is called.
I use MinGit, and it doesn’t add the SSH agent necissarily.
But if SSH is not working with git:
- search
Services
from the start Menu Scroll down toOpenSSH Authentication Agent
> right click > properties. Change the Startup type from Disabled to any of the other 3 options. I have mine set toAutomatic (Delayed Start)
. - Or, use in PowerShell, opened as Administrator:
Get-Service ssh-agent | Set-Service -StartupType Automatic
In bash use ; https://stackoverflow.com/questions/18880024/start-ssh-agent-on-login https://unix.stackexchange.com/questions/322124/ssh-add-add-all-private-keys-in-ssh-directory
Installing in WSL
I find it is simpler to make a host of new keys when you login to WSL rather than figure out a way to reference the ones in your windows mount.
Using SSH with GitHub
Unlike logging in with HTTPS, which is self explanatory, for SSH to work with a GitHub account, you need:
- SSH private key files saved in
~\.ssh
and registered withssh-add
. - SSH public keys (
….pub
extension) text registered on your GitHub account. - SSH
Host
,Hostname
,User
andIdentityFile
parameters added to your~\.ssh\conf
file - SSH address added as the remote location to your local GitHub repo in the format:
User@Host:GitHubUserName/repo
- Your
user.name
anduser.email
configured in git.
And there are lots or errors which can mess things up.
Delete all existing GitHub HTTPS credentials in windows credential manager:
- Type
credential
into start (Control Panel\All Control Panel Items\Credential Manager
), - Find
git:http://github.com
. These are the HTTPS keys. Delete them.
Delete existing SSH keys from the OpenSSH register:
ssh-add -d
Make a new key with OpenSSH called for example name_key
and saved in the ~\.ssh
directory. On the next line you should name the key for future reference, using. You have to enter full file path using /
file separators: e.g.: .ssh/name_key
.. You will reference this file later in the ~\.ssh\config
file.
Note: Whatever people say,
/
has been a valid file separator on Windows PowerShell since about 2008, so mix and match all you like.
Note: the email is not important. Also, you must explicity write ‘yes’ or ‘y’ at each stage to progress. -t RSA is the least secure -t DSA -t ECSDA -t ed25519 is the most secure option
ssh-keygen -t ed25519 -f $HOME/.ssh/id_name -C "youremail@whatever.com"
Add the private key (the one without the .pub file extension) to OpenSSH:
ssh-add $HOME/.ssh/id_name
Check the key is registered in OpenSSH:
ssh-add -l
Add the text in the .ssh/name_key.pub
file to your GitHub account.
Create, or open a text file called config
in the .ssh
directory and enter the details for the given account.
Host
: your custom handle for the service. If you have only 1 account, you can make it the same asHostName
HostName
: The IP address or HTTP URL of the server in question.IdentityFile
: The path to the private key which you just generated.IdentitiesOnly
: When you have uniquely namedHost
for each account on the same service, you can add theIdentitiesOnly yes
command which tells the ssh-agent will only try sending the private key corresponding to that particular Host.
I recommend naming the Host
yourself. This custom Host
name is what you will need to write into the git remote repo URL. It is possible to leave the default, but it can become confusing if you have multiple accounts with the Host
called github.com. I prefer to name the host explicitly. That way you can also test access to each host individually with ssh -T git@<Host>
, and you can drill down to the culprit. For example:
Host name_it
User git
HostName github.com
IdentityFile C:\Users\Seb\.ssh\name_key
IdentitiesOnly yes
Check your access is successful 🤞:
ssh -T git@name_it
Another way to test individual keys is to use the ssh command with the -i
flag. This way you don’t even need a config file. But you must still check that the the response comes back with the right username i.e. Hi sebanalysis...
, as although it tries that key first, if tries all the others too!
ssh -i $HOME/.ssh/id_sebanalysis -T git@github.com
Sometimes, in existing repos, you don’t need to have a different host name. But if you leave the IdentitiesOnly yes
flag, you need to have separate host names, as for a given session, the first key it sees in the conf file, it will lock to that account exclusively.
Because you have changed the host from the default github.com
to name_it
, you will have to modify the default SSH address for the repo on the website as below. Clone with the repo using the format <User>@<Host>:<GitHubUserName>/<repo>
:
git clone git@name_it/someuser/somerepo.git
Or change the address of an existing repo from HTTPS to SSH by first removing the existing URL, and then adding the new SSH URL:
git remote remove origin
git remote add origin git@name_it/someuser/somerepo.git
Check you have successfully added the new SSH URL:
git remote -v
If you have multiple accounts, you have to add the the git username and git email which you want to use for that repo. These are the names which appear on the git commits, both local and on GitHub. It is unrelated to SSH, but can be confusing and make you think that you’re connected to that repo via the wrong SSH details. Navigate to the repo and run:
git config user.name yourname
git config user.email youremail@whatever.com
The values will then be stored in in the .git/config
for that repo rather than your global configuration file.
You are finally done!
Common issues:
- Check the correct SSH URL is attached to the repo. Importantly, that it is not an HTTPS URL.
- The previously saved HTTPS keys are being used when they shouldn’t. Delete all existing credentials in windows credential manager
- Check SSH program is active.
n Windows PowerShell (run as admin):
-
Check the current status of ssh-agent:
Get-Service | ?{$_.Name -like '*ssh-agent*'} | select -Property Name, StartType, Status
-
Enable the Service if it is disabled:
Set-Service -Name ssh-agent -StartupType Manual
-
Start the Service:
Start-Service ssh-agent
-
Add your key as before:
ssh-add <path to the key>
Using SSH in Powershell on Linux
Powershell 7 can be used on linux. A Linux BASH shell profile contains the line: eval “$(ssh-agent -s)”, which assigns two environment variables: ‘SSH_AGENT_PID’ and ‘SSH_AUTH_SOCK’.
In Powershell on linux, there is no eval
command. The Invoke-Expression
command replicates the functionality but environment variables are written and set differently. Instead they must be set as: $env:variable=’value’. Therefore the string returned by ssh-agent
cannot be executed directly by Powershell. The following script captures the process ID’s and sets the relevant environment variables. Add it to your PowerShell profile.
# Start the ssh-agent daemon.
ssh-agent -s > ssh-env.txt
# Read the environment variables from the ssh-env.txt file into an array
$sshEnv = Get-Content ssh-env.txt
# Split the Array and set the environment variables
$env:SSH_AUTH_SOCK = $sshEnv[0].Split(';')[0].Split('=')[1]
$env:SSH_AGENT_PID = $sshEnv[1].Split(';')[0].Split('=')[1]
# Remove the ssh-env.txt file
Remove-Item ssh-env.txt
Errors
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ECDSA key sent by the remote host is
SHA256:lsjfl;sdjl;jf;lsdjfl;dsjlfj.
Please contact your system administrator.
Add correct host key in C:\\Users\\seb/.ssh/known_hosts to get rid of this message.
Offending ECDSA key in C:\\Users\\seb/.ssh/known_hosts:6
ECDSA host key for 172.18.6.4 has changed and you have requested strict checking.
Host key verification failed.
GO in to the .ssh/known_hosts file and delete the line with the IP address referenced
Even when yoy have different host names , it still wont connect with the right key
In this case, the only way is to remove all the keys fromm ssh-add:
ssh-add -D
Then re-add the one(s) you need, making sure each is a different hostname.