<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>The Wombelix Post - SSH</title><link href="https://dominik.wombacher.cc/" rel="alternate"/><link href="/feeds/tag_ssh.atom.xml" rel="self"/><id>https://dominik.wombacher.cc/</id><updated>2024-10-06T00:00:00+02:00</updated><entry><title>Access to SUSE Live Lab Environment through SSH reverse Tunnel and RDP</title><link href="https://dominik.wombacher.cc/posts/access-to-suse-live-lab-environment-through-ssh-reverse-tunnel-and-rdp.html" rel="alternate"/><published>2022-09-10T00:00:00+02:00</published><updated>2024-10-06T00:00:00+02:00</updated><author><name>Dominik Wombacher</name></author><id>tag:dominik.wombacher.cc,2022-09-10:/posts/access-to-suse-live-lab-environment-through-ssh-reverse-tunnel-and-rdp.html</id><summary type="html">&lt;!-- SPDX-FileCopyrightText: 2024 Dominik Wombacher &lt;dominik@wombacher.cc&gt; --&gt;
&lt;!--  --&gt;
&lt;!-- SPDX-License-Identifier: CC-BY-SA-4.0 --&gt;
&lt;p&gt;SUSE provides some great Training Courses with a lot of Exercises and Online Labs are also available for most of them.
But, at least in the Environment available to SUSE  ... &lt;a class="read-more" href="/posts/access-to-suse-live-lab-environment-through-ssh-reverse-tunnel-and-rdp.html"&gt; [read more]&lt;/a&gt;&lt;/p&gt;</summary><content type="html">&lt;!-- SPDX-FileCopyrightText: 2024 Dominik Wombacher &lt;dominik@wombacher.cc&gt; --&gt;
&lt;!--  --&gt;
&lt;!-- SPDX-License-Identifier: CC-BY-SA-4.0 --&gt;
&lt;p&gt;SUSE provides some great Training Courses with a lot of Exercises and Online Labs are also available for most of them.
But, at least in the Environment available to SUSE Partners, the Labs can only be accessed through a Browser,
with a fixed size of 1080x800, no support for Resize, Full-screen or Copy/Paste.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update 2024-10-06&lt;/strong&gt;: There is a new &lt;em&gt;Open in new window&lt;/em&gt; button available which allows higher resolutions than 1080x800 because it uses the full browser window. But all other limitations are the same since I wrote about it two years ago. Therefore I still prefer to reverse tunnel into the Lab machine and use an RDP client as explained in this post.&lt;/p&gt;
&lt;p&gt;The Tech Stack used to provide those access:
&lt;a class="reference external" href="https://github.com/hastexo/hastexo-xblock"&gt;hastexo XBlock&lt;/a&gt;
(Archive: &lt;a class="reference external" href="https://web.archive.org/web/20200914165434/https://github.com/hastexo/hastexo-xblock"&gt;[1]&lt;/a&gt;,
&lt;a class="reference external" href="https://archive.today/2022.09.10-092646/https://github.com/hastexo/hastexo-xblock"&gt;[2]&lt;/a&gt;),
&lt;a class="reference external" href="https://guacamole.apache.org"&gt;Apache Guacamole&lt;/a&gt;
(Archive: &lt;a class="reference external" href="https://web.archive.org/web/20220829145641/https://guacamole.apache.org/"&gt;[1]&lt;/a&gt;,
&lt;a class="reference external" href="https://archive.today/2020.06.25-070620/https://guacamole.apache.org/"&gt;[2]&lt;/a&gt;), and
&lt;a class="reference external" href="https://openedx.org"&gt;Open edX&lt;/a&gt;
(Archive: &lt;a class="reference external" href="https://web.archive.org/web/20220901141818/https://openedx.org/"&gt;[1]&lt;/a&gt;,
&lt;a class="reference external" href="https://archive.today/2022.04.01-170921/https://openedx.org/"&gt;[2]&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;As much I love the provided Trainings, that's just not really comfortable in my opinion.
It's fine for a few quick Exercises, but if you have some complex ones or do multiple hours of hands on Training,
a more direct way to connect, with support for Full-screen and Copy/Paste, would be way better.&lt;/p&gt;
&lt;p&gt;The alternative is to setup the Lab Environment locally, but that requires additional time and resources.&lt;/p&gt;
&lt;p&gt;SUSE Labs are based on a &lt;em&gt;main&lt;/em&gt; server, which runs all other virtual machines, relevant for the lab, via KVM.
You always access this main server and from there you can either use SSH or the
Virtual Machine Manager Console to connect to the other systems.&lt;/p&gt;
&lt;p&gt;The good thing, this &lt;em&gt;main&lt;/em&gt; server has full Internet Access via NAT (IPv4), we can establish outgoing connections
without restrictions and also have full root permissions. So by establishing a SSH Reverse Tunnel to a
public server, as rendezvous point, it's possible to access the Lab Server quite easy via RDP,
which is enabled by default, because of the used Tech Stack to provide Browser access.&lt;/p&gt;
&lt;pre class="code text literal-block"&gt;
-----------------------                                           ------------------------
| Local Workstation   |          -----------------------          | SUSE Live Lab Server |   ------------------------------
|                     | tcp/22 &amp;gt; | VPS (Public Server) | &amp;lt; tcp/22 |                      | &amp;gt; | Other Lab Virtual Machines |
| SSH Tunnel to VPS   |          -----------------------          | SSH Tunnel to VPS    |   ------------------------------
| Outgoing Connection |                                           | Outgoing Connection  |
-----------------------                                           ------------------------

    localhost:3389         &amp;gt;            SSH Tunnel            &amp;gt;        localhost:3389

&lt;/pre&gt;
&lt;p&gt;Steps:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Create VPS&lt;/li&gt;
&lt;/ol&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Any cheap Virtual Machine, for example &lt;a class="reference external" href="https://hetzner.cloud/?ref=9YU0qvtaSmQI"&gt;Hetzner Cloud (Referral Link)&lt;/a&gt;
with Public IPv4 address does the trick, you can also re-use any Server you might already have.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol class="arabic simple" start="2"&gt;
&lt;li&gt;Create additional User Account on the VPS used for SSH Tunneling&lt;/li&gt;
&lt;/ol&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;You have to type the User and Password into the SUSE Live Lab Server (no copy/paste),
so I picked something simple and didn't used my regular User for the tunneling, but it's up to you.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol class="arabic simple" start="3"&gt;
&lt;li&gt;Establish a SSH Reverse Tunnel from the Lab Server to the VPS and also from your local Workstation to the VPS&lt;/li&gt;
&lt;/ol&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;The commands used below are based on the Article
&lt;a class="reference external" href="https://www.sweetprocess.com/procedures/_AmM86Weq31FO0WDp5kRZFDBKRjB/ssh-tunnel-between-two-servers-behind-firewalls/"&gt;SSH tunnel between two servers behind firewalls&lt;/a&gt;
(Archive: &lt;a class="reference external" href="https://web.archive.org/web/20220910092054/https://www.sweetprocess.com/procedures/_AmM86Weq31FO0WDp5kRZFDBKRjB/ssh-tunnel-between-two-servers-behind-firewalls/"&gt;[1]&lt;/a&gt;,
&lt;a class="reference external" href="https://archive.today/2022.09.10-092054/https://www.sweetprocess.com/procedures/_AmM86Weq31FO0WDp5kRZFDBKRjB/ssh-tunnel-between-two-servers-behind-firewalls/"&gt;[2]&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;ol class="arabic simple" start="4"&gt;
&lt;li&gt;Connect via RDP&lt;/li&gt;
&lt;/ol&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;I'm running openSUSE Tumbleweed and use Remmina, any other Client with RDP support will work as well.&lt;/li&gt;
&lt;li&gt;It's a connection on your local Workstation to &lt;code&gt;localhost:3389&lt;/code&gt;,
which then goes through the established SSH Tunnel and hit Port 3389 (RDP) on the Lab Server.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;Commands:&lt;/p&gt;
&lt;pre class="code text literal-block"&gt;
# VPS (Hetzner Cloud, CX11, Falkenstein Germany, 0.0071 € / hour, Rocky Linux 9)
useradd -c &amp;quot;SSH Tunnel&amp;quot; -m -U sshtunnel
passwd sshtunnel

# SUSE Live Lab Server
ssh -o TCPKeepAlive=no -o ServerAliveInterval=15 -nNT -R 3389:localhost:3389 sshtunnel&amp;#64;&amp;lt;vps-public-ip&amp;gt;

# Local Workstation
ssh -o TCPKeepAlive=no -o ServerAliveInterval=15 -nNT -L 3389:localhost:3389 sshtunnel&amp;#64;&amp;lt;vps-public-ip&amp;gt;

# Lab Server
# The password for user &amp;quot;tux&amp;quot; is unknown so you have to reset it
sudo su -
passwd tux

# Local Workstation
# Open an RDP Client, connect to localhost as user &amp;quot;tux&amp;quot; with the password you set earlier on the Lab Server

&lt;/pre&gt;
&lt;p&gt;Important:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;1) Leave the Web Browser with the Live Lab HTML Viewer open, if you close it the VM will be suspended,
keep an eye on it, move the mouse from time to time when the windows is active or click the confirmation
that you still want to keep the VM running when you are inactive for a while.&lt;/p&gt;
&lt;p&gt;2) This &lt;em&gt;hack&lt;/em&gt; will affect the access to the lab server through the Browser, you will see a
&lt;strong&gt;login failed for display :0&lt;/strong&gt; error message, click ok and on the XRDP prompt, select &lt;strong&gt;xorg&lt;/strong&gt;,
user &lt;strong&gt;tux&lt;/strong&gt; and the password you set earlier.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is just a quick &amp;amp; dirty way to interact a little more comfortable with the Lab Environment,
you can tunnel through SSH whatever you want, SSH Sessions or X Forwarding, whatever you prefer.&lt;/p&gt;
&lt;p&gt;Especially the fact that your VM get suspended when you leave the website, makes it not really reliable,
but for me it worked quite well to prepare for some Exams.&lt;/p&gt;
&lt;p&gt;Happy hacking and enjoy your next SUSE Training :)&lt;/p&gt;
</content><category term="Linux"/><category term="SUSE"/><category term="Training"/><category term="Lab"/><category term="SSH"/><category term="RDP"/><category term="Tunnel"/></entry><entry><title>FreeBSD 13 Base System OpenSSH Server Hardening</title><link href="https://dominik.wombacher.cc/posts/freebsd_13_base_system_openssh_server_hardening.html" rel="alternate"/><published>2022-03-17T00:00:00+01:00</published><updated>2022-03-18T00:00:00+01:00</updated><author><name>Dominik Wombacher</name></author><id>tag:dominik.wombacher.cc,2022-03-17:/posts/freebsd_13_base_system_openssh_server_hardening.html</id><summary type="html">&lt;!-- SPDX-FileCopyrightText: 2023 Dominik Wombacher &lt;dominik@wombacher.cc&gt; --&gt;
&lt;!--  --&gt;
&lt;!-- SPDX-License-Identifier: CC-BY-SA-4.0 --&gt;
&lt;p&gt;Default sshd configs tend to focus more on compatibility instead security. Therefore hardening
should be one of the first things after setup a new system.&lt;/p&gt;
&lt;p&gt;I'm using the OpenSSH Daemon  ... &lt;a class="read-more" href="/posts/freebsd_13_base_system_openssh_server_hardening.html"&gt; [read more]&lt;/a&gt;&lt;/p&gt;</summary><content type="html">&lt;!-- SPDX-FileCopyrightText: 2023 Dominik Wombacher &lt;dominik@wombacher.cc&gt; --&gt;
&lt;!--  --&gt;
&lt;!-- SPDX-License-Identifier: CC-BY-SA-4.0 --&gt;
&lt;p&gt;Default sshd configs tend to focus more on compatibility instead security. Therefore hardening
should be one of the first things after setup a new system.&lt;/p&gt;
&lt;p&gt;I'm using the OpenSSH Daemon which comes with the FreeBSD Base System.
When you want to use the &lt;code&gt;openssh-portable&lt;/code&gt; port instead, skip &lt;em&gt;Step 3&lt;/em&gt;, the rest should be identical.&lt;/p&gt;
&lt;p&gt;Step 1) Delete existing host keys, generate new rsa and ed25519 key:&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
rm&lt;span class="pygments-w"&gt; &lt;/span&gt;/etc/ssh/ssh_host_*&lt;span class="pygments-w"&gt;
&lt;/span&gt;ssh-keygen&lt;span class="pygments-w"&gt; &lt;/span&gt;-q&lt;span class="pygments-w"&gt; &lt;/span&gt;-t&lt;span class="pygments-w"&gt; &lt;/span&gt;rsa&lt;span class="pygments-w"&gt; &lt;/span&gt;-b&lt;span class="pygments-w"&gt; &lt;/span&gt;&lt;span class="pygments-m"&gt;4096&lt;/span&gt;&lt;span class="pygments-w"&gt; &lt;/span&gt;-f&lt;span class="pygments-w"&gt; &lt;/span&gt;ssh_host_rsa_key&lt;span class="pygments-w"&gt; &lt;/span&gt;-N&lt;span class="pygments-w"&gt; &lt;/span&gt;&lt;span class="pygments-s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;ssh-keygen&lt;span class="pygments-w"&gt; &lt;/span&gt;-q&lt;span class="pygments-w"&gt; &lt;/span&gt;-t&lt;span class="pygments-w"&gt; &lt;/span&gt;ed25519&lt;span class="pygments-w"&gt; &lt;/span&gt;-f&lt;span class="pygments-w"&gt; &lt;/span&gt;ssh_host_ed25519_key&lt;span class="pygments-w"&gt; &lt;/span&gt;-N&lt;span class="pygments-w"&gt; &lt;/span&gt;&lt;span class="pygments-s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Step 2) Create new Diffie-Hellman groups and avoid small moduli&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
ssh-keygen&lt;span class="pygments-w"&gt; &lt;/span&gt;-G&lt;span class="pygments-w"&gt; &lt;/span&gt;moduli-3072.candidates&lt;span class="pygments-w"&gt; &lt;/span&gt;-b&lt;span class="pygments-w"&gt; &lt;/span&gt;&lt;span class="pygments-m"&gt;3072&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;ssh-keygen&lt;span class="pygments-w"&gt; &lt;/span&gt;-T&lt;span class="pygments-w"&gt; &lt;/span&gt;moduli-3072&lt;span class="pygments-w"&gt; &lt;/span&gt;-f&lt;span class="pygments-w"&gt; &lt;/span&gt;moduli-3072.candidates&lt;span class="pygments-w"&gt;
&lt;/span&gt;mv&lt;span class="pygments-w"&gt; &lt;/span&gt;moduli-3072&lt;span class="pygments-w"&gt; &lt;/span&gt;/etc/ssh/moduli&lt;span class="pygments-w"&gt;
&lt;/span&gt;rm&lt;span class="pygments-w"&gt; &lt;/span&gt;moduli-3072.candidates&lt;span class="pygments-w"&gt;
&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Step 3) Disable DSA and ECDSA host keys, only use RSA and ED25519&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
sysrc&lt;span class="pygments-w"&gt; &lt;/span&gt;&lt;span class="pygments-nv"&gt;sshd_dsa_enable&lt;/span&gt;&lt;span class="pygments-o"&gt;=&lt;/span&gt;&lt;span class="pygments-s2"&gt;&amp;quot;NO&amp;quot;&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;sysrc&lt;span class="pygments-w"&gt; &lt;/span&gt;&lt;span class="pygments-nv"&gt;sshd_ecdsa_enable&lt;/span&gt;&lt;span class="pygments-o"&gt;=&lt;/span&gt;&lt;span class="pygments-s2"&gt;&amp;quot;NO&amp;quot;&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;sysrc&lt;span class="pygments-w"&gt; &lt;/span&gt;&lt;span class="pygments-nv"&gt;sshd_ed25519_enable&lt;/span&gt;&lt;span class="pygments-o"&gt;=&lt;/span&gt;&lt;span class="pygments-s2"&gt;&amp;quot;YES&amp;quot;&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;sysrc&lt;span class="pygments-w"&gt; &lt;/span&gt;&lt;span class="pygments-nv"&gt;sshd_rsa_enable&lt;/span&gt;&lt;span class="pygments-o"&gt;=&lt;/span&gt;&lt;span class="pygments-s2"&gt;&amp;quot;YES&amp;quot;&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Step 4) Optimize &lt;code&gt;/etc/ssh/sshd_config&lt;/code&gt;, improve security, restrict allowed key exchange, cipher and MAC algorithms&lt;/p&gt;
&lt;pre class="code text literal-block"&gt;
# Hardening
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
KexAlgorithms curve25519-sha256,curve25519-sha256&amp;#64;libssh.org,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group-exchange-sha256
Ciphers chacha20-poly1305&amp;#64;openssh.com,aes256-gcm&amp;#64;openssh.com,aes128-gcm&amp;#64;openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
MACs hmac-sha2-256-etm&amp;#64;openssh.com,hmac-sha2-512-etm&amp;#64;openssh.com,umac-128-etm&amp;#64;openssh.com
HostKeyAlgorithms ssh-ed25519,ssh-ed25519-cert-v01&amp;#64;openssh.com

