SSH on Windows

You’ve mastered all the SSH settings on your Linux/Mac and suddenly you’re thrust into the Windows world and need to access another machine via SSH. Old-school Windows users will probably download PuTTY. That should allow the most basic SSH operations. But once you need to do some more advanced stuff, you’ll also need to download puttygen to generate a new SSH key. And if you don’t want to constantly enter the SSH key’s passphrase you’ll also need pageant as well. (Don’t even think about using SSH keys without passphrases!)

That sounds like a lot of hassle. Luckily Microsoft got their shit together and distribute SSH on any recent installation of Windows 10 and 11. It’s all ready to go from the command line. You’re using Windows Terminal (Windows Terminal in the Microsoft Store), right?

Just open up Windows Terminal and try it out!

Simple SSH usage

Generate SSH key

It works! But it’s no fun! You probably want (or need) to use SSH keys for authentication. Since the implementation of SSH on Windows is actually OpenSSH it comes with all the other commands you’re used to. Just use ssh-keygen to generate a new SSH key.

Generate a new SSH key

In my case I generated an ED25519 key. If you ever generated an SSH key on Linux or macOS this should look very familiar.

Unfortunately ssh-copy-id is missing on Windows. So getting that public key on a remote machine is a bit clunky. The simplest way I could come up with is this:

type $env:USERPROFILE/.ssh/ | ssh {REMOTE_HOST} "cat >> .ssh/authorized_keys"

Obviously replace {REMOTE_HOST} with the real host here. And make sure you’re copying the public key! (Note the .pub at the end of they key file) While writing this article I accidentaly copied the private key over and spent several minutes trying to figure out why things weren’t working as expected.

Copying public key to destination host
As you can see in the screenshot on the second connection I was asked for the passphrase for my .ssh/id_ed25519 key. We’re getting somewhere!

Enable ssh-agent

The final piece of the puzzle is ssh-agent. Nobody likes entering a passphrase on every connection. Once per session (however you define session in this context) should be enough.

By default Windows comes with ssh-agent but it’s disabled by default.
SSH Agent settings

You can also check the status of the agent from the shell.

Get-Service ssh-agent

You can enable ssh-agent in the services snap-in of MMC.

Or you can use the shell. You will need local admin privileges for these commands to work. (Run terminal as administrator)

Get-Service ssh-agent | Set-Service -StartupType automatic
Start-Service ssh-agent

Enabling ssh-agent service

Once that’s done you can return to your regular (non-privileged) terminal. If the previous commands executed without any error you should be able to try to list all loaded SSH keys in the agent. Try ssh-add -l in the terminal.

SSH Agent without any identities loaded

You should get an error message stating that the agent has no identities loaded.

So let’s load up that key that you previously generated.

ssh-add .\.ssh\id_ed25519

Loading key into agent
You’ll be asked for the key’s passphrase and then you’re finally ready to go.

Connect to the host once again. If you followed my instructions correctly ssh should not ask again for the ssh key’s passphrase on connecting.

Use Windows Terminal by default

CMD in Windows Terminal

Have you ever thought that the default Windows console host is a clunky old piece of garbage? Choosing the font or colors is awkward at best. And it can’t be even resized horizontally. What a piece of crap!

Microsoft seems to have finally realized that and started the Windows Terminal project.

Once you install Windows Terminal you’ll be a little disapointed when Powershell or the command line still open up in the old console host. Some settings need to be adjusted.

Windows 11

Windows Terminal on Windows 11 has the built-in option to be used as default terminal for PowerShell and Command Prompt (cmd.exe). Simply start Windows Terminal, go to settings and then choose the default terminal application. Click save and you’re done.

Windows Terminal settings on Windows 11

If you only use Windows 11 you can stop reading now. Well done! Thanks for stopping by.

Windows 10

If you try the same on Windows 10 you will be disappointed to find out that this option is missing. But there is a way to do this manually.

Click on the start menu and then type Command Prompt (or Powershell). Do not press enter! At the top of the start menu the shortcut to the application should show up. Right-click on that link and choose "show file location".

Search for application link

