<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Ssh on blog.iankulin.com</title><link>https://blog.iankulin.com/tags/ssh/</link><description>Recent content in Ssh on blog.iankulin.com</description><generator>Hugo</generator><language>en-AU</language><lastBuildDate>Sat, 10 Jan 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://blog.iankulin.com/tags/ssh/index.xml" rel="self" type="application/rss+xml"/><item><title>VS Code Dev Containers</title><link>https://blog.iankulin.com/vs-code-dev-containers/</link><pubDate>Sat, 10 Jan 2026 00:00:00 +0000</pubDate><guid>https://blog.iankulin.com/vs-code-dev-containers/</guid><description>&lt;h3 id="remote-ssh"&gt;Remote-SSH&lt;/h3&gt;
&lt;p&gt;One of the things I&amp;rsquo;ve done a bit in Visual Studio Code is using it&amp;rsquo;s ability to work on a different machine over SSH. I have a couple of LXCs on a server set up for different languages - one for C++ and another for Rust. They are things I don&amp;rsquo;t work in often, and I didn&amp;rsquo;t want to set them up on my laptop, but thought I might want them again sometime in the future.&lt;/p&gt;
&lt;p&gt;This is straightforward in VS Code - You install the &lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-ssh"&gt;remote ssh extension&lt;/a&gt; locally, then choose &lt;code&gt;Remote-SSH: Connect to Host&lt;/code&gt; in the command palette. A few seconds later, it appears that you&amp;rsquo;re working locally, but actually you are working in a remote session on the server your VS Code instance is SSH&amp;rsquo;d into (a small indicator in the bottom left is the tell). You need to clone your project from git since you&amp;rsquo;re working in the server&amp;rsquo;s file system, and there&amp;rsquo;s some complexity with extensions since you&amp;rsquo;re sort of working in a new VS Code instance, but apart from that it feels the same as working locally.&lt;/p&gt;
&lt;img src="https://blog.iankulin.com/images/architecture-ssh.png" width="968" alt="Remote SSH VS Code architecture from https://code.visualstudio.com/docs/remote/ssh"&gt;
&lt;p&gt;The official docs for &lt;a href="https://code.visualstudio.com/docs/remote/ssh"&gt;Remote Development using SSH are here.&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="why-now"&gt;Why now?&lt;/h3&gt;
&lt;p&gt;The reason I&amp;rsquo;ve been interested in this again lately is to provide a more secure environment for using AI agentic coding tools like Claude Code. If it&amp;rsquo;s running in it&amp;rsquo;s own server (that I can easily recreate from a snapshot) I don&amp;rsquo;t have to worry about dramas like having &lt;a href="https://www.theregister.com/2025/12/01/google_antigravity_wipes_d_drive/"&gt;my hard drive deleted&lt;/a&gt; by Gemini.&lt;/p&gt;
&lt;p&gt;But what if you don&amp;rsquo;t have the ability to spin up an environment on your homelab? There&amp;rsquo;s a few options, but probably the easiest for VS Code users is to work in a &amp;lsquo;Dev Container&amp;rsquo;.&lt;/p&gt;
&lt;h3 id="dev-containers"&gt;Dev Containers&lt;/h3&gt;
&lt;p&gt;Working in a Dev Container is basically the same as remoting into another server with VS Code, but in this case the other server is a container spun up in Docker.&lt;/p&gt;
&lt;img src="https://blog.iankulin.com/images/architecture-containers.png" width="968" alt="VS Code Dev Container architecture. From https://code.visualstudio.com/docs/devcontainers/containers"&gt;
&lt;p&gt;There&amp;rsquo;s a couple of important differences from working on a remote server:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;we&amp;rsquo;re working on our local files;&lt;/li&gt;
&lt;li&gt;Dev containers are an important system for sharing repeatable development environments, so it&amp;rsquo;s well integrated into VS Code - the tooling is nice.&lt;/li&gt;
&lt;li&gt;You need Docker/Docker desktop running locally.&lt;/li&gt;
&lt;li&gt;You need a container image to work with, and a &lt;code&gt;devcontainer.json&lt;/code&gt; file to tell VS Code how to manage all this.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The rest of this post will focus on the basics of working in a Dev Container. There is also a good explanation of all this in the &lt;a href="https://code.visualstudio.com/docs/devcontainers/tutorial"&gt;VS Code docs&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="the-container"&gt;The Container&lt;/h2&gt;
&lt;p&gt;After you&amp;rsquo;ve installed the VS Code &lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers"&gt;extension&lt;/a&gt;, and set up your local Docker environment, you&amp;rsquo;re going to need a Docker container to work in. There&amp;rsquo;s a &lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers"&gt;big list of existing containers&lt;/a&gt; that cover most scenarios, but I prefer to roll my own. This is achieved by writing a Dockerfile.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;FROM node:24-bookworm
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# Use non-root user for development
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;USER node
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# Development environment
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ENV NODE_ENV=development
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# Default command
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CMD [&amp;#34;npm&amp;#34;, &amp;#34;start&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I&amp;rsquo;m going to name this &lt;code&gt;Dockerfile.dev&lt;/code&gt; and put it in the &lt;code&gt;.devcontainer&lt;/code&gt; directory - later we&amp;rsquo;ll point to it from our &lt;code&gt;devcontainer.json&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screenshot-2026-01-09-at-16.57.06.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;The Dockerfile describes the system that we&amp;rsquo;ll be working in when we&amp;rsquo;re working on our project - it&amp;rsquo;s like the specification of our remote &amp;lsquo;server&amp;rsquo;. Sometimes you might want to install other stuff here - for example if you are a vim enthusiast, you might &lt;code&gt;apt install vim&lt;/code&gt; in the Dockerfile, but generally you should keep it reasonably generic.&lt;/p&gt;
&lt;h3 id="devcontainerjson"&gt;devcontainer.json&lt;/h3&gt;
&lt;p&gt;Next we need to tell VS Code how to work in the container we&amp;rsquo;ve specified.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;name&amp;#34;: &amp;#34;Node.js Dev Container&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;build&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;dockerfile&amp;#34;: &amp;#34;Dockerfile.dev&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;forwardPorts&amp;#34;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 3000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;postCreateCommand&amp;#34;: &amp;#34;npm install&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This goes in the .devcontainer directory. It&amp;rsquo;s almost all self explanatory - we tell the extension what container we&amp;rsquo;re using - in this case building it from &lt;code&gt;Dockerfile.dev&lt;/code&gt;, export the port we&amp;rsquo;re running on, and run a command in the terminal of our new system once it exists.&lt;/p&gt;
&lt;h3 id="whats-missing"&gt;What&amp;rsquo;s missing?&lt;/h3&gt;
&lt;p&gt;Alert readers will have noticed there&amp;rsquo;s a couple of things that we need which are missing.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;VS Code Server - the way that VS Code is working in this configuration is that it&amp;rsquo;s running on our local machine, but connecting to a &amp;ldquo;VS Code Server&amp;rdquo; inside the container.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Bind mounts to our local directory - Once we load up the dev container, all our local files will need to be available in VS Code somehow.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So how to these get in the container? We don&amp;rsquo;t have to do anything to deal with these two issues. This is part of the magic that the VS Code Dev Container extension is doing for us. After the container is created, the extension:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;installs the server binary, and starts it&lt;/li&gt;
&lt;li&gt;bind mounts the local workspace to &lt;code&gt;/workspaces/&amp;lt;your-folder-name&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;And sets that as the WORKDIR in the container&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="lets-go"&gt;Let&amp;rsquo;s go&lt;/h3&gt;
&lt;p&gt;Okay, with the &lt;code&gt;Dockerfile.dev&lt;/code&gt; and &lt;code&gt;devcontainer.json&lt;/code&gt; in place, we&amp;rsquo;re now ready to launch our devcontainer.&lt;/p&gt;
&lt;p&gt;In the VSCode command pallet, run &lt;code&gt;Dev Containers: Reopen in container&lt;/code&gt;. The first run will take a few moments since the container has to be built first, but then it should look something like this:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screenshot-2026-01-09-at-17.49.40.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;The big clue that you&amp;rsquo;re in the dev container now is the blue message in the bottom left corner. Most everything that we could do in the local environment we can do here in the container - for example editing code and running it.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screenshot-2026-01-09-at-17.54.43.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screenshot-2026-01-09-at-17.54.53.png" alt=""&gt;&lt;/p&gt;
&lt;h3 id="extensions"&gt;Extensions&lt;/h3&gt;
&lt;img src="https://blog.iankulin.com/images/screenshot-2026-01-09-at-18.05.45.png" width="427" alt=""&gt;
&lt;p&gt;If you have a look at your VS Code extensions while working in this dev container, you&amp;rsquo;ll see that some are still installed, but others are now greyed out. Some extensions only effect the UI (&amp;ldquo;UI Extensions&amp;rdquo; - listed under &amp;ldquo;Local - Installed&amp;rdquo;) so they live in the local VS Code, others have functionality that needs to run in the workspace environment so they (&amp;ldquo;Workspace extensions&amp;rdquo;) need to live in the VS Code server part.&lt;/p&gt;
&lt;p&gt;Any UI Extensions you had installed before will still be there since they live in the local VS Code, but they others will be greyed out and unavailable unless you install them into the dev container.&lt;/p&gt;
&lt;p&gt;In the image here you can see my &amp;ldquo;vscode-icons&amp;rdquo; and &amp;ldquo;vscode-pdf&amp;rdquo; which only effect how things are displayed are both still available, but &amp;ldquo;Beancount&amp;rdquo; &amp;amp; &amp;ldquo;Cline&amp;rdquo; that need access to files need to be installed in the container if I want to use them on this project.&lt;/p&gt;
&lt;p&gt;We can click on the &amp;ldquo;Install in Dev Container&amp;rdquo; button for any of these, and it will be installed into the dev container. I need ESLint for this project so I&amp;rsquo;ll could that - then it will appear in the &amp;lsquo;Dev Container&amp;rsquo; tab. This is a good way of mimicking the normal workflow for users, but this extension is only persisted in the container while it exists - If we make any changes to the &lt;code&gt;dockerfile&lt;/code&gt; or &lt;code&gt;devcontainer.json&lt;/code&gt; VS Code will rebuild the container and the extension will be gone again.&lt;/p&gt;
&lt;p&gt;If we want a workspace extension, a more persistent way to install it is to add it to our &lt;code&gt;devcontainer.json&lt;/code&gt;&lt;/p&gt;
&lt;h3 id="adding-extensions-to-devcontainerjson"&gt;Adding extensions to devcontainer.json&lt;/h3&gt;
&lt;p&gt;Extensions added this way will be the same for anyone who uses our dev container definition (which is what I&amp;rsquo;m calling the combined &lt;code&gt;dockerfile&lt;/code&gt; and &lt;code&gt;devcontainer.json&lt;/code&gt;), including if they just clone the project from git. In fact, this was the original intention of dev containers - to have a fully reproducible development environment that is stored with its project.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s add a couple of extensions.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;name&amp;#34;: &amp;#34;Node.js Dev Container&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;build&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;dockerfile&amp;#34;: &amp;#34;Dockerfile.dev&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;customizations&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;vscode&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;extensions&amp;#34;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;dbaeumer.vscode-eslint&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;esbenp.prettier-vscode&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;forwardPorts&amp;#34;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 3000
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;postCreateCommand&amp;#34;: &amp;#34;npm install&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you make these changes in VS Code, it will probably pop up and ask you if it can rebuild the container, otherwise open the command palette and select &amp;ldquo;Dev Containers: Rebuild Container&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;You might be wondering where we get the extension id&amp;rsquo;s from (like &lt;code&gt;dbaeumer.vscode-eslint&lt;/code&gt;) The easiest way to to right click on one in the extension list and select &amp;ldquo;Copy Extension ID&amp;rdquo;. It&amp;rsquo;s also listed on the extension web page.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screenshot-2026-01-10-at-15.23.47.jpg" alt=""&gt;&lt;/p&gt;
&lt;h3 id="finally"&gt;Finally&lt;/h3&gt;
&lt;p&gt;So that&amp;rsquo;s the basics of getting a simple dev container set up. The code for this is on &lt;a href="https://github.com/IanKulin/devcont-demo"&gt;GitHub here&lt;/a&gt;. There&amp;rsquo;s a crucial issue we haven&amp;rsquo;t solved though - how to pull in your ssh keys for pushing the code to external repositories. We&amp;rsquo;ll deal with that in a future post.&lt;/p&gt;</description></item><item><title>SSH login notification</title><link>https://blog.iankulin.com/ssh-login-notification/</link><pubDate>Mon, 13 May 2024 00:00:00 +0000</pubDate><guid>https://blog.iankulin.com/ssh-login-notification/</guid><description>&lt;p&gt;&lt;a href="https://unsplash.com/photos/brown-bell-on-white-concrete-wall-4VRzuA4UxSY?utm_content=creditShareLink&amp;utm_medium=referral&amp;utm_source=unsplash"&gt;&lt;img src="https://blog.iankulin.com/images/nick-fewings-4vrzua4uxsy-unsplash.jpg" width="400" alt="Photo by Nick Fewings Unsplash
"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;My VPS&amp;rsquo;s are usually locked down so just ports 80 &amp;amp; 443 (for web server) and 22 (for ssh) are open. That&amp;rsquo;s great for reducing the attack surface, but having ssh open is a potentially disastrous vulnerability. For this reason I often close that at the cloud firewall level as well, but it has to be open when I&amp;rsquo;m making changes or running the weekly ansible update/cleanup playbooks.&lt;/p&gt;
&lt;p&gt;To make things a bit safer, I run &lt;a href="https://blog.iankulin.com/beginning-node-app-security/"&gt;Fail2Ban&lt;/a&gt; on the ssh logs, and also have notifications turned on via &lt;a href="https://ntfy.sh/"&gt;Ntfy&lt;/a&gt;. Ntfy is so useful I make an annual donation to support it&amp;rsquo;s development and help with Phil&amp;rsquo;s server costs. I recommend you do to. In fact, my setup for getting a notification on my watch everytime someone ssh&amp;rsquo;s into one of my VPS&amp;rsquo;s is just copied directly from &lt;a href="https://docs.ntfy.sh/examples/#__tabbed_1_1"&gt;Phil&amp;rsquo;s examples&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="changes"&gt;Changes&lt;/h3&gt;
&lt;p&gt;If you&amp;rsquo;re not logged in as root (that should be turned off) you&amp;rsquo;ll need to run all these as sudo.&lt;/p&gt;
&lt;p&gt;Edit &lt;code&gt;/etc/pam.d/sshd&lt;/code&gt; to add these lines to the bottom:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# at the end of the file
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;session optional pam_exec.so /usr/bin/ntfy-ssh-login.sh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then create the file &lt;code&gt;/usr/bin/ntfy-ssh-login.sh&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#5e81ac;font-style:italic"&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;if&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;[&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;${&lt;/span&gt;PAM_TYPE&lt;span style="color:#a3be8c"&gt;}&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;open_session&amp;#34;&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;]&lt;/span&gt;&lt;span style="color:#eceff4"&gt;;&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; curl &lt;span style="color:#ebcb8b"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -H prio:high &lt;span style="color:#ebcb8b"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -H tags:warning &lt;span style="color:#ebcb8b"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -d &lt;span style="color:#a3be8c"&gt;&amp;#34;SSH login: &lt;/span&gt;&lt;span style="color:#a3be8c"&gt;${&lt;/span&gt;PAM_USER&lt;span style="color:#a3be8c"&gt;}&lt;/span&gt;&lt;span style="color:#a3be8c"&gt; from &lt;/span&gt;&lt;span style="color:#a3be8c"&gt;${&lt;/span&gt;PAM_RHOST&lt;span style="color:#a3be8c"&gt;}&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#ebcb8b"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ntfy.sh/your-unique-notification-string
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;but replace &lt;code&gt;your-unique-notification-string&lt;/code&gt; with whatever string you&amp;rsquo;re monitoring with the app. Note that if you&amp;rsquo;re using the shared (rather than self hosted) service, these are public. If I&amp;rsquo;d used mine here, you&amp;rsquo;d be able to use it to spam my phone with alerts. For this reason, many people use GUIDs.&lt;/p&gt;
&lt;p&gt;We need to make this executable:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;chmod +x /usr/bin/ntfy-ssh-login.sh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And restart the ssh daemon&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo systemctl restart sshd
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then log out, and ssh back in, and you should get the notification.&lt;/p&gt;</description></item><item><title>Disable SSH root logins</title><link>https://blog.iankulin.com/disable-ssh-root-logins/</link><pubDate>Mon, 18 Sep 2023 00:00:00 +0000</pubDate><guid>https://blog.iankulin.com/disable-ssh-root-logins/</guid><description>&lt;p&gt;This always makes me laugh:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-08-03-at-8.01.20-pm.jpg" alt="Screenshot of terminal output full of lines saying &amp;ldquo;Failed password for root&amp;rdquo;"&gt;&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s like half the traffic on the internet is &lt;a href="https://blog.iankulin.com/chinese-hackers-want-to-steal-my-hello-world-container/"&gt;bots&lt;/a&gt; trying random passwords on root accounts over ssh. This is on an Ubuntu VPS on BinaryLane that had only been spun up five minutes or so. Looks like about one attempt every 10 seconds.&lt;/p&gt;
&lt;p&gt;This is why the number three thing on my new install list is to disable root access via ssh. Here&amp;rsquo;s my system - possibly just for Ubuntu and related systems:&lt;/p&gt;
&lt;p&gt;Add a new user, and put them in the sudo group&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;add user fred
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;usermod -aG sudo fred
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then log out, and ssh back in with the user you just created. Now we want to edit the config file for the ssh daemon. Since we&amp;rsquo;re not logged in as root now, we&amp;rsquo;ll have to use &lt;code&gt;sudo&lt;/code&gt;, so we&amp;rsquo;ll also find out if that&amp;rsquo;s working.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo nano /etc/ssh/sshd_config
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If &lt;code&gt;sudo&lt;/code&gt; doesn&amp;rsquo;t work, either you stuffed up adding the new username to the sudo group, or you don&amp;rsquo;t have sudo installed. If the problem is the latter, log out, and ssh back in as root and install it with &lt;code&gt;apt install sudo&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;There is probably a line with &lt;code&gt;PermitRootLogin&lt;/code&gt; in it. It may be commented out, or set to &lt;code&gt;yes&lt;/code&gt;. But we want it to end up looking like this&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PermitRootLogin no
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We&amp;rsquo;ll need to restart the daemon to pick up the config changes.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo systemctl restart sshd
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now if you log out, and try to ssh back in as root, it should fail. If it doesn&amp;rsquo;t, a likely issue is that there&amp;rsquo;s other configuration files being included. I feel I&amp;rsquo;ve mentioned before that a common pattern with Linux config files, at least on the Debian based systems I use, is that there&amp;rsquo;s a main config file that you probably shouldn&amp;rsquo;t mess with, but it pulls in subsidiary config files, often in a subdirectory called &lt;code&gt;conf.d&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;In the case of this file, there&amp;rsquo;s a line up the top saying&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Include /etc/ssh/sshd_config.d/*.conf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;which does exactly that.&lt;/p&gt;
&lt;h3 id="spy-vs-spy"&gt;Spy vs Spy&lt;/h3&gt;
&lt;p&gt;I&amp;rsquo;d love to know what passwords these bots are trying. I was thinking it wouldn&amp;rsquo;t be all that hard to write something that would face the password login process and run it on port 22 to see. I asked ChatGPT about this, but goodie-goddie that it is, all I got was a warning about ethics and some ssh security tips.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.iankulin.com/images/screen-shot-2023-08-04-at-6.04.02-pm.png"&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-08-04-at-6.04.02-pm.png" width="800" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m not the first person to &lt;a href="https://www.darkreading.com/endpoint/a-common-password-list-accounts-for-nearly-all-cyberattacks"&gt;think of this&lt;/a&gt;, so I might come back to this idea later. If I was running brute force ssh I guess I&amp;rsquo;d use one of the common password lists from one of the big leaks, so it might not be that exciting. It would also be interesting to see what the first command they tried to run is as well.&lt;/p&gt;</description></item><item><title>Ansible with Secrets</title><link>https://blog.iankulin.com/ansible-with-secrets/</link><pubDate>Sun, 13 Aug 2023 00:00:00 +0000</pubDate><guid>https://blog.iankulin.com/ansible-with-secrets/</guid><description>&lt;p&gt;We wrote a nice &lt;a href="https://blog.iankulin.com/first-ansible-playbook/"&gt;little Ansible playbook&lt;/a&gt; the other day to install nginx on our web servers and ensure it was running. We were able to store the usernames in the &lt;code&gt;hosts&lt;/code&gt; inventory file using the a&lt;code&gt;nsible_ssh_user&lt;/code&gt; variable. Then, we ran the playbook with the command:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ansible-playbook web_installs.yaml --ask-become-pass&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This asked us the password to use with the usernames in the &lt;code&gt;hosts&lt;/code&gt; file. Luckily that day, it was the same username/password combo to use for sudo on every server. What happens if that&amp;rsquo;s not the case? Here&amp;rsquo;s our new hosts file for today. There&amp;rsquo;s a cool new sysadmin in town - Jane.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#eceff4"&gt;[&lt;/span&gt;vm323_deb&lt;span style="color:#eceff4"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#b48ead"&gt;100.108&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#b48ead"&gt;154.133&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#eceff4"&gt;[&lt;/span&gt;vm323_deb&lt;span style="color:#eceff4"&gt;:&lt;/span&gt;vars&lt;span style="color:#eceff4"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ansible_ssh_user&lt;span style="color:#81a1c1"&gt;=&lt;/span&gt;ian
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#eceff4"&gt;[&lt;/span&gt;vm324&lt;span style="color:#81a1c1"&gt;-&lt;/span&gt;deb&lt;span style="color:#eceff4"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#b48ead"&gt;100.77&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#b48ead"&gt;75.14&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#eceff4"&gt;[&lt;/span&gt;vm324_deb&lt;span style="color:#eceff4"&gt;:&lt;/span&gt;vars&lt;span style="color:#eceff4"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ansible_ssh_user&lt;span style="color:#81a1c1"&gt;=&lt;/span&gt;jane
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We could still use &lt;code&gt;--ask-become-pass&lt;/code&gt; but it only asks us one password, and it&amp;rsquo;s highly unlikely (we hope) that Jane and Ian have chosen the same password.&lt;/p&gt;
&lt;p&gt;If you look at the inventory file above, you can see how the variables work - it&amp;rsquo;s the same variable name - Ansible swaps the correct value in for each server as it accesses them. There&amp;rsquo;s many of these variables in addition to &lt;code&gt;ansible_ssh_user&lt;/code&gt;, including &lt;code&gt;ansible_ssh_pass&lt;/code&gt;, so maybe we can do something like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#eceff4"&gt;[&lt;/span&gt;vm323_deb&lt;span style="color:#eceff4"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#b48ead"&gt;100.108&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#b48ead"&gt;154.133&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#eceff4"&gt;[&lt;/span&gt;vm323_deb&lt;span style="color:#eceff4"&gt;:&lt;/span&gt;vars&lt;span style="color:#eceff4"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ansible_ssh_user&lt;span style="color:#81a1c1"&gt;=&lt;/span&gt;ian
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ansible_become_password&lt;span style="color:#81a1c1"&gt;=&lt;/span&gt;mittens96
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#eceff4"&gt;[&lt;/span&gt;vm324_deb&lt;span style="color:#eceff4"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#b48ead"&gt;100.77&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#b48ead"&gt;75.14&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#eceff4"&gt;[&lt;/span&gt;vm324_deb&lt;span style="color:#eceff4"&gt;:&lt;/span&gt;vars&lt;span style="color:#eceff4"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ansible_ssh_user&lt;span style="color:#81a1c1"&gt;=&lt;/span&gt;jane
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ansible_become_password&lt;span style="color:#81a1c1"&gt;=&lt;/span&gt;GBLEzrvc8rnUFruVrCwm
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you try that, it will work. However &lt;strong&gt;it is a terrible idea to store our ssh passwords in that inventory file in plaintext.&lt;/strong&gt; They would be available to anyone who gets access to my workstation, AND when I commit my work to git, it&amp;rsquo;s getting copied somewhere, probably including github. This is such a common problem there&amp;rsquo;s &lt;a href="https://www.gitguardian.com/solutions/scan-github-for-passwords"&gt;some business&lt;/a&gt; that have come into being to scan for passwords and API keys in people&amp;rsquo;s repos.&lt;/p&gt;
&lt;p&gt;There &lt;em&gt;is&lt;/em&gt; a better way. Ansible will allow us to store the secrets in a separate file as variables, and that separate file can be encrypted while it&amp;rsquo;s on disk, and Ansible will decrypt it to use from memory then clean up after itself. There&amp;rsquo;s a couple of new (to us) things here - variables, and the encryption. Let&amp;rsquo;s look at them separately.&lt;/p&gt;
&lt;h3 id="variables"&gt;Variables&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;[Ansible variables](https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_variables.html)&lt;/code&gt; is a whole subject, we&amp;rsquo;re just going to look at the minimum we need to solve out problem.&lt;/p&gt;
&lt;p&gt;We can create another file in our project, let&amp;rsquo;s call it plaintext.yaml and store our usernames and passwords in there as key: value pairs.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-07-06-at-11.43.01-am.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Then we need to tell our playbook to import that &lt;code&gt;plaintext.yaml&lt;/code&gt; file with &lt;code&gt;vars_files&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-07-06-at-11.53.25-am.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Then in the inventory file, we can substitute the usernames and passwords with our variables.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-07-06-at-11.58.55-am.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Now, when the playbook runs, it will substitute the real values into the &lt;code&gt;host&lt;/code&gt; inventory file for us. Let&amp;rsquo;s check that.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-07-06-at-12.03.09-pm.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Bingo bongo. But we haven&amp;rsquo;t actually solved our security problem yet. The ssh passwords are still dangerously stored in plaintext in our file system. What we have done is learned how to have variables in an external file, pull that into the playbook and have the values substituted in. Now we need the next step - keeping those passwords safe.&lt;/p&gt;
&lt;h3 id="ansible-vault"&gt;Ansible Vault&lt;/h3&gt;
&lt;p&gt;Clearly, every serious use of Ansible is going to have this issue (of needing ssh credentials, but not wanting to give them away to hackers) so of course, there is an elegant solution for it.&lt;/p&gt;
&lt;p&gt;What if the file with all the passwords was stored encrypted, then only decrypted for use by our playbook, and it was never saved anywhere as plaintext? That solves the problem.&lt;/p&gt;
&lt;p&gt;Ansible has a tool for this called &lt;a href="https://docs.ansible.com/ansible/2.8/user_guide/vault.html"&gt;Ansible Vault&lt;/a&gt;. We&amp;rsquo;ll create the yaml file with our variables with that tool, and it will be saved encrypted. When we run the playbook we&amp;rsquo;ll get it to ask us for the password to decrypt the file. It will do that in memory and run the playbook.&lt;/p&gt;
&lt;p&gt;The command to create our file, which we&amp;rsquo;ll call &lt;code&gt;vault.yaml&lt;/code&gt; will be:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ansible-vault create vault.yaml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This will ask us to enter the password we want to use. The strength of this password needs to be good. If it&amp;rsquo;s crackable, you are giving away root access to your systems. And it&amp;rsquo;s in a file, not in a login situation where you can time out after three logins. Whoever has the file has the time to brute force password of the the &lt;a href="https://www.ipswitch.com/blog/use-aes-256-encryption-secure-data"&gt;AES 256&lt;/a&gt; encryption.&lt;/p&gt;
&lt;img src="https://blog.iankulin.com/images/h4c7m5z2a2b71-copy.jpg" width="460" alt=""&gt;
&lt;p&gt;Once you&amp;rsquo;ve entered your strong password twice, it will open up the new file in the default editor - probably vim. You may need help to use this editor.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-07-06-at-12.46.35-pm.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;When you&amp;rsquo;re done, save the file and exit. What does this file look like:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-07-06-at-12.51.38-pm.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Yep. That should do it. We still need to tell our playbook to use this file instead of the other one.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1"&gt;---&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1"&gt;-&lt;/span&gt; name&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; nginx &lt;span style="color:#81a1c1;font-weight:bold"&gt;for&lt;/span&gt; all web servers
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; vars_files&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;./&lt;/span&gt;vault&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;yaml
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; hosts&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; all
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; become&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; yes
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; tasks&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1"&gt;-&lt;/span&gt; name&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; nginx installed
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; apt&lt;span style="color:#eceff4"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; name&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; nginx
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; state&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; latest
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1"&gt;-&lt;/span&gt; name&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; nginx running
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; service&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; name&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; nginx
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; state&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; started
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; enabled&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; yes
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And when we run the playbook, we need to let it know to ask us the vault password.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ansible-playbook web_installs.yaml --ask-vault-pass
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-07-06-at-1.00.16-pm.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;If you need to edit the secrets file in the future, the command for that would be&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ansible-vault edit vault.yaml&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Once again it will ask the password, and once again it will open up in vim.&lt;/p&gt;</description></item><item><title>SSH with Keys to Synology</title><link>https://blog.iankulin.com/ssh-with-keys-to-synology/</link><pubDate>Mon, 27 Mar 2023 00:00:00 +0000</pubDate><guid>https://blog.iankulin.com/ssh-with-keys-to-synology/</guid><description>&lt;p&gt;The Synology operating system DSM (I&amp;rsquo;m on DSM 7.1.1) is Linux, but its highly customised for the purpose of making running a complicated Linux NAS doable for less technical users.&lt;/p&gt;
&lt;p&gt;Due to that, some things that are routine in a regular distro, require a few more steps to jump through to get them to work. SSH-ing in to a Synology with keys is one of those things.&lt;/p&gt;
&lt;h3 id="should-you"&gt;Should you?&lt;/h3&gt;
&lt;p&gt;Before you do start fiddling around, it&amp;rsquo;s probably worth mentioning that almost all the things you might want to do on the Synology can be accomplished through their web interface, or by installing a &amp;lsquo;package&amp;rsquo; from the &lt;em&gt;Package Center&lt;/em&gt;. For example, if you need to run a cron job, that&amp;rsquo;s done through the &lt;em&gt;Control Panel&lt;/em&gt; &amp;lsquo;&lt;em&gt;Task Scheduler&lt;/em&gt;&amp;rsquo;. If you need TailScale installed to easily access it over Wireguard, there&amp;rsquo;s a TailScale package. In general it&amp;rsquo;s probably easier and safer to do things their way.&lt;/p&gt;
&lt;h3 id="enabling-ssh"&gt;Enabling SSH&lt;/h3&gt;
&lt;p&gt;Before you can SSH into the Synology, you need to enable the SSH service. This is straightforward with the web interface. In &lt;em&gt;Control Panel&lt;/em&gt;, look for &lt;em&gt;Terminal &amp;amp; SMNP&lt;/em&gt; and tick the box, and click &lt;em&gt;Apply&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-03-25-at-6.01.35-pm.png" alt=""&gt;&lt;/p&gt;
&lt;h3 id="home-directory"&gt;Home directory&lt;/h3&gt;
&lt;p&gt;If you SSH to the Synology now, it works, but you&amp;rsquo;ll notice that there&amp;rsquo;s a warning message saying &amp;ldquo;Could not chdir to home directory /var/services/homes/&lt;user name&gt;: No such file or directory&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-03-25-at-7.12.36-pm.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;The reason for this is that unlike most distros, when you create a user in DSM, there&amp;rsquo;s no home directory created for them. There must be some bash config somewhere since I get that nice prompt, but no user home directory.&lt;/p&gt;
&lt;p&gt;Lot&amp;rsquo;s of times, you could just ignore that warning, you can still probably do what you wanted to, but it is going to be an issue for installing SSH keys - when you do the &lt;code&gt;ssh-copy-id&lt;/code&gt; it will want to create a .ssh file in the user&amp;rsquo;s home directory, and if they haven&amp;rsquo;t got one, that is not going to work. You&amp;rsquo;ll get a similar sort of error saying something like&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;sh: line 0: cd: /var/services/homes/&amp;lt;user_name&amp;gt;: No such file or directory mkdir: cannot create directory '.ssh': Permission denied&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Again, there&amp;rsquo;s a setting in the web interface to create home directories for the users. We&amp;rsquo;re in the &lt;em&gt;Control Panel&lt;/em&gt; again, but this time look for &lt;em&gt;User &amp;amp; Group&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-03-25-at-6.20.35-pm.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Tick the box for &lt;em&gt;Enable user home service&lt;/em&gt;, and hit &lt;em&gt;Apply&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Now you&amp;rsquo;ll be able to copy the keys as usual with ssh-copy-id.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.iankulin.com/images/screen-shot-2023-03-25-at-7.25.59-pm.png"&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-03-25-at-7.25.59-pm.png" width="1000" alt=""&gt;&lt;/a&gt;&lt;/p&gt;</description></item><item><title>ssh key login on VPS</title><link>https://blog.iankulin.com/ssh-key-login-on-vps/</link><pubDate>Sun, 12 Feb 2023 00:00:00 +0000</pubDate><guid>https://blog.iankulin.com/ssh-key-login-on-vps/</guid><description>&lt;p&gt;Due to &lt;a href="https://blog.iankulin.com/chinese-hackers-want-to-steal-my-hello-world-container/"&gt;potential brute force attacks&lt;/a&gt;, it&amp;rsquo;s a good idea to turn off password access via shh and instead rely on ssh keys. In this post, I&amp;rsquo;ll run through that process.&lt;/p&gt;
&lt;h4 id="generating-your-key"&gt;Generating your key&lt;/h4&gt;
&lt;p&gt;On a mac (or actually most *ix systems), your ssh keys live in the &lt;code&gt;.ssh&lt;/code&gt; directory inside the users home directory. Since it starts with a period, it&amp;rsquo;s a &amp;lsquo;hidden&amp;rsquo; directory. To see it in Finder press&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Shift|Command|.&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;(that command includes the full stop). Here&amp;rsquo;s mine:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-01-31-at-6.05.49-pm.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;The keys are in pairs, there are two pairs of keys above: id_ecdsa and id_rsa. Each pair of keys includes a public key and a private key. It&amp;rsquo;s the public key we want to put on the server. The private key is precious - it should not be anywhere that others can access it. The public key can safely be provided to a server that can use it to securely authenticate the holder of the private key by doing some complicated stuff.&lt;/p&gt;
&lt;p&gt;If you don&amp;rsquo;t already have a key pair, we need to create one. On Mac or Linux that is a &lt;a href="https://www.makeuseof.com/ssh-keygen-mac/"&gt;straightforward process in a terminal&lt;/a&gt;, on Windows I think the recommendation is usually to use &lt;a href="https://www.ssh.com/academy/ssh/putty/windows/puttygen"&gt;PuTTY&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id="installing-your-key-on-the-target-system"&gt;Installing your key on the target system&lt;/h4&gt;
&lt;p&gt;It&amp;rsquo;s possible to create a file on the system we want to ssh onto and to paste the public key into in, but from a Mac or Linux machine, we can use the &lt;code&gt;ssh-copy-id&lt;/code&gt; command which will do all that for us in an error-free way. It has the format:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ssh-copy-id &amp;lt;username&amp;gt;@&amp;lt;host&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a href="https://blog.iankulin.com/images/screen-shot-2023-02-04-at-1.51.49-pm.png"&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-02-04-at-1.51.49-pm.png" width="800" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4 id="turning-off-password-access"&gt;Turning off password access&lt;/h4&gt;
&lt;p&gt;Although it&amp;rsquo;s convenient to ssh in without a password (because we&amp;rsquo;re using keys), the main reason for doing this is to turn off passwords to make brute-force password attacks impotent. For that, we need to turn off passwords for &lt;code&gt;ssh&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Note that I&amp;rsquo;m running on Unbuntu server 22.x so your mileage may vary. Certainly when I was reading around about this I found many slightly different approaches, but this is what I&amp;rsquo;ve done and tested so that ssh refuses to accept passwords.&lt;/p&gt;
&lt;p&gt;The configuration files for ssh on Ubuntu are at /etc/ssh/&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.iankulin.com/images/screen-shot-2023-02-04-at-3.57.15-pm.png"&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-02-04-at-3.57.15-pm.png" width="800" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s the &lt;code&gt;sshd_config&lt;/code&gt; we&amp;rsquo;re interested in (&lt;code&gt;ssh_config&lt;/code&gt; is for the client, we&amp;rsquo;re wanting to change the ssh server - daemon). You&amp;rsquo;ll also notice there&amp;rsquo;s a &lt;code&gt;sshd_config.d&lt;/code&gt; directory. The reason for this is that the config file has a line in it at the top that includes all the config files in that directory. This is a common pattern in Unbuntu - the main config file pulls in other config files. When you see that, you really shouldn&amp;rsquo;t edit the main config file as it&amp;rsquo;s possible that a future update will change it, you edit, or add to the files in the directory below.&lt;/p&gt;
&lt;p&gt;The way it words is that the commands in the files in the sub-directory will have priority over the defaults in the main config file (which is slightly counter-intuitive for me).&lt;/p&gt;
&lt;p&gt;The VPS I am using is on &lt;a href="https://blog.iankulin.com/your-own-aussie-server-on-binarylane/"&gt;binarylane&lt;/a&gt;, and they already have a config file in the subdirectory, so I&amp;rsquo;ll edit that.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-02-04-at-4.08.24-pm.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;With a standard Unbuntu install, there are no files in there, so you&amp;rsquo;ll need to create one with &lt;code&gt;touch&lt;/code&gt;, then add the line &lt;code&gt;PasswordAuthentication no&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Many of the articles on the internet also talk about turning off &lt;code&gt;ChallengeResponseAuthentication&lt;/code&gt; and &lt;code&gt;UsePAM&lt;/code&gt;, but I found with my VPS and local Unbuntu servers, all that was needed was &lt;code&gt;PasswordAuthentication&lt;/code&gt; if my intention was to prevent these attacks.&lt;/p&gt;
&lt;p&gt;Note that once this config is activated, you won&amp;rsquo;t be able to log in via ssh with a password, so it would be foolhardy to do it without having set up &lt;em&gt;and&lt;/em&gt; tested your login with keys.&lt;/p&gt;
&lt;p&gt;This config won&amp;rsquo;t be active until the ssh daemon is restarted.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo systemctl reload ssh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now if someone attempts to ssh in they&amp;rsquo;ll see this:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-02-04-at-4.16.37-pm.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Not that turning off passwords like this is only for ssh. You&amp;rsquo;ll still be able to log in via the console if you&amp;rsquo;ve stuffed something up.&lt;/p&gt;</description></item><item><title>SSH &amp; the scary warning</title><link>https://blog.iankulin.com/ssh-the-scary-warning/</link><pubDate>Wed, 08 Feb 2023 00:00:00 +0000</pubDate><guid>https://blog.iankulin.com/ssh-the-scary-warning/</guid><description>&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-01-28-at-8.41.11-pm.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;The first time you connect to a new server with ssh, it asks you something like:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜ ~ &amp;gt; ssh ian@192.168.100.20 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;The authenticity of host &amp;#39;192.168.100.20 (192.168.100.20)&amp;#39; can&amp;#39;t be established.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ED25519 key fingerprint is SHA256:ZcNTcOjO/0fOLC5iNChf8Q8MHN7z2d+VV0qz7XqH1g4.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;This key is not known by any other names
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Warning: Permanently added &amp;#39;192.168.100.20&amp;#39; (ED25519) to the list of known hosts.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once you&amp;rsquo;ve said yes, it adds the server &amp;lsquo;fingerprint&amp;rsquo; to the known hosts file, then next time you ssh there, it feels safe - we know this server.&lt;/p&gt;
&lt;p&gt;But&amp;hellip;. if you&amp;rsquo;re playing around with virtual machines. Loading them, booting them, rebuilding them, cloning them etc. You might try and connect to a VM which is a different one from before, but which has the same ip address. SSH will not be happy:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜ ~ &amp;gt; ssh ian@192.168.100.20
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Someone could be eavesdropping on you right now (man-in-the-middle attack)!
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;It is also possible that a host key has just been changed.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;The fingerprint for the ED25519 key sent by the remote host is
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;SHA256:ZcNTcOjO/0fOLC5iNChf8Q8MHN7z2d+VV0qz7XqH1g4.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Please contact your system administrator.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Add correct host key in /Users/user/.ssh/known_hosts to get rid of this message.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Offending ECDSA key in /Users/user/.ssh/known_hosts:9
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Host key for 192.168.100.20 has changed and you have requested strict checking.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Host key verification failed.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It is right to be suspicious. From its point of view, it goes to Joe&amp;rsquo;s house each day, and it&amp;rsquo;s always Joe who answers the door. Today, it&amp;rsquo;s someone completely different but who says they are Joe. But since we know this is a different server, this is an expected result, so I&amp;rsquo;d like to ignore it.&lt;/p&gt;
&lt;p&gt;Although the message says to add the new fingerprint to the known_hosts file, it&amp;rsquo;s easier just to delete the old ones. Then when I try to connect to this server again, it will think it&amp;rsquo;s a new one and ask me to accept it. To delete this ip address (or hostname) out of the known hosts file, I just need to:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜ ~ &amp;gt; ssh-keygen -R 192.168.100.20
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# Host 192.168.100.20 found: line 7
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# Host 192.168.100.20 found: line 8
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# Host 192.168.100.20 found: line 9
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/Users/user/.ssh/known_hosts updated.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And we&amp;rsquo;re good to go again. But thank you ssh for being so careful.&lt;/p&gt;</description></item><item><title>Chinese Hackers Want to steal my Hello World container</title><link>https://blog.iankulin.com/chinese-hackers-want-to-steal-my-hello-world-container/</link><pubDate>Mon, 06 Feb 2023 00:00:00 +0000</pubDate><guid>https://blog.iankulin.com/chinese-hackers-want-to-steal-my-hello-world-container/</guid><description>&lt;p&gt;A smart thing to do after setting up a server on the internet, is to set up SSH keys and then turn passwords off for SSH. The reason for this is that scanning for open port 22 on IP addresses, then brute forcing password files on them is pretty much hacker 101. So if you have passwords turned on, and especially if you have a weak password you are really inviting someone to take over your server as root and add it to their botnet army for liking Putin&amp;rsquo;s twitter posts or whatever.&lt;/p&gt;
&lt;p&gt;When I was writing &lt;a href="https://blog.iankulin.com/sudo-incident-reports-where-do-they-go/"&gt;the post about looking for the sudo attempt&lt;/a&gt; &amp;lsquo;report&amp;rsquo;, you might have noticed some sshd timeouts:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-01-28-at-12.08.21-pm.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s what&amp;rsquo;s going on there. SSH has a timeout value of about a minute. I&amp;rsquo;d also guess those kex_exchange_identification messages are suspicious as well. I thought I&amp;rsquo;d google one of the IP addreses:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.iankulin.com/images/screen-shot-2023-01-28-at-12.18.14-pm.png"&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-01-28-at-12.18.14-pm.png" width="895" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Oh, so it&amp;rsquo;s China, and multiple people are reporting SSH brute force attacks:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-01-28-at-12.20.35-pm.jpg" alt=""&gt;&lt;/p&gt;</description></item></channel></rss>