# Security
PermitRootLogin no
AuthenticationMethods publickey
ChallengeResponseAuthentication no
UsePAM no
VersionAddendum none
X11Forwarding no
AuthorizedKeysFile .ssh/authorized_keys
Subsystem sftp /usr/libexec/sftp-server

&lt;/pre&gt;
&lt;p&gt;Run &lt;code&gt;service sshd restart&lt;/code&gt; to apply the new settings, to verify the results of your hardening,
you can use the CLI Tool &lt;a class="reference external" href="https://github.com/jtesta/ssh-audit"&gt;ssh-audit&lt;/a&gt;
which is also available as &lt;a class="reference external" href="https://www.ssh-audit.com"&gt;Online Version&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Following a Custom Policy for ssh-audit based on the above recommendations:&lt;/p&gt;
&lt;pre class="code text literal-block"&gt;
name = &amp;quot;Custom Policy - FreeBSD 13 Base System OpenSSH Daemon (2022/03/17)&amp;quot;
version = 1
dh_modulus_size_diffie-hellman-group-exchange-sha256 = 2048
host keys = ssh-ed25519
key exchanges = curve25519-sha256, curve25519-sha256&amp;#64;libssh.org, diffie-hellman-group16-sha512, diffie-hellman-group18-sha512, diffie-hellman-group-exchange-sha256
ciphers = chacha20-poly1305&amp;#64;openssh.com, aes256-gcm&amp;#64;openssh.com, aes128-gcm&amp;#64;openssh.com, aes256-ctr, aes192-ctr, aes128-ctr
macs = hmac-sha2-256-etm&amp;#64;openssh.com, hmac-sha2-512-etm&amp;#64;openssh.com, umac-128-etm&amp;#64;openssh.com