An explorer window should open up with the link to the application highlighted. Right-click that link one once more and then choose properties. On the "Link" tab edit the target.

Properties of CMD link

Replace the target with the following: wt.exe -p "CMD"

The argument after -p is the name of the Windows Terminal profile. If you have an english version of Windows your profile might be called "Command Prompt".

Click OK and close the explorer window.

Repeat the steps to change the link to Windows Powershell and (if you have it installed) Powershell Core. If you don’t know what the names of the profiles in Windows Terminal are, just launch Windows Terminal and open the profiles menu.

Windows Terminal profiles menu

Next time you want to launch Powershell/Command Prompt you will be greeted by Windows Terminal launching Powershell/Command Prompt.

Pfsense Gateway Latency with Telegraf

Some years ago I started using the Telegraf package on pfSense and was disappointed to find out that it didn’t report the gateway latencies. So I wrote a quick&dirty Python 2 script that would parse the output of pfSense’s dpinger and output it in a format that Telegraf could send to InfluxDB.

With the most recent update of pfSense to version 2.4.5 Python 2 is no longer included and I had to update my script to Python 3.

The updated version (as well as the older version for Python 2) can be found in this Gist. Copy that Python script into /usr/local/libexec/telegraf/. And don’t forget to add that “Additional configuration for Telegraf” snippet to the configuration of Telegraf in the pfSense GUI.

Pair a second Trådfri remote to lights

I had a Trådfri remote paired with my lights but wanted to add a second remote. Googling returned a lot of contradicting information. In the end the following steps lead to success:

  1. Reset the new remote (just to be sure). Remove the cover at the back of the remote. Press the button inside 4x (within a 5 second span). On the front a red led should light up
  2. Now grab the already paired remote. Remove the cover on the back as well. Move the remotes close to each other and keep them close for the next steps,
  3. Press the button at the back of the new remote first and keep it depressed.
  4. After 1-2 seconds press the button at the back of the already paired remote as well and keep it depressed.
  5. At first the lights at the front of the remotes should be blinking rapidly but after 5-10 seconds they should both settle on a slow a steady pulse.

That’s it. Both remotes should now be able to control the same lights.

If it didn’t work just start again from the beginning. Just make sure not to reset the already paired remote or you’ll have to pair it with all the lights again!

How to assign a docker-machine host a static ip address

Boot2docker uses DHCP by default. Most solutions I found simply assign a static address and neglect to disable DHCP. Which led to the machine simply changing its ip address after some time.

This command line should take care of that:

cat <<EOF | docker-machine ssh docker-host sudo tee /var/lib/boot2docker/ > /dev/null
kill `more /var/run/`
ifconfig eth0 netmask broadcast up
ip route add default via

After creating that file on the host restart it and regenerate the client certificates:

docker-machine restart docker-host
docker-machine env docker-host
docker-machine regenerate-certs docker-host

What you need to know about the German umlauts if you’re typesetting a German document

sz ligature

German has 4 special characters that you need to be aware of, if you’re typesetting a German document. The 3 umlauts ä, ö, ü and the special ligature ß.
The umlauts are like regular characters. They come in lower case and upper case variants. ä, Ä, ö, Ö, ü and Ü.
The ß (sz ligature) is a special kind of character. First, there is no upper case variant of it. (At least not until recently, but it’s still a debated topic) And second, you should not confuse it with an upper case B or even the Greek beta character β! Those are completely different characters.
There are also some special rules regarding upper-casing the ß. Since there is no upper case ß, the ß becomes SS. But not every SS will become a ß when down-cased. (e.g. upper-casing “Straße” becomes “STRASSE”. But down-casing “WASSER” becomes “Wasser”).


Datenroaming from Hell

Ich bin demnächst ein paar Tage in Polen und möchte gerne auf Internet auf dem Smartphone nicht verzichten. Ich habe also bei T-Mobile (meinem Mobilfunkprovider) geschaut, wie ich im Ausland ins Internet komme, ohne meine Organe verkaufen zu müssen.


