245 lines
52 KiB
HTML
245 lines
52 KiB
HTML
<!doctype html><html lang=en dir=auto><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"><meta name=robots content="index, follow"><title>Securing SSH 🤖 | ahmza's ramblings</title>
|
||||
|
|
<meta name=keywords content="HomeLab,SSH,RemoteAccess"><meta name=description content="Ever wanted to make your SSH connections more secure. Read this"><meta name=author content="ahmza"><link rel=canonical href=https://blog.ahmza.com/Page%28/posts/securing-ssh.md%29><link crossorigin=anonymous href=/assets/css/stylesheet.49e35863ac4b53ab71c7e3249dd5e722c701ee07f8d0cb006a4f4e954364b6fe.css integrity="sha256-SeNYY6xLU6txx+MkndXnIscB7gf40MsAak9OlUNktv4=" rel="preload stylesheet" as=style><script defer crossorigin=anonymous src=/assets/js/highlight.f413e19d0714851f6474e7ee9632408e58ac146fbdbe62747134bea2fa3415e0.js integrity="sha256-9BPhnQcUhR9kdOfuljJAjlisFG+9vmJ0cTS+ovo0FeA=" onload=hljs.initHighlightingOnLoad()></script><link rel=icon href=https://blog.ahmza.com/img/favicon.png><link rel=icon type=image/png sizes=16x16 href=https://blog.ahmza.com/img/favicon.png><link rel=icon type=image/png sizes=32x32 href=https://blog.ahmza.com/img/favicon.png><link rel=apple-touch-icon href=https://blog.ahmza.com/img/favicon.png><link rel=mask-icon href=https://blog.ahmza.com/img/favicon.png><meta name=theme-color content="#2e2e33"><meta name=msapplication-TileColor content="#2e2e33"><noscript><style>#theme-toggle,.top-link{display:none}</style></noscript><script async src="https://www.googletagmanager.com/gtag/js?id=G-HSJHLHP8FZ"></script><script>var doNotTrack=!1;if(!doNotTrack){window.dataLayer=window.dataLayer||[];function gtag(){dataLayer.push(arguments)}gtag("js",new Date),gtag("config","G-HSJHLHP8FZ",{anonymize_ip:!1})}</script><meta property="og:title" content="Securing SSH 🤖"><meta property="og:description" content="Ever wanted to make your SSH connections more secure. Read this"><meta property="og:type" content="article"><meta property="og:url" content="https://blog.ahmza.com/posts/securing-ssh/"><meta property="og:image" content="https://blog.ahmza.com/webp/posts/secure-ssh/feature-anim.webp"><meta property="article:section" content="posts"><meta property="article:published_time" content="2021-12-07T22:41:02+00:00"><meta property="article:modified_time" content="2021-12-07T22:41:02+00:00"><meta property="og:site_name" content="ahmza's ramblings"><meta name=twitter:card content="summary_large_image"><meta name=twitter:image content="https://blog.ahmza.com/webp/posts/secure-ssh/feature-anim.webp"><meta name=twitter:title content="Securing SSH 🤖"><meta name=twitter:description content="Ever wanted to make your SSH connections more secure. Read this"><script type=application/ld+json>{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":2,"name":"Posts","item":"https://blog.ahmza.com/posts/"},{"@type":"ListItem","position":3,"name":"Securing SSH 🤖","item":"https://blog.ahmza.com/posts/securing-ssh/"}]}</script><script type=application/ld+json>{"@context":"https://schema.org","@type":"BlogPosting","headline":"Securing SSH 🤖","name":"Securing SSH 🤖","description":"Ever wanted to make your SSH connections more secure. Read this","keywords":["HomeLab","SSH","RemoteAccess"],"articleBody":"Introduction SSH is a widely used protocol to access remote devices. The problem with SSH is at the authentication stage, Brute force attacks are one of the ways an SSH connection can be compromised. A malicious actor will constantly hammer the remote host with different passwords until it can gain access. With further configuration of SSH we can make the service a lot more secure.\nConfigure SSH Famous last words: Configuring SSH like many things in Linux is as simple as editing a few config files\nAlways be sure to create a backup file it’s very easy to end up locking yourself out of a device.\nI would recommend practising on a machine that is not critical.\nCreate SSH Keys SSH keys use public and private key encryption for authentication.\nTo create a set of keys, on the client do:\nssh-keygen You will be asked where you want to save the keys, I recommend the default location for less hair pulling later.\nEnter file in which to save the key (/home/user/.ssh/id_rsa): You will
|
|||
|
|
with SSH is at the authentication stage, Brute force attacks are one of
|
|||
|
|
the ways an SSH connection can be compromised. A malicious actor will
|
|||
|
|
constantly hammer the remote host with different passwords until it can
|
|||
|
|
gain access. With further configuration of SSH we can make the service
|
|||
|
|
a lot more secure.</p><h1 id=configure-ssh><strong>Configure SSH</strong><a hidden class=anchor aria-hidden=true href=#configure-ssh>#</a></h1><video autoplay loop muted playsinline aria-label='this is fine' style=display:block;margin-left:auto;margin-right:auto;width:50%;height:auto;padding:10px>
|
|||
|
|
<source src=/webm/this-is-fine.webm type=video/webm></video><blockquote><p><strong>Famous last words:</strong> Configuring SSH like many things in Linux is
|
|||
|
|
as simple as editing a few config files</p></blockquote><p>Always be sure to <strong>create a backup file</strong> it’s very easy to end up
|
|||
|
|
locking yourself out of a device.</p><p>I would recommend practising on a machine that is not critical.</p><h2 id=create-ssh-keys><strong>Create SSH Keys</strong><a hidden class=anchor aria-hidden=true href=#create-ssh-keys>#</a></h2><p>SSH keys use public and private key encryption for authentication.</p><p>To create a set of keys, <strong>on the client do:</strong></p><div class=highlight><pre tabindex=0 class=chroma><code class=language-bash data-lang=bash><span class=line><span class=cl>ssh-keygen
|
|||
|
|
</span></span></code></pre></div><p>You will be asked where you want to save the keys, <strong>I recommend the<br>default location</strong> for less hair pulling later.</p><div class=highlight><pre tabindex=0 class=chroma><code class=language-bash data-lang=bash><span class=line><span class=cl>Enter file in which to save the key <span class=o>(</span>/home/user/.ssh/id_rsa<span class=o>)</span>:
|
|||
|
|
</span></span></code></pre></div><p>You will be asked to enter a password for the ssh keys, be sure to use
|
|||
|
|
a strong password.</p><div class=highlight><pre tabindex=0 class=chroma><code class=language-bash data-lang=bash><span class=line><span class=cl>Enter passphrase <span class=o>(</span>empty <span class=k>for</span> no passphrase<span class=o>)</span>:
|
|||
|
|
</span></span></code></pre></div><p>Once that is done you will see a confirmation screen like the one below</p><div class=highlight><pre tabindex=0 class=chroma><code class=language-fallback data-lang=fallback><span class=line><span class=cl>Output
|
|||
|
|
</span></span><span class=line><span class=cl>Your identification has been saved in /home/user/.ssh/id_rsa
|
|||
|
|
</span></span><span class=line><span class=cl>Your public key has been saved in /home/user/.ssh/id_rsa.pub
|
|||
|
|
</span></span><span class=line><span class=cl>The key fingerprint is:
|
|||
|
|
</span></span><span class=line><span class=cl>SHA256:tIurljnWJRBc1RnHUJQ5GtND7p9HWKnjV6zjE9AFR1Y user@host
|
|||
|
|
</span></span><span class=line><span class=cl>The key's randomart image is:
|
|||
|
|
</span></span><span class=line><span class=cl>+---[RSA 3072]----+
|
|||
|
|
</span></span><span class=line><span class=cl>| . .....oX=o.oE|
|
|||
|
|
</span></span><span class=line><span class=cl>| o =oB oo|
|
|||
|
|
</span></span><span class=line><span class=cl>| . . +.+ o.|
|
|||
|
|
</span></span><span class=line><span class=cl>| . . .... o+ |
|
|||
|
|
</span></span><span class=line><span class=cl>| . S .+. +|
|
|||
|
|
</span></span><span class=line><span class=cl>| .... ..o+.|
|
|||
|
|
</span></span><span class=line><span class=cl>| +.o. .=o.|
|
|||
|
|
</span></span><span class=line><span class=cl>| * .. .oo |
|
|||
|
|
</span></span><span class=line><span class=cl>| o.o. .. |
|
|||
|
|
</span></span><span class=line><span class=cl>+----[SHA256]-----+
|
|||
|
|
</span></span></code></pre></div><h2 id=copy-ssh-keys><strong>Copy SSH Keys</strong><a hidden class=anchor aria-hidden=true href=#copy-ssh-keys>#</a></h2><blockquote><p><strong>Quick note:</strong> user@host is the <strong>username</strong> on the <strong>remeote host</strong>
|
|||
|
|
you would like to copy your public key to.</p></blockquote><div class=highlight><pre tabindex=0 class=chroma><code class=language-bash data-lang=bash><span class=line><span class=cl>ssh-copy-id user@host
|
|||
|
|
</span></span></code></pre></div><p><strong>If asked to confirm the connection to the remote host answer yes</strong>, this
|
|||
|
|
happens when a new machine with an unknown identity wants to connect to
|
|||
|
|
the client.</p><div class=highlight><pre tabindex=0 class=chroma><code class=language-fallback data-lang=fallback><span class=line><span class=cl>Output
|
|||
|
|
</span></span><span class=line><span class=cl>The authenticity of host 'host(host)' can't be established.
|
|||
|
|
</span></span><span class=line><span class=cl>ECDSA key fingerprint is xx:xx:xx:xx:xx:xx:xx:xx.
|
|||
|
|
</span></span><span class=line><span class=cl>Are you sure you want to continue connecting (yes/no)? yes
|
|||
|
|
</span></span></code></pre></div><p>You will then be asked to <strong>enter a password</strong> for the user on the remote
|
|||
|
|
host</p><div class=highlight><pre tabindex=0 class=chroma><code class=language-fallback data-lang=fallback><span class=line><span class=cl>Output
|
|||
|
|
</span></span><span class=line><span class=cl>/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
|
|||
|
|
</span></span><span class=line><span class=cl>/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
|
|||
|
|
</span></span><span class=line><span class=cl>user@host's password:
|
|||
|
|
</span></span></code></pre></div><p>If successful you should be able to access the device using the SSH key</p><p>To verify this, SSH to the device and <strong>it should ask for the Keys’s
|
|||
|
|
password not the users</strong></p><div class=highlight><pre tabindex=0 class=chroma><code class=language-bash data-lang=bash><span class=line><span class=cl>Enter passphrase <span class=k>for</span> key <span class=s1>'/home/user/.ssh/id_rsa'</span>:
|
|||
|
|
</span></span></code></pre></div><h2 id=modify-ssh-config><strong>Modify SSH Config</strong><a hidden class=anchor aria-hidden=true href=#modify-ssh-config>#</a></h2><p>create a backup</p><div class=highlight><pre tabindex=0 class=chroma><code class=language-bash data-lang=bash><span class=line><span class=cl>sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
|
|||
|
|
</span></span></code></pre></div><p>open the original file in a text editor</p><div class=highlight><pre tabindex=0 class=chroma><code class=language-bash data-lang=bash><span class=line><span class=cl>sudo vim /etc/ssh/sshd_config
|
|||
|
|
</span></span></code></pre></div><p>For a new user this might be daunting. Take your time and you will be
|
|||
|
|
fine 😊</p><video autoplay loop muted playsinline aria-label='thats a big one' style=display:block;margin-left:auto;margin-right:auto;width:50%;height:auto;padding:10px>
|
|||
|
|
<source src=/webm/thats-a-big-one.webm type=video/webm></video><p><strong>Lines we want to modify</strong></p><blockquote><p><strong>Quick note:</strong> you may need to uncomment some lines as well as add a
|
|||
|
|
few</p></blockquote><ul><li>Protocol 2 - add to line 15</li><li>Port 2222 - modify line 17</li><li>PermitRootLogin no - modify line 36</li><li>Max Auth Tries 5 - modify line 38</li><li>PasswordAuthentication no - modify line 60</li><li>PermitEmptyPasswords no -modify line 61</li><li>AllowUsers ahmza - add line 67</li><li>ClientAliveInterval 180 - modify line 104</li></ul><div class=highlight><pre tabindex=0 class=chroma><code class=language-gdscript3 data-lang=gdscript3><span class=line><span class=cl><span class=c1># $OpenBSD: sshd_config,v 1.103 2018/04/09 20:41:22 tj Exp $</span>
|
|||
|
|
</span></span><span class=line><span class=cl>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1># This is the sshd server system-wide configuration file. See</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1># sshd_config(5) for more information.</span>
|
|||
|
|
</span></span><span class=line><span class=cl>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1># This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin</span>
|
|||
|
|
</span></span><span class=line><span class=cl>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1># The strategy used for options in the default sshd_config shipped with</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1># OpenSSH is to specify options with their default value where</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1># possible, but leave them commented. Uncommented options override the</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1># default value.</span>
|
|||
|
|
</span></span><span class=line><span class=cl>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=n>Include</span> <span class=o>/</span><span class=n>etc</span><span class=o>/</span><span class=n>ssh</span><span class=o>/</span><span class=n>sshd_config</span><span class=o>.</span><span class=n>d</span><span class=o>/*.</span><span class=n>conf</span>
|
|||
|
|
</span></span><span class=line><span class=cl>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=n>Protocol</span> <span class=mi>2</span>
|
|||
|
|
</span></span><span class=line><span class=cl>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=n>Port</span> <span class=mi>2222</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#AddressFamily any</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#ListenAddress 0.0.0.0</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#ListenAddress ::</span>
|
|||
|
|
</span></span><span class=line><span class=cl>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#HostKey /etc/ssh/ssh_host_rsa_key</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#HostKey /etc/ssh/ssh_host_ecdsa_key</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#HostKey /etc/ssh/ssh_host_ed25519_key</span>
|
|||
|
|
</span></span><span class=line><span class=cl>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1># Ciphers and keying</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#RekeyLimit default none</span>
|
|||
|
|
</span></span><span class=line><span class=cl>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1># Logging</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#SyslogFacility AUTH</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#LogLevel INFO</span>
|
|||
|
|
</span></span><span class=line><span class=cl>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1># Authentication:</span>
|
|||
|
|
</span></span><span class=line><span class=cl>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#LoginGraceTime 2m</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=n>PermitRootLogin</span> <span class=n>no</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#StrictModes yes</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=n>MaxAuthTries</span> <span class=mi>5</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#MaxSessions 10</span>
|
|||
|
|
</span></span><span class=line><span class=cl>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#PubkeyAuthentication yes</span>
|
|||
|
|
</span></span><span class=line><span class=cl>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1># Expect .ssh/authorized_keys2 to be disregarded by default in future.</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#AuthorizedKeysFile .ssh/authorized_keys .ssh/authorized_keys2</span>
|
|||
|
|
</span></span><span class=line><span class=cl>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#AuthorizedPrincipalsFile none</span>
|
|||
|
|
</span></span><span class=line><span class=cl>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#AuthorizedKeysCommand none</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#AuthorizedKeysCommandUser nobody</span>
|
|||
|
|
</span></span><span class=line><span class=cl>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1># For this to work you will also need host keys in /etc/ssh/ssh_known_hosts</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#HostbasedAuthentication no</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1># Change to yes if you don't trust ~/.ssh/known_hosts for</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1># HostbasedAuthentication</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#IgnoreUserKnownHosts no</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1># Don't read the user's ~/.rhosts and ~/.shosts files</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#IgnoreRhosts yes</span>
|
|||
|
|
</span></span><span class=line><span class=cl>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1># To disable tunneled clear text passwords, change to no here!</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=n>PasswordAuthentication</span> <span class=n>no</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=n>PermitEmptyPasswords</span> <span class=n>no</span>
|
|||
|
|
</span></span><span class=line><span class=cl>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=n>AllowUsers</span> <span class=n>ahmza</span>
|
|||
|
|
</span></span><span class=line><span class=cl>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1># Change to yes to enable challenge-response passwords (beware issues with</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1># some PAM modules and threads)</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=n>ChallengeResponseAuthentication</span> <span class=n>no</span>
|
|||
|
|
</span></span><span class=line><span class=cl>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1># Kerberos options</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#KerberosAuthentication no</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#KerberosOrLocalPasswd yes</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#KerberosTicketCleanup yes</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#KerberosGetAFSToken no</span>
|
|||
|
|
</span></span><span class=line><span class=cl>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1># GSSAPI options</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#GSSAPIAuthentication no</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#GSSAPICleanupCredentials yes</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#GSSAPIStrictAcceptorCheck yes</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#GSSAPIKeyExchange no</span>
|
|||
|
|
</span></span><span class=line><span class=cl>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1># Set this to 'yes' to enable PAM authentication, account processing,</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1># and session processing. If this is enabled, PAM authentication will</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1># be allowed through the ChallengeResponseAuthentication and</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1># PasswordAuthentication. Depending on your PAM configuration,</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1># PAM authentication via ChallengeResponseAuthentication may bypass</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1># the setting of "PermitRootLogin without-password".</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1># If you just want the PAM account and session checks to run without</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1># PAM authentication, then enable this but set PasswordAuthentication</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1># and ChallengeResponseAuthentication to 'no'.</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=n>UsePAM</span> <span class=n>yes</span>
|
|||
|
|
</span></span><span class=line><span class=cl>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#AllowAgentForwarding yes</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#AllowTcpForwarding yes</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#GatewayPorts no</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=n>X11Forwarding</span> <span class=n>yes</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#X11DisplayOffset 10</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#X11UseLocalhost yes</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#PermitTTY yes</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=n>PrintMotd</span> <span class=n>no</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#PrintLastLog yes</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#TCPKeepAlive yes</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#PermitUserEnvironment no</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#Compression delayed</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=n>ClientAliveInterval</span> <span class=mi>180</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#ClientAliveCountMax 3</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#UseDNS no</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#PidFile /var/run/sshd.pid</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#MaxStartups 10:30:100</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#PermitTunnel no</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#ChrootDirectory none</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#VersionAddendum none</span>
|
|||
|
|
</span></span><span class=line><span class=cl>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1># no default banner path</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#Banner none</span>
|
|||
|
|
</span></span><span class=line><span class=cl>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1># Allow client to pass locale environment variables</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=n>AcceptEnv</span> <span class=n>LANG</span> <span class=n>LC_</span><span class=o>*</span>
|
|||
|
|
</span></span><span class=line><span class=cl>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1># override default of no subsystems</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=n>Subsystem</span> <span class=n>sftp</span> <span class=o>/</span><span class=n>usr</span><span class=o>/</span><span class=n>lib</span><span class=o>/</span><span class=n>openssh</span><span class=o>/</span><span class=n>sftp</span><span class=o>-</span><span class=n>server</span>
|
|||
|
|
</span></span><span class=line><span class=cl>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1># Example of overriding settings on a per-user basis</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1>#Match User anoncvs</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1># X11Forwarding no</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1># AllowTcpForwarding no</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1># PermitTTY no</span>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=c1># ForceCommand cvs server</span>
|
|||
|
|
</span></span></code></pre></div><video autoplay loop muted playsinline aria-label='not so bad' style=display:block;margin-left:auto;margin-right:auto;width:50%;height:auto;padding:10px>
|
|||
|
|
<source src=/webm/wasnt-so-bad.webm type=video/webm></video><p><strong>Now lets explain what we just did</strong></p><ul><li><strong>Protocol 2</strong> - released in 2006, SSH2 introduced improved
|
|||
|
|
encryption algorithms.</li><li><strong>Port 2222</strong> - The port number can be whatever number you want.
|
|||
|
|
Choose something other than 22 this will help hide your device from malicious actors</li><li><strong>PermitRootLogin no</strong> - If the root account were to be compromised
|
|||
|
|
then the attacker has full control of the system so we stop it from being able to log in.</li><li><strong>MaxAuthTries 5</strong> - After 5 failed attempts the remote host blocks
|
|||
|
|
requests from that IP for a period of time.</li><li><strong>PasswordAuthentication no</strong> - We have the SSH key installed so we
|
|||
|
|
no longer need to have password authentication.</li><li><strong>PermitEmptyPasswords no</strong> - We don’t want to allow empty passwords
|
|||
|
|
to be used as authentication for obvious reasons.</li><li><strong>AllowUsers username</strong> - Add the usernames of users you want to be
|
|||
|
|
able to connect to the remote host and other users trying to connect
|
|||
|
|
will be dropped.</li><li><strong>Client Alive Interval 180</strong> - Drop the connection after a certain
|
|||
|
|
period of inactivity</li></ul><h2 id=check-were-able-to-connect><strong>Check were able to connect</strong><a hidden class=anchor aria-hidden=true href=#check-were-able-to-connect>#</a></h2><p>restart sshd service</p><div class=highlight><pre tabindex=0 class=chroma><code class=language-bash data-lang=bash><span class=line><span class=cl>sudo systemctl restart sshd
|
|||
|
|
</span></span></code></pre></div><p><strong>Keep the current SSH connection open</strong> and create a new session.</p><p>If you are able to connect to the remote hosts then you are all set. If
|
|||
|
|
not then you still have the initial connection to the remote host to
|
|||
|
|
roll back the changes and troubleshoot.</p><h1 id=success><strong>Success</strong><a hidden class=anchor aria-hidden=true href=#success>#</a></h1><video autoplay loop muted playsinline aria-label=clap style=display:block;margin-left:auto;margin-right:auto;width:50%;height:auto;padding:10px>
|
|||
|
|
<source src=/webm/clap.webm type=video/webm></video><h1 id=setting-up-fail2ban><strong>Setting up</strong> <em><strong>Fail2Ban</strong></em><a hidden class=anchor aria-hidden=true href=#setting-up-fail2ban>#</a></h1><p><em>Fail2Ban</em> is an intrusion prevention tool. Although we are slowing
|
|||
|
|
bots down with MaxAuthTries the attacker is still able to carry on
|
|||
|
|
brute forcing. Which is what Fail2Ban is for, it actually blocks the
|
|||
|
|
connections from that IP.</p><h2 id=install-fail2ban><strong>Install</strong> <em><strong>Fail2Ban</strong></em><a hidden class=anchor aria-hidden=true href=#install-fail2ban>#</a></h2><p><strong>We will install Fail2Ban on the remote host</strong>
|
|||
|
|
First upgrade any packages, then <strong>install</strong> <em><strong>Fail2Ban</strong></em></p><div class=highlight><pre tabindex=0 class=chroma><code class=language-bash data-lang=bash><span class=line><span class=cl>sudo apt update <span class=o>&&</span> sudo apt upgrade
|
|||
|
|
</span></span><span class=line><span class=cl>sudo apt install fail2ban
|
|||
|
|
</span></span></code></pre></div><p>Now we need to enable the service so it starts when the remote host
|
|||
|
|
starts</p><div class=highlight><pre tabindex=0 class=chroma><code class=language-bash data-lang=bash><span class=line><span class=cl>sudo systemctl <span class=nb>enable</span> --now fail2ban
|
|||
|
|
</span></span></code></pre></div><h2 id=configure-fail2ban><strong>Configure</strong> <em><strong>Fail2Ban</strong></em><a hidden class=anchor aria-hidden=true href=#configure-fail2ban>#</a></h2><p>The Fail2Ban config file we want to edit is called <strong>jail.local</strong> located in <strong>/etc/fail2ban/</strong>
|
|||
|
|
open jail.local in your editor of choice</p><div class=highlight><pre tabindex=0 class=chroma><code class=language-bash data-lang=bash><span class=line><span class=cl>sudo vim /etc/fail2ban/jail.local
|
|||
|
|
</span></span></code></pre></div><p>The config for <em>Fail2Ban</em> is a lot shorter than sshd so this should be
|
|||
|
|
quick</p><div class=highlight><pre tabindex=0 class=chroma><code class=language-gdscript3 data-lang=gdscript3><span class=line><span class=cl><span class=p>[</span><span class=n>DEFAULT</span><span class=p>]</span>
|
|||
|
|
</span></span><span class=line><span class=cl> <span class=n>bantime</span> <span class=o>=</span> <span class=mi>8</span><span class=n>h</span>
|
|||
|
|
</span></span><span class=line><span class=cl> <span class=n>ignoreip</span> <span class=o>=</span> <span class=mf>127.0</span><span class=o>.</span><span class=mf>0.1</span> <span class=o><</span><span class=n>ip</span> <span class=n>addresses</span> <span class=n>to</span> <span class=n>be</span> <span class=n>ignored</span><span class=o>></span>
|
|||
|
|
</span></span><span class=line><span class=cl> <span class=n>ignoreself</span> <span class=o>=</span> <span class=bp>true</span>
|
|||
|
|
</span></span><span class=line><span class=cl>
|
|||
|
|
</span></span><span class=line><span class=cl><span class=p>[</span><span class=n>sshd</span><span class=p>]</span>
|
|||
|
|
</span></span><span class=line><span class=cl> <span class=n>enabled</span> <span class=o>=</span> <span class=bp>true</span>
|
|||
|
|
</span></span><span class=line><span class=cl> <span class=n>port</span> <span class=o>=</span> <span class=mi>2222</span>
|
|||
|
|
</span></span><span class=line><span class=cl> <span class=n>filter</span> <span class=o>=</span> <span class=n>sshd</span>
|
|||
|
|
</span></span><span class=line><span class=cl> <span class=n>logpath</span> <span class=o>=</span> <span class=o>/</span><span class=k>var</span><span class=o>/</span><span class=nb>log</span><span class=o>/</span><span class=n>auth</span><span class=o>.</span><span class=n>log</span>
|
|||
|
|
</span></span><span class=line><span class=cl> <span class=n>maxretry</span> <span class=o>=</span> <span class=mi>3</span>
|
|||
|
|
</span></span><span class=line><span class=cl> <span class=n>findtime</span> <span class=o>=</span> <span class=mi>10</span><span class=n>m</span>
|
|||
|
|
</span></span></code></pre></div><p><strong>[Default]</strong> - Settings in here apply to all jails</p><ul><li><strong>bantime</strong> - how long the ban will last</li><li><strong>ignoreip</strong> - IP addresses to ignore</li><li><strong>ignoreself</strong> - stops from locking itself out</li></ul><p><strong>[sshd]</strong> - this is the jail for sshd</p><ul><li><strong>enabled</strong> - decides weather the jail is active or not</li><li><strong>port</strong> - the port number the service</li><li><strong>filter</strong> - tells the jail which filter to use from /etc/fail2ban/filter.d</li><li><strong>logpath</strong> - where the log you want fail2ban to read is</li><li><strong>maxretry</strong> - Times the client can attempt a login before being banned</li><li><strong>findtime</strong> - An amount of time which maxretry must occur to trigger a
|
|||
|
|
ban for example in 10 minutes if 3 failed login attempts are made the
|
|||
|
|
ban the IP</li></ul><p><strong>Restart</strong> <em><strong>Fail2Ban</strong></em> to load the configuration</p><div class=highlight><pre tabindex=0 class=chroma><code class=language-bash data-lang=bash><span class=line><span class=cl>sudo systemctl restart fail2ban
|
|||
|
|
</span></span></code></pre></div><h2 id=testing-fail2ban><strong>Testing</strong> <em><strong>Fail2Ban</strong></em><a hidden class=anchor aria-hidden=true href=#testing-fail2ban>#</a></h2><p>To test Fail2Ban lets create a test user and set a password for the
|
|||
|
|
user</p><div class=highlight><pre tabindex=0 class=chroma><code class=language-bash data-lang=bash><span class=line><span class=cl>sudo useradd <span class=nb>test</span>
|
|||
|
|
</span></span><span class=line><span class=cl>sudo passwd <span class=nb>test</span>
|
|||
|
|
</span></span></code></pre></div><p><strong>open the sshd config</strong></p><div class=highlight><pre tabindex=0 class=chroma><code class=language-bash data-lang=bash><span class=line><span class=cl>sudo vim /etc/ssh/sshd_config
|
|||
|
|
</span></span></code></pre></div><p>modify the line <strong>PasswordAuthentication</strong> to say <strong>yes</strong> and add the test user to <strong>AllowUsers</strong></p><div class=highlight><pre tabindex=0 class=chroma><code class=language-bash data-lang=bash><span class=line><span class=cl>PasswordAuthentication yes
|
|||
|
|
</span></span><span class=line><span class=cl>AllowUsers user <span class=nb>test</span>
|
|||
|
|
</span></span></code></pre></div><p><strong>restart the sshd service</strong></p><div class=highlight><pre tabindex=0 class=chroma><code class=language-bash data-lang=bash><span class=line><span class=cl>sudo systemctl restart sshd
|
|||
|
|
</span></span></code></pre></div><p>Attempt to login to the remote host using the test account using an
|
|||
|
|
incorrect password. After 3 failed attempts it should say connection
|
|||
|
|
refused.</p><div class=highlight><pre tabindex=0 class=chroma><code class=language-bash data-lang=bash><span class=line><span class=cl>ssh test@host -p <span class=m>2222</span>
|
|||
|
|
</span></span></code></pre></div><p><em>Fail2Ban</em> should do something along the lines of …
|
|||
|
|
<video autoplay loop muted playsinline aria-label='you shall not pass' style=display:block;margin-left:auto;margin-right:auto;width:50%;height:auto;padding:10px>
|
|||
|
|
<source src=/webm/you-shall-not-pass.webm type=video/webm></video></p><p>log back in as your normal user, remove the test user and restore the
|
|||
|
|
sshd config.</p><p><strong>To remove the user</strong></p><div class=highlight><pre tabindex=0 class=chroma><code class=language-bash data-lang=bash><span class=line><span class=cl>sudo userdel <span class=nb>test</span>
|
|||
|
|
</span></span></code></pre></div><p><strong>restore the /etc/ssh/sshd_config file</strong></p><div class=highlight><pre tabindex=0 class=chroma><code class=language-bash data-lang=bash><span class=line><span class=cl>sudo vim /etc/ssh/sshd_config
|
|||
|
|
</span></span></code></pre></div><p>Set <strong>PasswordAuthentication</strong> back to <strong>no</strong> and remove test from <strong>AllowUsers</strong></p><div class=highlight><pre tabindex=0 class=chroma><code class=language-bash data-lang=bash><span class=line><span class=cl>PasswordAuthentication no
|
|||
|
|
</span></span><span class=line><span class=cl>AllowUsers user
|
|||
|
|
</span></span></code></pre></div><h1 id=conclusion><strong>Conclusion</strong><a hidden class=anchor aria-hidden=true href=#conclusion>#</a></h1><p>well done, you managed to make it through all that !! At least now you
|
|||
|
|
can be reassured that if them pesky brute-force attackers decide to
|
|||
|
|
target your machine they wont have a fun time being in Jail 🤣 sorry
|
|||
|
|
bad joke.</p><p>By now you have managed to setup an ssh key for a client and copy it to
|
|||
|
|
a remote host, re-configure the sshd config to lockdown authentication
|
|||
|
|
and last but not least install and configure Fail2Ban to block pesky
|
|||
|
|
attackers.</p><video autoplay loop muted playsinline aria-label=proud style=display:block;margin-left:auto;margin-right:auto;width:50%;height:auto;padding:10px>
|
|||
|
|
<source src=/webm/proud.webm type=video/webm></video></div><footer class=post-footer><ul class=post-tags><li><a href=https://blog.ahmza.com/tags/homelab/>Homelab</a></li><li><a href=https://blog.ahmza.com/tags/ssh/>SSH</a></li><li><a href=https://blog.ahmza.com/tags/remoteaccess/>RemoteAccess</a></li></ul></footer></article></main><footer class=footer><span>© 2023 <a href=https://blog.ahmza.com>ahmza's ramblings</a></span>
|
|||
|
|
<span>Powered by
|
|||
|
|
<a href=https://gohugo.io/ rel="noopener noreferrer" target=_blank>Hugo</a> &
|
|||
|
|
<a href=https://github.com/adityatelange/hugo-PaperMod/ rel=noopener target=_blank>PaperMod</a></span></footer><a href=#top aria-label="go to top" title="Go to Top (Alt + G)" class=top-link id=top-link accesskey=g><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 6" fill="currentcolor"><path d="M12 6H0l6-6z"/></svg></a><script src=https://storage.ko-fi.com/cdn/scripts/overlay-widget.js></script><script>kofiWidgetOverlay.draw("ahmza",{type:"floating-chat","floating-chat.donateButton.text":"Tip","floating-chat.donateButton.background-color":"rgb(145, 70, 255)","floating-chat.donateButton.text-color":"#fff"})</script><script>let menu=document.getElementById("menu");menu&&(menu.scrollLeft=localStorage.getItem("menu-scroll-position"),menu.onscroll=function(){localStorage.setItem("menu-scroll-position",menu.scrollLeft)}),document.querySelectorAll('a[href^="#"]').forEach(e=>{e.addEventListener("click",function(e){e.preventDefault();var t=this.getAttribute("href").substr(1);window.matchMedia("(prefers-reduced-motion: reduce)").matches?document.querySelector(`[id='${decodeURIComponent(t)}']`).scrollIntoView():document.querySelector(`[id='${decodeURIComponent(t)}']`).scrollIntoView({behavior:"smooth"}),t==="top"?history.replaceState(null,null," "):history.pushState(null,null,`#${t}`)})})</script><script>var mybutton=document.getElementById("top-link");window.onscroll=function(){document.body.scrollTop>800||document.documentElement.scrollTop>800?(mybutton.style.visibility="visible",mybutton.style.opacity="1"):(mybutton.style.visibility="hidden",mybutton.style.opacity="0")}</script><script>document.getElementById("theme-toggle").addEventListener("click",()=>{document.body.className.includes("dark")?(document.body.classList.remove("dark"),localStorage.setItem("pref-theme","light")):(document.body.classList.add("dark"),localStorage.setItem("pref-theme","dark"))})</script><script>document.querySelectorAll("pre > code").forEach(e=>{const n=e.parentNode.parentNode,t=document.createElement("button");t.classList.add("copy-code"),t.innerHTML="copy";function s(){t.innerHTML="copied!",setTimeout(()=>{t.innerHTML="copy"},2e3)}t.addEventListener("click",t=>{if("clipboard"in navigator){navigator.clipboard.writeText(e.textContent),s();return}const n=document.createRange();n.selectNodeContents(e);const o=window.getSelection();o.removeAllRanges(),o.addRange(n);try{document.execCommand("copy"),s()}catch{}o.removeRange(n)}),n.classList.contains("highlight")?n.appendChild(t):n.parentNode.firstChild==n||(e.parentNode.parentNode.parentNode.parentNode.parentNode.nodeName=="TABLE"?e.parentNode.parentNode.parentNode.parentNode.parentNode.appendChild(t):e.parentNode.appendChild(t))})</script></body></html>
|