&lt;/pre&gt;
&lt;p&gt;Copy the policy into a file and run &lt;code&gt;ssh-audit -P=&amp;lt;policy.txt&amp;gt; &amp;lt;servername&amp;gt;&lt;/code&gt;.
The result should be similar to following example without warnings or errors:&lt;/p&gt;
&lt;pre class="code text literal-block"&gt;
# general
(gen) banner: SSH-2.0-OpenSSH_8.8
(gen) software: OpenSSH 8.8
(gen) compatibility: OpenSSH 7.4+, Dropbear SSH 2018.76+
(gen) compression: enabled (zlib&amp;#64;openssh.com)

# key exchange algorithms
(kex) curve25519-sha256                     -- [info] available since OpenSSH 7.4, Dropbear SSH 2018.76
(kex) curve25519-sha256&amp;#64;libssh.org          -- [info] available since OpenSSH 6.5, Dropbear SSH 2013.62
(kex) diffie-hellman-group16-sha512         -- [info] available since OpenSSH 7.3, Dropbear SSH 2016.73
(kex) diffie-hellman-group18-sha512         -- [info] available since OpenSSH 7.3
(kex) diffie-hellman-group-exchange-sha256 (2048-bit) -- [info] available since OpenSSH 4.4

# host-key algorithms
(key) ssh-ed25519                           -- [info] available since OpenSSH 6.5

# encryption algorithms (ciphers)
(enc) chacha20-poly1305&amp;#64;openssh.com         -- [info] available since OpenSSH 6.5
                                            `- [info] default cipher since OpenSSH 6.9.
(enc) aes256-gcm&amp;#64;openssh.com                -- [info] available since OpenSSH 6.2
(enc) aes128-gcm&amp;#64;openssh.com                -- [info] available since OpenSSH 6.2
(enc) aes256-ctr                            -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52
(enc) aes192-ctr                            -- [info] available since OpenSSH 3.7
(enc) aes128-ctr                            -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52

# message authentication code algorithms
(mac) hmac-sha2-256-etm&amp;#64;openssh.com         -- [info] available since OpenSSH 6.2
(mac) hmac-sha2-512-etm&amp;#64;openssh.com         -- [info] available since OpenSSH 6.2
(mac) umac-128-etm&amp;#64;openssh.com              -- [info] available since OpenSSH 6.2

# fingerprints
(fin) ssh-ed25519: SHA256:uN9Oton+VmLL793KirVFB+ilD3Bndra4I/3yFntgX8k

# algorithm recommendations (for OpenSSH 8.8)
(rec) +diffie-hellman-group14-sha256        -- kex algorithm to append
(rec) +rsa-sha2-256                         -- key algorithm to append
(rec) +rsa-sha2-512                         -- key algorithm to append

&lt;/pre&gt;
&lt;p&gt;Sources:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://ozgurkazancci.com/ssh-server-security-audit-hardening-freebsd"&gt;https://ozgurkazancci.com/ssh-server-security-audit-hardening-freebsd&lt;/a&gt;
(Archive: &lt;a class="reference external" href="https://web.archive.org/web/20220311055553/https://ozgurkazancci.com/ssh-server-security-audit-hardening-freebsd/"&gt;[1]&lt;/a&gt;,
&lt;a class="reference external" href="https://archive.today/2022.03.17-211815/https://ozgurkazancci.com/ssh-server-security-audit-hardening-freebsd/"&gt;[2]&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://gist.github.com/koobs/e01cf8869484a095605404cd0051eb11"&gt;https://gist.github.com/koobs/e01cf8869484a095605404cd0051eb11&lt;/a&gt;
(Archive: &lt;a class="reference external" href="https://web.archive.org/web/20220313140130/https://gist.github.com/koobs/e01cf8869484a095605404cd0051eb11"&gt;[1]&lt;/a&gt;,
&lt;a class="reference external" href="https://archive.today/2021.09.16-082343/https://gist.github.com/koobs/e01cf8869484a095605404cd0051eb11"&gt;[2]&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.ssh-audit.com/hardening_guides.html"&gt;https://www.ssh-audit.com/hardening_guides.html&lt;/a&gt;
(Archive: &lt;a class="reference external" href="https://web.archive.org/web/20220113100935/https://www.ssh-audit.com/hardening_guides.html"&gt;[1]&lt;/a&gt;,
&lt;a class="reference external" href="https://archive.today/2022.03.17-211934/https://www.ssh-audit.com/hardening_guides.html"&gt;[2]&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
</content><category term="Unix"/><category term="FreeBSD"/><category term="OpenSSH"/><category term="Hardening"/><category term="SSH"/></entry><entry><title>EMail Notification to Unlock LUKS encrypted disk via Dropbear SSH</title><link href="https://dominik.wombacher.cc/posts/email_notification_to_unlock_luks_encrypted_disk_via_dropbear_ssh.html" rel="alternate"/><published>2022-03-16T00:00:00+01:00</published><updated>2022-03-16T00:00:00+01:00</updated><author><name>Dominik Wombacher</name></author><id>tag:dominik.wombacher.cc,2022-03-16:/posts/email_notification_to_unlock_luks_encrypted_disk_via_dropbear_ssh.html</id><summary type="html">&lt;!-- SPDX-FileCopyrightText: 2023 Dominik Wombacher &lt;dominik@wombacher.cc&gt; --&gt;
&lt;!--  --&gt;
&lt;!-- SPDX-License-Identifier: CC-BY-SA-4.0 --&gt;
&lt;p&gt;I'm running Proxmox VE Hosts with full encrypted disks and Dropbear SSH to unlock them remotely.
I wanted to get notified when I have to login and enter the key  ... &lt;a class="read-more" href="/posts/email_notification_to_unlock_luks_encrypted_disk_via_dropbear_ssh.html"&gt; [read more]&lt;/a&gt;&lt;/p&gt;</summary><content type="html">&lt;!-- SPDX-FileCopyrightText: 2023 Dominik Wombacher &lt;dominik@wombacher.cc&gt; --&gt;
&lt;!--  --&gt;
&lt;!-- SPDX-License-Identifier: CC-BY-SA-4.0 --&gt;
&lt;p&gt;I'm running Proxmox VE Hosts with full encrypted disks and Dropbear SSH to unlock them remotely.
I wanted to get notified when I have to login and enter the key, e.g. in case of an unexpected reboot.&lt;/p&gt;
&lt;p&gt;My setup is based on the &lt;a class="reference external" href="https://www.mailjet.com"&gt;mailjet&lt;/a&gt; Free Tier (6000 Mails / Month, 200 Mails / Day)
and some initramfs customizing to include curl, a few other required libraries and
a simple script to send an API request, tested on PVE 7.1 / Debian 11 (bullseye)&lt;/p&gt;
&lt;p&gt;I will enclose placeholder in &lt;strong&gt;&amp;lt; &amp;gt;&lt;/strong&gt;, please replace them with appropriate values based on your Environment.&lt;/p&gt;
&lt;p&gt;The hook script &lt;code&gt;/etc/initramfs-tools/hooks/curl&lt;/code&gt; take care that &lt;em&gt;curl&lt;/em&gt;,
&lt;em&gt;libnss_dns&lt;/em&gt; and a &lt;em&gt;resolv.conf&lt;/em&gt; are included in the initramfs:&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="pygments-ch"&gt;#!/bin/sh
&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-nv"&gt;PREREQ&lt;/span&gt;&lt;span class="pygments-o"&gt;=&lt;/span&gt;&lt;span class="pygments-s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="pygments-w"&gt;

&lt;/span&gt;prereqs&lt;span class="pygments-o"&gt;()&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-o"&gt;{&lt;/span&gt;&lt;span class="pygments-w"&gt;
        &lt;/span&gt;&lt;span class="pygments-nb"&gt;echo&lt;/span&gt;&lt;span class="pygments-w"&gt; &lt;/span&gt;&lt;span class="pygments-s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="pygments-nv"&gt;$PREREQ&lt;/span&gt;&lt;span class="pygments-s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-o"&gt;}&lt;/span&gt;&lt;span class="pygments-w"&gt;

&lt;/span&gt;&lt;span class="pygments-k"&gt;case&lt;/span&gt;&lt;span class="pygments-w"&gt; &lt;/span&gt;&lt;span class="pygments-nv"&gt;$1&lt;/span&gt;&lt;span class="pygments-w"&gt; &lt;/span&gt;&lt;span class="pygments-k"&gt;in&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;prereqs&lt;span class="pygments-o"&gt;)&lt;/span&gt;&lt;span class="pygments-w"&gt;
        &lt;/span&gt;prereqs&lt;span class="pygments-w"&gt;
        &lt;/span&gt;&lt;span class="pygments-nb"&gt;exit&lt;/span&gt;&lt;span class="pygments-w"&gt; &lt;/span&gt;&lt;span class="pygments-m"&gt;0&lt;/span&gt;&lt;span class="pygments-w"&gt;
        &lt;/span&gt;&lt;span class="pygments-p"&gt;;;&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-k"&gt;esac&lt;/span&gt;&lt;span class="pygments-w"&gt;

&lt;/span&gt;.&lt;span class="pygments-w"&gt; &lt;/span&gt;/usr/share/initramfs-tools/hook-functions&lt;span class="pygments-w"&gt;

&lt;/span&gt;copy_exec&lt;span class="pygments-w"&gt; &lt;/span&gt;/usr/bin/curl&lt;span class="pygments-w"&gt; &lt;/span&gt;/bin&lt;span class="pygments-w"&gt;

&lt;/span&gt;&lt;span class="pygments-c1"&gt;# Fix DNS resolver
&lt;/span&gt;cp&lt;span class="pygments-w"&gt; &lt;/span&gt;-a&lt;span class="pygments-w"&gt; &lt;/span&gt;/usr/lib/x86_64-linux-gnu/libnss_dns*&lt;span class="pygments-w"&gt; &lt;/span&gt;&lt;span class="pygments-nv"&gt;$DESTDIR&lt;/span&gt;/usr/lib/x86_64-linux-gnu/&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-nb"&gt;printf&lt;/span&gt;&lt;span class="pygments-w"&gt; &lt;/span&gt;&lt;span class="pygments-s2"&gt;&amp;quot;nameserver &amp;lt;dns_server1_ipv4_address&amp;gt;\nnameserver &amp;lt;dns_server2_ipv4_address&amp;gt;\n&amp;quot;&lt;/span&gt;&lt;span class="pygments-w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="pygments-w"&gt; &lt;/span&gt;&lt;span class="pygments-nv"&gt;$DESTDIR&lt;/span&gt;/etc/resolv.conf&lt;span class="pygments-w"&gt;
&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;The actual notification will be send by &lt;code&gt;/etc/initramfs-tools/scripts/init-premount/notification&lt;/code&gt; through the mailjet API.
You shouldn't have a problem to adjust it to use any other Service as long you can trigger a API via curl :)&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="pygments-ch"&gt;#!/bin/sh
&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-nv"&gt;PREREQ&lt;/span&gt;&lt;span class="pygments-o"&gt;=&lt;/span&gt;&lt;span class="pygments-s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="pygments-w"&gt;

&lt;/span&gt;prereqs&lt;span class="pygments-o"&gt;()&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-o"&gt;{&lt;/span&gt;&lt;span class="pygments-w"&gt;
        &lt;/span&gt;&lt;span class="pygments-nb"&gt;echo&lt;/span&gt;&lt;span class="pygments-w"&gt; &lt;/span&gt;&lt;span class="pygments-s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="pygments-nv"&gt;$PREREQ&lt;/span&gt;&lt;span class="pygments-s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-o"&gt;}&lt;/span&gt;&lt;span class="pygments-w"&gt;

&lt;/span&gt;&lt;span class="pygments-k"&gt;case&lt;/span&gt;&lt;span class="pygments-w"&gt; &lt;/span&gt;&lt;span class="pygments-nv"&gt;$1&lt;/span&gt;&lt;span class="pygments-w"&gt; &lt;/span&gt;&lt;span class="pygments-k"&gt;in&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;prereqs&lt;span class="pygments-o"&gt;)&lt;/span&gt;&lt;span class="pygments-w"&gt;
        &lt;/span&gt;prereqs&lt;span class="pygments-w"&gt;
        &lt;/span&gt;&lt;span class="pygments-nb"&gt;exit&lt;/span&gt;&lt;span class="pygments-w"&gt; &lt;/span&gt;&lt;span class="pygments-m"&gt;0&lt;/span&gt;&lt;span class="pygments-w"&gt;
        &lt;/span&gt;&lt;span class="pygments-p"&gt;;;&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-k"&gt;esac&lt;/span&gt;&lt;span class="pygments-w"&gt;

&lt;/span&gt;.&lt;span class="pygments-w"&gt; &lt;/span&gt;/scripts/functions&lt;span class="pygments-w"&gt;

&lt;/span&gt;configure_networking&lt;span class="pygments-w"&gt;

&lt;/span&gt;/bin/curl&lt;span class="pygments-w"&gt; &lt;/span&gt;--insecure&lt;span class="pygments-w"&gt; &lt;/span&gt;-s&lt;span class="pygments-w"&gt; &lt;/span&gt;&lt;span class="pygments-se"&gt;\
&lt;/span&gt;-X&lt;span class="pygments-w"&gt; &lt;/span&gt;POST&lt;span class="pygments-w"&gt; &lt;/span&gt;&lt;span class="pygments-se"&gt;\
&lt;/span&gt;--user&lt;span class="pygments-w"&gt; &lt;/span&gt;&lt;span class="pygments-s2"&gt;&amp;quot;&amp;lt;mailjet_api_user&amp;gt;:&amp;lt;mailjet_api_pass&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="pygments-w"&gt; &lt;/span&gt;&lt;span class="pygments-se"&gt;\
&lt;/span&gt;https://api.mailjet.com/v3.1/send&lt;span class="pygments-w"&gt; &lt;/span&gt;&lt;span class="pygments-se"&gt;\
&lt;/span&gt;-H&lt;span class="pygments-w"&gt; &lt;/span&gt;&lt;span class="pygments-s1"&gt;'Content-Type: application/json'&lt;/span&gt;&lt;span class="pygments-w"&gt; &lt;/span&gt;&lt;span class="pygments-se"&gt;\
&lt;/span&gt;-d&lt;span class="pygments-w"&gt; &lt;/span&gt;&lt;span class="pygments-s1"&gt;'{
  &amp;quot;Messages&amp;quot;:[
    {
      &amp;quot;From&amp;quot;: {
        &amp;quot;Email&amp;quot;: &amp;quot;&amp;lt;sender_email&amp;gt;&amp;quot;,
        &amp;quot;Name&amp;quot;: &amp;quot;&amp;lt;sender_name&amp;gt;&amp;quot;
      },
      &amp;quot;To&amp;quot;: [
        {
          &amp;quot;Email&amp;quot;: &amp;quot;&amp;lt;recipient_mail&amp;gt;&amp;quot;,
          &amp;quot;Name&amp;quot;: &amp;quot;&amp;lt;recipient_name&amp;gt;&amp;quot;
        },
        {
          &amp;quot;Email&amp;quot;: &amp;quot;&amp;lt;recipient2_mail&amp;gt;&amp;quot;,
          &amp;quot;Name&amp;quot;: &amp;quot;Pushover&amp;quot;
        }
      ],
      &amp;quot;Subject&amp;quot;: &amp;quot;Action required: Unlock &amp;lt;fqdn&amp;gt;!&amp;quot;,
      &amp;quot;TextPart&amp;quot;: &amp;quot;Server &amp;lt;fqdn&amp;gt; was restarted and need to be unlocked to proceed boot sequence.&amp;quot;,
      &amp;quot;CustomID&amp;quot;: &amp;quot;DropbearUnlockRequest&amp;quot;
    }
  ]
}'&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;I'm also using &lt;a class="reference external" href="https://pushover.net"&gt;Pushover&lt;/a&gt; to receive notifications on my mobile, they offer mail2push,
so I just added my personal pushover address as second recipient to get notified by Mail and Pushover.&lt;/p&gt;
&lt;p&gt;Make both scripts executable:&lt;/p&gt;
&lt;pre class="code text literal-block"&gt;
chmod +x /etc/initramfs-tools/hooks/curl`
chmod +x /etc/initramfs-tools/scripts/init-premount/notification

&lt;/pre&gt;
&lt;p&gt;Run &lt;code&gt;update-initramfs -u&lt;/code&gt; and you are good to go, during the next reboot you should receive
an Email Notification to enter your LUKS Key and unlock your disk.&lt;/p&gt;
</content><category term="Linux"/><category term="Debian"/><category term="Proxmox"/><category term="Dropbear"/><category term="SSH"/><category term="LUKS"/><category term="EMail"/></entry><entry><title>SUSE Manager / Uyuni - Salt SSH Push: Thin package corrupted</title><link href="https://dominik.wombacher.cc/posts/suse-manager-uyuni-salt-ssh-push-thin-package-corrupted.html" rel="alternate"/><published>2021-03-02T00:00:00+01:00</published><updated>2021-03-02T00:00:00+01:00</updated><author><name>Dominik Wombacher</name></author><id>tag:dominik.wombacher.cc,2021-03-02:/posts/suse-manager-uyuni-salt-ssh-push-thin-package-corrupted.html</id><summary type="html">&lt;!-- SPDX-FileCopyrightText: 2023 Dominik Wombacher &lt;dominik@wombacher.cc&gt; --&gt;
&lt;!--  --&gt;
&lt;!-- SPDX-License-Identifier: CC-BY-SA-4.0 --&gt;
&lt;p&gt;At work we had issues with almost all Salt-SSH / SSH-Push connected Clients for months due to an unhandled exception &lt;code&gt;ImportError: No module named 'salt.exceptions'&lt;/code&gt; that occurred regularly. It took  ... &lt;a class="read-more" href="/posts/suse-manager-uyuni-salt-ssh-push-thin-package-corrupted.html"&gt; [read more]&lt;/a&gt;&lt;/p&gt;</summary><content type="html">&lt;!-- SPDX-FileCopyrightText: 2023 Dominik Wombacher &lt;dominik@wombacher.cc&gt; --&gt;
&lt;!--  --&gt;
&lt;!-- SPDX-License-Identifier: CC-BY-SA-4.0 --&gt;
&lt;p&gt;At work we had issues with almost all Salt-SSH / SSH-Push connected Clients for months due to an unhandled exception &lt;code&gt;ImportError: No module named 'salt.exceptions'&lt;/code&gt; that occurred regularly. It took me a lot of time to track the issue down together with SUSE so I want to share my Experience.&lt;/p&gt;
&lt;div class="section" id="error"&gt;
&lt;h2&gt;Error&lt;/h2&gt;
&lt;pre class="code text literal-block"&gt;
[...]
&amp;quot;stderr&amp;quot;: &amp;quot;Traceback (most recent call last):\n File
\&amp;quot;/var/tmp/.user_a567dc_salt/salt-call\&amp;quot;, line 26, in \n from
salt.scripts import salt_call\n File
\&amp;quot;/var/tmp/.user_a567dc_salt/pyall/salt/scripts.py\&amp;quot;, line 21, in \n
from salt.exceptions import SaltSystemExit, SaltClientError,
SaltReqTimeoutError\nImportError: No module named 'salt.exceptions'&amp;quot;
[...]

&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="background"&gt;
&lt;h2&gt;Background&lt;/h2&gt;
&lt;p&gt;Normally Salt is using an Agent (Salt-Minion) but also supports an Agentless approach called Salt-SSH.
A package (&lt;em&gt;&amp;quot;thin.tgz&amp;quot;&lt;/em&gt;), which contains all python code and files that Salt need to run Jobs on a server, will be uploaded and extracted to &lt;strong&gt;/var/tmp/.&amp;lt;user&amp;gt;_&amp;lt;id&amp;gt;_salt/&lt;/strong&gt; on the target Server.
The &amp;quot;&lt;em&gt;id&lt;/em&gt;&amp;quot; is related to the used Salt Version, the &amp;quot;&lt;em&gt;user&lt;/em&gt;&amp;quot; is the one configured on the Salt Master - in our Case SUSE Manager - which has full sudo permissions and is allowed to login via SSH on the target.&lt;/p&gt;
&lt;p&gt;Everytime Salt connect to run a Job, some checks will performed to verify that state of the thin package:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Does the Folder for the specified user with the matching id exist in &lt;em&gt;/var/tmp/&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Is the file &lt;em&gt;&amp;quot;code-checksum&amp;quot;&lt;/em&gt; available and does the containing checksum matches with the thin.tgz package on the Salt Master&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As long both checks are successful, the Salt Master will _not_ upload a new &lt;em&gt;thin.tgz&lt;/em&gt; - that's important to understand.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="troubleshooting"&gt;
&lt;h2&gt;Troubleshooting&lt;/h2&gt;
&lt;p&gt;First it was totally unclear were the issue was coming from, it could occur with every job type, on different server at a different time.
The thin package was always corrupted at some point what caused the unhandled exception.
The Workaround was to manually delete the whole folder of the Salt thin package on the target Server so the Salt Master uploaded a fresh copy next time.&lt;/p&gt;
&lt;p&gt;SUSE helped to go through tons of logs and to visualize a timeline were I could see that the issue seem to occur every 7 days.&lt;/p&gt;
&lt;p&gt;Further investigation confirmed, in this case the problem was self-made. Someone from the Team configured systemd to automatically cleanup the tmp folder on a lot of server and neither tested nor documented it well.
Removing the thin package folder wouldn't be a problem, it would be just newly uploaded, as long it's done right but it wasn't.&lt;/p&gt;
&lt;pre class="code text literal-block"&gt;
/etc/tmpfiles.d/clean_tmp.conf

D /tmp 1777 root root 7d
D /var/tmp 1777 root root 7d

&lt;/pre&gt;
&lt;p&gt;The tmpfiles config removed only files and folder owned by user &lt;em&gt;root&lt;/em&gt;, but a few files, like &amp;quot;&lt;em&gt;code-checksum&lt;/em&gt;&amp;quot;, of the thin package folder are owned by salt.
So every 7 days almost all files were removed and therefore corrupted Salt thin, but the Salt Master found the folder and the &amp;quot;&lt;em&gt;code-checksum&lt;/em&gt;&amp;quot; file with the correct hash and thought the thin state is healthy.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="solution"&gt;
&lt;h2&gt;Solution&lt;/h2&gt;
&lt;p&gt;At the end I just removed the custom tmpfiles config and once again the thin folder manually on all affected server.&lt;/p&gt;
&lt;p&gt;For us there wasn't much benefit in deleting the thin package weekly and generate high load and consume bandwith to re-upload it. In case you prefer the regular cleanup of your tmp folders, just ensure that the whole thin folder and all files are covered and either removed ore kept untouched by your ruleset.&lt;/p&gt;
&lt;p&gt;Even though it was a human error and not directly related to SUSE Manager / Uyuni or Salt it demonstrated how fragile such components can be.
From a technical point of view I understand why there are just a few checks and validation of the hash in a file.
Doing that for the whole folder content on every job run would horrible slow and increase the load.
But as we can see, it comes with a price and can be affected by something you wouldn't expect.&lt;/p&gt;
&lt;/div&gt;
</content><category term="Linux"/><category term="Uyuni"/><category term="SUSE Manager"/><category term="SSH"/><category term="Salt"/><category term="Exception"/></entry><entry><title>SUSE Manager / Uyuni - Valid PTR Record required for SSH-Push Clients</title><link href="https://dominik.wombacher.cc/posts/suse-manager-uyuni-valid-ptr-required-for-ssh-push.html" rel="alternate"/><published>2021-02-23T00:00:00+01:00</published><updated>2021-02-23T00:00:00+01:00</updated><author><name>Dominik Wombacher</name></author><id>tag:dominik.wombacher.cc,2021-02-23:/posts/suse-manager-uyuni-valid-ptr-required-for-ssh-push.html</id><summary type="html">&lt;!-- SPDX-FileCopyrightText: 2023 Dominik Wombacher &lt;dominik@wombacher.cc&gt; --&gt;
&lt;!--  --&gt;
&lt;!-- SPDX-License-Identifier: CC-BY-SA-4.0 --&gt;
&lt;p&gt;I'm responsible for a &lt;a class="reference external" href="https://www.suse.com/products/suse-manager/"&gt;SUSE Manager&lt;/a&gt; Installation, the commercial product
based on &lt;a class="reference external" href="https://www.uyuni-project.org"&gt;Uyuni&lt;/a&gt;, with almost 900 connected Server.&lt;/p&gt;
&lt;p&gt;The recommend connection method is using a Salt Minion, but SSH-Push - based  ... &lt;a class="read-more" href="/posts/suse-manager-uyuni-valid-ptr-required-for-ssh-push.html"&gt; [read more]&lt;/a&gt;&lt;/p&gt;</summary><content type="html">&lt;!-- SPDX-FileCopyrightText: 2023 Dominik Wombacher &lt;dominik@wombacher.cc&gt; --&gt;
&lt;!--  --&gt;
&lt;!-- SPDX-License-Identifier: CC-BY-SA-4.0 --&gt;
&lt;p&gt;I'm responsible for a &lt;a class="reference external" href="https://www.suse.com/products/suse-manager/"&gt;SUSE Manager&lt;/a&gt; Installation, the commercial product
based on &lt;a class="reference external" href="https://www.uyuni-project.org"&gt;Uyuni&lt;/a&gt;, with almost 900 connected Server.&lt;/p&gt;
&lt;p&gt;The recommend connection method is using a Salt Minion, but SSH-Push - based on Salt-SSH - is the agentless alternative.
In our Environment, something around 200 Server using this connection type, because there is already a Salt Minion running,
attached to a different Salt Master.&lt;/p&gt;
&lt;div class="section" id="problem"&gt;
&lt;h2&gt;Problem&lt;/h2&gt;
&lt;p&gt;During the last weeks we faced some issues were the &lt;strong&gt;salt-api&lt;/strong&gt; service is going to crash due to an unhandled exception from time to time.&lt;/p&gt;
&lt;p&gt;Investigation together with SUSE is still ongoing but so far it seems like, that under rare conditions, a Server with connection method
SSH-Push and without valid PTR DNS Record can indeed raise an Exception in the Salt Codebase.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="background"&gt;
&lt;h2&gt;Background&lt;/h2&gt;
&lt;p&gt;Function &lt;code&gt;ip_to_host&lt;/code&gt; located in &lt;strong&gt;/usr/lib/python3.6/site-packages/salt/utils/network.py&lt;/strong&gt; is passing the FQDN to Python built-in Function
&lt;code&gt;socket.gethostbyaddr&lt;/code&gt;. This will raise an Exception, handled by &lt;code&gt;ip_to_host&lt;/code&gt; which then return &lt;code&gt;None&lt;/code&gt; (Normally that should be a Hostname).&lt;/p&gt;
&lt;p&gt;Based on the return value, a new Minion Job for Server &lt;code&gt;None&lt;/code&gt; will be started and end up in an &lt;strong&gt;unhandled Exception&lt;/strong&gt; that cause salt-api
to crash as shown in the following error message (Debug Mode need to be enabled for &lt;em&gt;Salt&lt;/em&gt; as well &lt;em&gt;Taskomatic&lt;/em&gt;):&lt;/p&gt;
&lt;p&gt;&lt;em&gt;/var/log/salt/api_error&lt;/em&gt;&lt;/p&gt;
&lt;pre class="code text literal-block"&gt;
Traceback (most recent call last):
        File &amp;quot;/usr/lib/python3.6/site-packages/salt/netapi/rest_cherrypy/app.py&amp;quot;, line 860, in hypermedia_handler
                ret = cherrypy.serving.request._hypermedia_inner_handler(*args, **kwargs)
        File &amp;quot;/usr/lib/python3.6/site-packages/cherrypy/_cpdispatch.py&amp;quot;, line 54, in __call__
                return self.callable(*self.args, **self.kwargs)
        File &amp;quot;/usr/lib/python3.6/site-packages/salt/netapi/rest_cherrypy/app.py&amp;quot;, line 2140, in POST
                'return': list(self.exec_lowstate()),
        File &amp;quot;/usr/lib/python3.6/site-packages/salt/netapi/rest_cherrypy/app.py&amp;quot;, line 1187, in exec_lowstate
                ret = self.api.run(chunk)
        File &amp;quot;/usr/lib/python3.6/site-packages/salt/netapi/__init__.py&amp;quot;, line 152, in run
                return l_fun(*f_call.get('args', ()), **f_call.get('kwargs', {}))
        File &amp;quot;/usr/lib/python3.6/site-packages/salt/netapi/__init__.py&amp;quot;, line 218, in ssh
                return ssh_client.cmd_sync(kwargs)
        File &amp;quot;/usr/lib/python3.6/site-packages/salt/client/ssh/client.py&amp;quot;, line 159, in cmd_sync
                **kwargs)
        File &amp;quot;/usr/lib/python3.6/site-packages/salt/client/ssh/client.py&amp;quot;, line 123, in cmd
                for ret in ssh.run_iter(jid=kwargs.get('jid', None)):
        File &amp;quot;/usr/lib/python3.6/site-packages/salt/client/ssh/__init__.py&amp;quot;, line 696, in run_iter
                self.cache_job(jid, host, ret[host], fun)
        File &amp;quot;/usr/lib/python3.6/site-packages/salt/client/ssh/__init__.py&amp;quot;, line 720, in cache_job
                'fun': fun})
        File &amp;quot;/usr/lib/python3.6/site-packages/salt/returners/local_cache.py&amp;quot;, line 147, in returner
                hn_dir = os.path.join(jid_dir, load['id'])
        File &amp;quot;/usr/lib64/python3.6/posixpath.py&amp;quot;, line 94, in join
                genericpath._check_arg_types('join', a, *p)
        File &amp;quot;/usr/lib64/python3.6/genericpath.py&amp;quot;, line 149, in _check_arg_types
                (funcname, s.__class__.__name__)) from None