Der Standardtarif („In allen Tarifen voreingestellt“) ist indiskutabel. Wer das verbrochen hat, verdient einen besonderen Platz in der Hölle.

Da ich nicht ganz eine Woche in Polen bin, fiel mein Blick zuerst auf den „Travel&Surf“-Tarif für 7 Tage. Aber 150 MB für 7 Tage für 15€ ist einfach nur lachhaft. Die 150 MB würden vielleicht für einen Tag reichen. Und der Preis ist ist völlig inakzeptabel. (0,10€/MB)

Ich habe zum Schluß die Flat für 20€ genommen. Da wird mein monatliches Inklusiv-Volumen verwendet. In Deutschland bin ich meist in irgendwelchen WLANs eingebucht, und verbrauche mein Inklusiv-Volumen kaum, es bleibt also ausreichend Volumen über. Die 20€ sind immer noch horrend, aber alle Alternativen sind noch schlimmer.

Sollte ich demnächst wieder öfters Polen sein, werde ich mich nach Prepaid-Optionen direkt in Polen umschauen müssen.

Minimalistische Firewall-Regeln auf 1&1 Cloud Server

Beim Wechsel von meinem „alten“ 1&1 Dynamic Cloud Server auf einen neuen 1&1 Cloud Server (man beachte die Abwesenheit des Wortes „Dynamic“) habe ich mich gewundert, wieso Email-Versand und -Empfang nicht funktionieren wollte. Nach langer und vergeblicher Suche in Plesk fand ich die Ursache im 1&1 Cloud Panel.

Im Panel finden sich unter Netzwerk -> Firewall-Richtlinien zwei Default-Richtlinien. Die Richtlinie für Linux läßt gerade mal SSH (Port 22), HTTP(S) (Port 80 und 443) und Plesk (8443 und 8447) zu. Erst als ich hier noch SMTP (Port 25), Submission (Port 587) und IMAPS (Port 993) in die Richtlinie aufgenommen habe, funktionierten Emails wie gewohnt.


SSH-Agent für Authentizierung mit sudo verwenden

Pam-ssh-agent-auth ist ein PAM-Modul, um SSH-Schlüssel für die Authentizierung mit sudo zu verwenden. Das ständige eintippen des Passwortes kann auf die Dauer lästig werden, aber die authentizierung ganz abzuschalten fühlt sich auch irgendwie falsch an. Dieses Modul stellt einen guten Kompromiß dar.


Die Installation ist auf CentOS 7 (und CentOS 6) ist recht einfach, da das Modul einfach mit yum installiert werden kann:

yum install pam_ssh_agent_auth


Nach der Installation sind noch ein paar Anpassungen notwendig, damit das Modul mit sudo verwendet wird. Die Umgebungsvariable SSH_AUTH_SOCK muß von sudo erhalten bleiben. Hierzu muß in der sudoers-Datei (mit visudo bearbeiten) folgende Zeile ergänzt werden: (Die Datei enthält bereits einige env_keep-Zeilen. Diese sollte einfach hinter die anderen env_keep-Zeilen angehängt werden.)

Defaults    env_keep += "SSH_AUTH_SOCK"

Jetzt muß noch PAM auch das Modul für sudo verwenden. In der /etc/pam.d/sudo-Datei muß am Anfang (nach der Zeile mit #%PAM-1.0) folgende Zeile eingefügt werden:

auth       sufficient file=%h/.ssh/authorized_keys

Damit ist die ganze Konfiguration abgeschlossen.


Um zu Testen, ob das nun funktioniert, sollte man sich mit einem SSH-Schlüssel auf der Maschine anmelden und dann mit erst sudo -k möglicherweise noch gecachte Login-Daten aus sudo löschen und dann mit sudo -l schauen, was sudo einem erlaubt.

Sollte sudo unerwartet trotzdem nach dem Passwort fragen, kann man in der /var/log/secure nach Hinweisen für das Problem suchen. In meinem Fall hatte ich schlichtweg vergessen, den SSH-Agent beim SSH-Login weiterzuleiten (-A von der Kommandozeile oder ForwardAgent yes in der ~/.ssh/config.