TypeError: join() argument must be str or bytes, not 'NoneType'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
        File &amp;quot;/usr/lib/python3.6/site-packages/cherrypy/_cprequest.py&amp;quot;, line 638, in respond
                self._do_respond(path_info)
        File &amp;quot;/usr/lib/python3.6/site-packages/cherrypy/_cprequest.py&amp;quot;, line 697, in _do_respond
                response.body = self.handler()
        File &amp;quot;/usr/lib/python3.6/site-packages/cherrypy/lib/encoding.py&amp;quot;, line 219, in __call__
                self.body = self.oldhandler(*args, **kwargs)
        File &amp;quot;/usr/lib/python3.6/site-packages/salt/netapi/rest_cherrypy/app.py&amp;quot;, line 894, in hypermedia_handler
                if cherrypy.config['debug']
        File &amp;quot;/usr/lib64/python3.6/traceback.py&amp;quot;, line 167, in format_exc
                return &amp;quot;&amp;quot;.join(format_exception(*sys.exc_info(), limit=limit, chain=chain))
        File &amp;quot;/usr/lib64/python3.6/traceback.py&amp;quot;, line 121, in format_exception
                type(value), value, tb, limit=limit).format(chain=chain))
        File &amp;quot;/usr/lib64/python3.6/traceback.py&amp;quot;, line 498, in __init__
                _seen=_seen)
        File &amp;quot;/usr/lib64/python3.6/traceback.py&amp;quot;, line 509, in __init__
                capture_locals=capture_locals)
        File &amp;quot;/usr/lib64/python3.6/traceback.py&amp;quot;, line 338, in extract
                if limit &amp;gt;= 0:

TypeError: '&amp;gt;=' not supported between instances of 'TypeError' and 'int'

&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;/var/log/salt/api&lt;/em&gt;&lt;/p&gt;
&lt;pre class="code text literal-block"&gt;
[...]
2021-02-08 01:08:01,229 [salt.utils.network:239 ][DEBUG ][38989] salt.utils.network.ip_to_host('server.example.com') failed: [Errno 0] Resolver Error 0 (no error)
[...]
2021-02-08 01:08:02,801 [salt.loaded.int.returner.local_cache:252 ][DEBUG ][38989] Adding minions for job 20210208000802780236: [None]
[...]
2021-02-08 01:08:02,839 [salt.utils.process:767 ][ERROR ][5340] An un-handled exception from the multiprocessing process 'Process-1:335' was caught:
[...]
2021-02-08 01:08:02,916 [salt.client.ssh :644 ][ERROR ][38989] Target 'None' did not return any data, probably due to an error.
2021-02-08 01:08:02,917 [salt.loaded.int.netapi.rest_cherrypy.app:887 ][DEBUG ][38989] Error while processing request for: /run

&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;/var/log/rhn/rhn_taskomatic_daemon.log&lt;/em&gt;&lt;/p&gt;
&lt;pre class="code text literal-block"&gt;
2021-02-08 01:08:02,976 [Thread-70313] ERROR com.redhat.rhn.taskomatic.task.SSHPush - com.suse.salt.netapi.
exception.SaltException: Response code: 500
java.lang.RuntimeException: com.suse.salt.netapi.exception.SaltException: Response code: 500
        at com.suse.manager.webui.services.impl.SaltService.callSync(SaltService.java:235)
        at com.suse.manager.webui.services.impl.SaltService.ping(SaltService.java:244)
        at com.redhat.rhn.taskomatic.task.sshpush.SSHPushWorkerSalt.performCheckin(SSHPushWorkerSalt.java:337)
        at com.redhat.rhn.taskomatic.task.sshpush.SSHPushWorkerSalt.lambda$run$0(SSHPushWorkerSalt.java:122)
        at java.base/java.util.Optional.ifPresent(Optional.java:183)
        at com.redhat.rhn.taskomatic.task.sshpush.SSHPushWorkerSalt.run(SSHPushWorkerSalt.java:110)
        at EDU.oswego.cs.dl.util.concurrent.PooledExecutor$Worker.run(PooledExecutor.java:732)
        at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: com.suse.salt.netapi.exception.SaltException: Response code: 500
        at com.suse.salt.netapi.client.impl.HttpAsyncClientImpl.createSaltException(HttpAsyncClientImpl.java:
        145)
        at com.suse.salt.netapi.client.impl.HttpAsyncClientImpl.access$000(HttpAsyncClientImpl.java:27)
        at com.suse.salt.netapi.client.impl.HttpAsyncClientImpl$1.completed(HttpAsyncClientImpl.java:121)
        at com.suse.salt.netapi.client.impl.HttpAsyncClientImpl$1.completed(HttpAsyncClientImpl.java:101)
        at org.apache.http.concurrent.BasicFuture.completed(BasicFuture.java:123)
        at org.apache.http.impl.nio.client.DefaultClientExchangeHandlerImpl.responseCompleted
(DefaultClientExchangeHandlerImpl.java:181)
        at org.apache.http.nio.protocol.HttpAsyncRequestExecutor.processResponse(HttpAsyncRequestExecutor.java:
        442)
        at org.apache.http.nio.protocol.HttpAsyncRequestExecutor.inputReady(HttpAsyncRequestExecutor.java:332)
        at org.apache.http.impl.nio.DefaultNHttpClientConnection.consumeInput(DefaultNHttpClientConnection.java:
        265)
        at org.apache.http.impl.nio.client.InternalIODispatch.onInputReady(InternalIODispatch.java:81)
        at org.apache.http.impl.nio.client.InternalIODispatch.onInputReady(InternalIODispatch.java:39)
        at org.apache.http.impl.nio.reactor.AbstractIODispatch.inputReady(AbstractIODispatch.java:121)
        at org.apache.http.impl.nio.reactor.BaseIOReactor.readable(BaseIOReactor.java:162)
        at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvent(AbstractIOReactor.java:337)
        at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvents(AbstractIOReactor.java:315)
        at org.apache.http.impl.nio.reactor.AbstractIOReactor.execute(AbstractIOReactor.java:276)
        at org.apache.http.impl.nio.reactor.BaseIOReactor.execute(BaseIOReactor.java:104)
        at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor$Worker.run
(AbstractMultiworkerIOReactor.java:588)
... 1 more

&lt;/pre&gt;
&lt;p&gt;You can quickly check, with two Python based commands, if the reverse lookup is working for a given FQDN.
In this Example we assume the FQDN is &lt;strong&gt;server.example.com&lt;/strong&gt; and the assigned IP Address is &lt;strong&gt;10.11.12.13&lt;/strong&gt;:&lt;/p&gt;
&lt;pre class="code text literal-block"&gt;
python3 -c 'import socket; print(socket.gethostbyaddr(&amp;quot;server.example.com&amp;quot;))'
python3 -c 'import socket; print(socket.getaddrinfo(&amp;quot;server.example.com&amp;quot;, 0, 0, 0, 0))'

&lt;/pre&gt;
&lt;p&gt;In case everything is fine, both should return something similar as the following:&lt;/p&gt;
&lt;pre class="code text literal-block"&gt;
('server.example.com', [], ['10.11.12.13'])
[(&amp;lt;AddressFamily.AF_INET: 2&amp;gt;, &amp;lt;SocketKind.SOCK_STREAM: 1&amp;gt;, 6, '', ('10.11.12.13', 0)),
        (&amp;lt;AddressFamily.AF_INET: 2&amp;gt;, &amp;lt;SocketKind.SOCK_DGRAM: 2&amp;gt;, 17, '', ('10.11.12.13', 0)),
        (&amp;lt;AddressFamily.AF_INET: 2&amp;gt;, &amp;lt;SocketKind.SOCK_RAW: 3&amp;gt;, 0, '', ('10.11.12.13', 0))]

&lt;/pre&gt;
&lt;p&gt;Further reading regarding &lt;em&gt;gethostbyaddr&lt;/em&gt;: &lt;a class="reference external" href="https://docs.python.org/3/library/socket.html#socket.gethostbyaddr"&gt;https://docs.python.org/3/library/socket.html#socket.gethostbyaddr&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="solution"&gt;
&lt;h2&gt;Solution&lt;/h2&gt;
&lt;p&gt;I expect that SUSE is going to include a Patch in future SUSE Manager and Uyuni releases were a Server will probably skipped
if there is no valid PTR Record. So you should double check in your Environment, that all Systems connected via SSH-Push / Salt-SSH
have the necessary DNS Records and can be resolved by their FQDN as well IP Address to avoid potential issues.&lt;/p&gt;
&lt;/div&gt;
</content><category term="Linux"/><category term="Uyuni"/><category term="SUSE Manager"/><category term="SSH"/><category term="Salt"/><category term="DNS"/></entry></feed>