<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Firewall – Serverküche</title><link>https://serverkueche.de/en/tags/firewall/</link><description>Firewall – Neueste Beiträge von Serverküche</description><generator>Hugo</generator><language>en-US</language><managingEditor>feedback@serverkueche.de (Serverküche)</managingEditor><webMaster>feedback@serverkueche.de (Serverküche)</webMaster><copyright>2026 Serverküche</copyright><lastBuildDate>Fri, 17 Jul 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://serverkueche.de/en/tags/firewall/index.xml" rel="self" type="application/rss+xml"/><item><title>Setting up a firewall with UFW</title><link>https://serverkueche.de/en/tutorials/firewall-ufw-setup/</link><pubDate>Fri, 17 Jul 2026 00:00:00 +0000</pubDate><author>feedback@serverkueche.de (Serverküche)</author><guid>https://serverkueche.de/en/tutorials/firewall-ufw-setup/</guid><description>Set up a host firewall in minutes with UFW: block everything except SSH, HTTP and HTTPS on your server – without ever locking yourself out.</description><content:encoded><![CDATA[<p>By default, your server accepts connections on all open ports. A <strong>firewall</strong>
turns that around: it blocks everything and only lets through what you explicitly
allow. <strong>UFW</strong> (&ldquo;Uncomplicated Firewall&rdquo;) does this with a few, readable commands –
the perfect first line of defense.</p>
<h2 id="what-are-we-building">What are we building?</h2>
<p>By the end, <strong>UFW</strong> runs on your <strong>Debian 13</strong> with the base rule &ldquo;<strong>block all
incoming</strong>&rdquo;, with only <strong>SSH</strong> (your access) plus <strong>HTTP/HTTPS</strong> (ports 80/443,
which you&rsquo;ll need later for Traefik) open. Outgoing connections stay allowed. The
key part: we proceed in a way that ensures you <strong>don&rsquo;t lock yourself out</strong>.</p>
<h2 id="prerequisites">Prerequisites</h2>
<ul>
<li>A <a href="/en/tutorials/harden-ssh/">hardened server</a> with a sudo user</li>
<li>You know which <strong>port your SSH</strong> runs on (default: 22)</li>
</ul>
<h2 id="step-by-step">Step by step</h2>
<h3 id="step-1-install-ufw">Step 1: Install UFW</h3>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <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></span><span class="line"><span class="cl">sudo apt install -y ufw</span></span></code></pre></div>
</div>
<p>Check the version – UFW is <strong>inactive</strong> at first, which is intended:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ufw version</span></span></code></pre></div>
</div>
<h3 id="step-2-define-the-base-rules">Step 2: Define the base rules</h3>
<p>First the default direction: deny everything incoming, allow everything outgoing.</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo ufw default deny incoming
</span></span><span class="line"><span class="cl">sudo ufw default allow outgoing</span></span></code></pre></div>
</div>
<div class="sk-code">
  <span class="sk-code-head">Ausgabe</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">Default incoming policy changed to &#39;deny&#39;
</span></span><span class="line"><span class="cl">(be sure to update your rules accordingly)
</span></span><span class="line"><span class="cl">Default outgoing policy changed to &#39;allow&#39;
</span></span><span class="line"><span class="cl">(be sure to update your rules accordingly)</span></span></code></pre></div>
</div>
<p>These rules don&rsquo;t take effect yet – UFW is still inactive. So the exceptions come
now, <strong>before</strong> we switch it on.</p>
<h3 id="step-3-allow-ssh--first-or-youll-lock-yourself-out">Step 3: Allow SSH – first, or you&rsquo;ll lock yourself out</h3>
<div class="not-prose my-6 rounded-lg border-l-4 p-4 border-paprika-400 bg-paprika-50 dark:border-paprika-700 dark:bg-paprika-900/20">
  <p class="mb-1 flex items-center gap-2 font-semibold text-slate-900 dark:text-white">
    <span aria-hidden="true">🔥</span>Allow SSH first, then activate
  </p>
  <div class="prose-kitchen text-sm">If you enable UFW with the &ldquo;deny incoming&rdquo; rule <strong>without</strong> having allowed SSH
first, the next command cuts your own connection – and you can no longer get in via
SSH. This order is non-negotiable.</div>
</div>
<p>If your SSH runs on the default port 22 (and <code>openssh-server</code> is installed), there&rsquo;s
a ready-made profile for it:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo ufw allow OpenSSH</span></span></code></pre></div>
</div>
<p>If you changed the SSH port (e.g. to 2222), allow exactly that port instead:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo ufw allow 2222/tcp</span></span></code></pre></div>
</div>
<h3 id="step-4-allow-http-and-https">Step 4: Allow HTTP and HTTPS</h3>
<p>For the later <a href="/en/tutorials/traefik-reverse-proxy/">reverse proxy with Traefik</a> you
need the web ports. Open them right away:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo ufw allow 80/tcp
</span></span><span class="line"><span class="cl">sudo ufw allow 443/tcp</span></span></code></pre></div>
</div>
<p>UFW confirms each rule with <code>Rules updated</code> and <code>Rules updated (v6)</code> (the IPv6
variant).</p>
<h3 id="step-5-activate-the-firewall-and-check-it">Step 5: Activate the firewall and check it</h3>
<p>Now switch it on:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo ufw enable</span></span></code></pre></div>
</div>
<div class="sk-code">
  <span class="sk-code-head">Ausgabe</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
</span></span><span class="line"><span class="cl">Firewall is active and enabled on system startup</span></span></code></pre></div>
</div>
<p>Check the result:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo ufw status verbose</span></span></code></pre></div>
</div>
<div class="sk-code">
  <span class="sk-code-head">Ausgabe</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">Status: active
</span></span><span class="line"><span class="cl">Logging: on (low)
</span></span><span class="line"><span class="cl">Default: deny (incoming), allow (outgoing), disabled (routed)
</span></span><span class="line"><span class="cl">New profiles: skip
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">To                         Action      From
</span></span><span class="line"><span class="cl">--                         ------      ----
</span></span><span class="line"><span class="cl">22/tcp (OpenSSH)           ALLOW IN    Anywhere
</span></span><span class="line"><span class="cl">80/tcp                     ALLOW IN    Anywhere
</span></span><span class="line"><span class="cl">443/tcp                    ALLOW IN    Anywhere
</span></span><span class="line"><span class="cl">22/tcp (OpenSSH (v6))      ALLOW IN    Anywhere (v6)
</span></span><span class="line"><span class="cl">80/tcp (v6)                ALLOW IN    Anywhere (v6)
</span></span><span class="line"><span class="cl">443/tcp (v6)               ALLOW IN    Anywhere (v6)</span></span></code></pre></div>
</div>
<p><code>Status: active</code> and your three allowances – done. <strong>To be safe, test in a second
SSH session</strong> that you can still connect before closing the first one.</p>
<h2 id="when-things-go-wrong">When things go wrong</h2>
<div class="troubleshoot not-prose">
<p><strong>After <code>ufw enable</code> you can no longer get in via SSH.</strong> The SSH rule was missing or
targeted the wrong port. Connect via the <strong>console in the netcup SCP</strong> (VNC,
independent of SSH), allow your SSH port there (<code>sudo ufw allow …</code>) and test again.
That&rsquo;s exactly what step 3 warns about.</p>
<p><strong><code>ERROR: Could not find a profile matching 'OpenSSH'</code>.</strong> The OpenSSH profile only
exists if <code>openssh-server</code> is installed. Use the port number instead: <code>sudo ufw allow 22/tcp</code> (or your port). <code>sudo ufw app list</code> shows the available profiles.</p>
<p><strong>A Docker container is reachable from outside even though UFW doesn&rsquo;t open the
port.</strong> Not your mistake – <strong>Docker bypasses UFW</strong>. Docker writes its rules directly
into <code>iptables</code> and inserts them ahead of the UFW chains. A published container port
(<code>ports:</code> in the compose.yaml) is thus open, no matter what UFW says. The clean
solution is a second firewall layer <strong>in front of</strong> the server – at netcup the
<a href="/en/tutorials/netcup-firewall-setup/">firewall in the SCP</a> as an upstream
perimeter. On the host it also helps to bind container ports only to <code>127.0.0.1</code>
instead of <code>0.0.0.0</code>.</p>

</div>

<h2 id="maintenance--backups">Maintenance &amp; backups</h2>
<ul>
<li><strong>View and delete rules:</strong> <code>sudo ufw status numbered</code> numbers all rules;
<code>sudo ufw delete 3</code> removes rule 3. That&rsquo;s how you tidy up when a service goes
away.</li>
<li><strong>New services:</strong> For every additional public port, one targeted rule – never
&ldquo;just open everything&rdquo;. What doesn&rsquo;t need to be open stays closed.</li>
<li><strong>No backup needed,</strong> but note down your allowances (or keep them in the same
document as your DNS records). The rule set is retyped in seconds.</li>
<li><strong>Know the limits:</strong> UFW protects the host, but not against the Docker gap above.
An upstream perimeter firewall like the
<a href="/en/tutorials/netcup-firewall-setup/">netcup firewall in the SCP</a> complements UFW
into two layers that secure each other – ideal once containers with open ports are
running.</li>
</ul>
]]></content:encoded></item><item><title>Setting up the netcup firewall in the SCP (with the stateless-UDP trick)</title><link>https://serverkueche.de/en/tutorials/netcup-firewall-setup/</link><pubDate>Fri, 17 Jul 2026 00:00:00 +0000</pubDate><author>feedback@serverkueche.de (Serverküche)</author><guid>https://serverkueche.de/en/tutorials/netcup-firewall-setup/</guid><description>Set up the netcup firewall as network protection in front of the server: composable policy templates in the SCP – with the trick for stateless UDP (DNS &amp; NTP).</description><content:encoded><![CDATA[<p>netcup comes with a <strong>firewall in front of your server</strong> – in the Server Control Panel,
before a packet even reaches the operating system. Built correctly, it&rsquo;s a strong shield.
But there&rsquo;s a trick many people fail at: the netcup firewall is <strong>stateless for UDP</strong>. This
tutorial shows you a clean, reusable firewall – and why DNS and NTP otherwise suddenly get
stuck.</p>
<h2 id="what-are-we-building">What are we building?</h2>
<p>In the <strong>netcup SCP</strong> we build a network firewall from <strong>composable policy templates</strong>: a
<strong>base</strong> template (that every server needs), one for <strong>SSH</strong>, and one for <strong>web
(HTTP/HTTPS)</strong>. You assign these building blocks to your server as needed – a web server
gets base + SSH + web, a server without a website only base + SSH. By the end, everything
inbound is blocked except what you deliberately allow.</p>
<p>A netcup-specific detail makes the difference: for <strong>UDP the firewall works statelessly</strong> –
which is why services like DNS and NTP need their own inbound rule, otherwise they suddenly
get stuck. Why that is and how the base template solves it is shown in step 2.</p>
<div class="not-prose my-6 rounded-lg border-l-4 p-4 border-sky-300 bg-sky-50 dark:border-sky-800 dark:bg-sky-900/20">
  <p class="mb-1 flex items-center gap-2 font-semibold text-slate-900 dark:text-white">
    <span aria-hidden="true">ℹ️</span>Network firewall ≠ host firewall
  </p>
  <div class="prose-kitchen text-sm">The netcup firewall works in the <strong>network in front of the server</strong> and does <strong>not</strong>
replace the firewall on the server itself (<a href="/en/tutorials/firewall-ufw-setup/">UFW</a>). Both
together are &ldquo;defense in depth&rdquo;: if one layer fails or is misconfigured, the other kicks
in. Feel free to set up both.</div>
</div>
<h2 id="prerequisites">Prerequisites</h2>
<ul>
<li>A netcup server, e.g. your <a href="/en/tutorials/first-steps-netcup-vps/">first VPS</a>.</li>
<li>Your <strong>SCP credentials</strong> (customer number + SCP password from the netcup welcome email –
different from your SSH login).</li>
<li>Clarity about your <strong>SSH port</strong>: the default is <code>22</code>, and it stays that way when
<a href="/en/tutorials/harden-ssh/">hardening SSH</a>. If you changed it elsewhere, use your real
port – otherwise you lock yourself out when activating.</li>
</ul>
<div class="not-prose my-6 overflow-hidden rounded-xl border border-paprika-200 bg-paprika-50 dark:border-paprika-800 dark:bg-paprika-900/20">
  <div class="flex items-center justify-between border-b border-paprika-200 bg-paprika-100 px-4 py-1.5 text-xs font-semibold uppercase tracking-wide text-paprika-700 dark:border-paprika-800 dark:bg-paprika-900/40 dark:text-paprika-300">
    <span>🍳 Recommendation</span>
    <span title="Links marked with * are affiliate links.">Ad</span>
  </div>
  <div class="flex flex-col gap-4 p-4 sm:flex-row sm:items-center sm:justify-between">
    <div>
      <p class="text-lg font-bold text-slate-900 dark:text-white">VPS 1000 G12</p>
      <p class="mt-1 text-sm text-slate-600 dark:text-slate-300">4 vCores · 8 GB RAM · 256 GB NVMe</p>
      <p class="mt-1 text-sm font-semibold text-paprika-700 dark:text-paprika-400">from €10.36/month</p>
      <p class="mt-2 text-sm text-slate-600 dark:text-slate-400">The firewall is included in the SCP with every netcup server.</p>
    </div>
    <a href="https://www.netcup.com/en/server/vps/vps-1000-g12-iv-12m?ref=44083" rel="sponsored noopener" target="_blank"
   class="inline-flex shrink-0 items-center justify-center rounded-lg bg-paprika-600 px-5 py-2.5 font-semibold text-white transition-colors hover:bg-paprika-700">
  Go to netcup →
</a>

  </div><div class="px-4 pb-4"><p class="not-prose my-3 flex flex-wrap items-center gap-x-2 gap-y-1 rounded-lg border border-herb-500/40 bg-herb-50 px-3 py-2 text-sm text-slate-700 dark:bg-herb-900/20 dark:text-slate-200">
  <span>💶 <strong>5 € voucher</strong> for new netcup customers:</span>
  <code class="rounded bg-white px-2 py-0.5 font-mono text-sm font-semibold text-herb-800 dark:bg-slate-800 dark:text-herb-400">36nc17844976032</code>
  <span class="text-xs text-slate-500 dark:text-slate-400">(new customers only, no domains)</span>
</p></div>
</div>

<h2 id="step-by-step">Step by step</h2>
<h3 id="step-1-open-firewall-policies-in-the-scp">Step 1: Open Firewall Policies in the SCP</h3>
<p>Log into the <a href="https://www.servercontrolpanel.de/">Server Control Panel</a> and open the
<strong>Firewall Policies</strong> menu item at the top. Here you create reusable rule sets
(&ldquo;policies&rdquo;) – independent of the individual server. You only assign them later.</p>
<h3 id="step-2-build-the-base-template">Step 2: Build the base template</h3>
<p>Click <strong>Create firewall policy</strong>, give it the name <code>Serverküche Base</code> and, via <strong>Add
rule</strong>, create these four rules – all <strong>INBOUND</strong> and <strong>ACCEPT</strong>:</p>
<table>
	<thead>
			<tr>
					<th>Description</th>
					<th>Protocol</th>
					<th>Source port (Src)</th>
					<th>Destination port (Dst)</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>DNS replies (stateless)</td>
					<td>UDP</td>
					<td><strong>53</strong></td>
					<td>any</td>
			</tr>
			<tr>
					<td>NTP replies (stateless)</td>
					<td>UDP</td>
					<td><strong>123</strong></td>
					<td>any</td>
			</tr>
			<tr>
					<td>ICMP (ping/PMTU)</td>
					<td>ICMP</td>
					<td>–</td>
					<td>–</td>
			</tr>
			<tr>
					<td>ICMPv6 (Neighbor Discovery)</td>
					<td>ICMPv6</td>
					<td>–</td>
					<td>–</td>
			</tr>
	</tbody>
</table>
<p><figure class="my-6"><img src="/en/tutorials/netcup-firewall-setup/netcup-fw-basis-regeln_hu_9e99585f9ae8a8a2.webp" srcset="/en/tutorials/netcup-firewall-setup/netcup-fw-basis-regeln_hu_940a2c430e5ad078.webp 480w, /en/tutorials/netcup-firewall-setup/netcup-fw-basis-regeln_hu_9e99585f9ae8a8a2.webp 768w, /en/tutorials/netcup-firewall-setup/netcup-fw-basis-regeln_hu_9b56e056028b7396.webp 1200w, /en/tutorials/netcup-firewall-setup/netcup-fw-basis-regeln_hu_a4a5b78ddd1de01e.webp 1920w" sizes="(min-width: 768px) 768px, 100vw"
    width="768" height="432"
    data-full="/en/tutorials/netcup-firewall-setup/netcup-fw-basis-regeln_hu_191c700aae76cc67.webp"
    alt="The base template in the netcup SCP with four inbound ACCEPT rules: DNS and NTP via the source port, plus ICMP and ICMPv6" title="The base template: DNS/NTP replies come in via source port 53/123"
    loading="lazy" decoding="async" class="rounded-lg"><figcaption class="mt-2 text-sm text-center text-slate-500 italic">The base template: DNS/NTP replies come in via source port 53/123</figcaption></figure></p>
<p>Two things that make the difference here:</p>
<ul>
<li><strong>DNS/NTP via the <code>Src Port</code>, not the destination port.</strong> Your server <em>queries</em> DNS/NTP
(outbound); the <strong>reply</strong> comes back from port 53 or 123. Because UDP is stateless, you
need this inbound rule – otherwise there&rsquo;s no name resolution and no time
synchronization, even though &ldquo;everything else&rdquo; seems to work.</li>
<li><strong>Never forget ICMPv6.</strong> Without Neighbor Discovery, IPv6 breaks completely. ICMP (v4) on
top is useful for ping and path MTU discovery. netcup&rsquo;s default policy &ldquo;Ping allow&rdquo; does
already cover ICMP – it&rsquo;s deliberately in the base template again so your foundation stays
complete even if you ever remove the netcup defaults.</li>
</ul>
<div class="not-prose my-6 rounded-lg border-l-4 p-4 border-sky-300 bg-sky-50 dark:border-sky-800 dark:bg-sky-900/20">
  <p class="mb-1 flex items-center gap-2 font-semibold text-slate-900 dark:text-white">
    <span aria-hidden="true">ℹ️</span>As soon as one rule exists, netcup blocks the rest automatically
  </p>
  <div class="prose-kitchen text-sm">You do <strong>not</strong> need to create a final &ldquo;block everything&rdquo;. <strong>Without</strong> an assigned policy,
everything inbound is allowed. <strong>But as soon as you assign the server at least one of your
own policies, netcup switches the default to &ldquo;block all&rdquo;</strong> – from then on everything
inbound is blocked that none of your rules explicitly allows. So the whitelist arises on
its own; outbound stays open.</div>
</div>
<div class="not-prose my-6 rounded-lg border-l-4 p-4 border-herb-400 bg-herb-50 dark:border-herb-700 dark:bg-herb-900/20">
  <p class="mb-1 flex items-center gap-2 font-semibold text-slate-900 dark:text-white">
    <span aria-hidden="true">🧑‍🍳</span>Does your server use DHCP?
  </p>
  <div class="prose-kitchen text-sm">netcup VPS are usually configured <strong>statically</strong> (<code>iface … inet static</code>) – then there&rsquo;s
nothing to do here. netcup&rsquo;s network does run a DHCP server, but because UDP is stateless,
the DHCP <strong>reply</strong> (source port <strong>67</strong>) is discarded by the whitelist. If your server is
exceptionally configured via DHCP, add <code>INBOUND · UDP · ACCEPT · Src 67</code> to the base
template (for DHCPv6 additionally <code>Src 547</code>) – otherwise it loses its IP at the next lease
renewal.</div>
</div>
<h3 id="step-3-small-building-blocks-for-ssh-and-web">Step 3: Small building blocks for SSH and web</h3>
<p>Instead of one big rule monolith, you create <strong>atomic templates</strong> that you freely combine.
Create two more policies following the same pattern:</p>
<ul>
<li><strong><code>Serverküche SSH</code></strong> – one rule: INBOUND, TCP, ACCEPT, destination port <strong>22</strong>.</li>
<li><strong><code>Serverküche Web</code></strong> – two rules: INBOUND, TCP, ACCEPT, destination port <strong>80</strong> and
<strong>443</strong>.</li>
</ul>
<p><figure class="my-6"><img src="/en/tutorials/netcup-firewall-setup/netcup-fw-policys_hu_8300974e73f572e.webp" srcset="/en/tutorials/netcup-firewall-setup/netcup-fw-policys_hu_37f1808047787952.webp 480w, /en/tutorials/netcup-firewall-setup/netcup-fw-policys_hu_8300974e73f572e.webp 768w, /en/tutorials/netcup-firewall-setup/netcup-fw-policys_hu_4fba52dd0cbe8f8e.webp 1200w, /en/tutorials/netcup-firewall-setup/netcup-fw-policys_hu_490c02b761af2a0d.webp 1920w" sizes="(min-width: 768px) 768px, 100vw"
    width="768" height="432"
    data-full="/en/tutorials/netcup-firewall-setup/netcup-fw-policys_hu_113b718980b0626c.webp"
    alt="The three composable firewall templates in the netcup SCP overview: base, SSH and web" title="Three small, reusable building blocks instead of one monolith"
    loading="lazy" decoding="async" class="rounded-lg"><figcaption class="mt-2 text-sm text-center text-slate-500 italic">Three small, reusable building blocks instead of one monolith</figcaption></figure></p>
<p>The gain: the base rules appear only <strong>once</strong>, not duplicated in every policy. If a service
is added later (e.g. a mail server or WireGuard), you build another small template for it
and plug it in – without touching the existing ones.</p>
<h3 id="step-4-assign-templates-to-the-server">Step 4: Assign templates to the server</h3>
<p>Switch to <strong>Server → your server → &ldquo;Firewall&rdquo; tab</strong> and click <strong>Edit firewall policies</strong>.
Move the appropriate ones from <strong>Available firewall policies</strong> to <strong>Selected</strong>: for a web
server <code>Serverküche Base</code> + <code>Serverküche SSH</code> + <code>Serverküche Web</code>.</p>
<p><figure class="my-6"><img src="/en/tutorials/netcup-firewall-setup/netcup-fw-zuweisen_hu_b5de2471022cffb5.webp" srcset="/en/tutorials/netcup-firewall-setup/netcup-fw-zuweisen_hu_916fa5dee97d09.webp 480w, /en/tutorials/netcup-firewall-setup/netcup-fw-zuweisen_hu_b5de2471022cffb5.webp 768w, /en/tutorials/netcup-firewall-setup/netcup-fw-zuweisen_hu_2f19ef31e0b0bfcc.webp 1200w, /en/tutorials/netcup-firewall-setup/netcup-fw-zuweisen_hu_1ec7e51f2b6aaab8.webp 1920w" sizes="(min-width: 768px) 768px, 100vw"
    width="768" height="432"
    data-full="/en/tutorials/netcup-firewall-setup/netcup-fw-zuweisen_hu_d021fbd03a3210d1.webp"
    alt="The assignment dialog in the netcup SCP: on the left the available templates, on the right the ones selected for this server" title="Assign = plug together: base &#43; SSH &#43; web on a web server"
    loading="lazy" decoding="async" class="rounded-lg"><figcaption class="mt-2 text-sm text-center text-slate-500 italic">Assign = plug together: base &#43; SSH &#43; web on a web server</figcaption></figure></p>
<p>Confirm with <strong>Apply</strong> and then <strong>Save</strong>. Check that the <strong>&ldquo;Firewall active&rdquo;</strong> switch is
turned on. The assigned rules now appear in the list – together with netcup&rsquo;s <strong>default
policies</strong> (more on those below).</p>
<p><figure class="my-6"><img src="/en/tutorials/netcup-firewall-setup/netcup-fw-server_hu_1b203778eff9dee8.webp" srcset="/en/tutorials/netcup-firewall-setup/netcup-fw-server_hu_8c4daef82bf14989.webp 480w, /en/tutorials/netcup-firewall-setup/netcup-fw-server_hu_1b203778eff9dee8.webp 768w, /en/tutorials/netcup-firewall-setup/netcup-fw-server_hu_aec528535f9a750b.webp 1200w, /en/tutorials/netcup-firewall-setup/netcup-fw-server_hu_dbeac9995b0b9626.webp 1920w" sizes="(min-width: 768px) 768px, 100vw"
    width="768" height="432"
    data-full="/en/tutorials/netcup-firewall-setup/netcup-fw-server_hu_d32ec044e4959b65.webp"
    alt="The server&rsquo;s firewall tab with an active firewall and the assigned rules" title="Firewall active – rules are evaluated top to bottom, the first match wins"
    loading="lazy" decoding="async" class="rounded-lg"><figcaption class="mt-2 text-sm text-center text-slate-500 italic">Firewall active – rules are evaluated top to bottom, the first match wins</figcaption></figure></p>
<div class="not-prose my-6 rounded-lg border-l-4 p-4 border-amber-400 bg-amber-50 dark:border-amber-700 dark:bg-amber-900/20">
  <p class="mb-1 flex items-center gap-2 font-semibold text-slate-900 dark:text-white">
    <span aria-hidden="true">⚠️</span>Don&#39;t lock yourself out
  </p>
  <div class="prose-kitchen text-sm">Only activate the firewall if the <strong>SSH rule</strong> (port 22 or your real port) is in it. During
the switch, keep a <strong>second SSH session open</strong> and open a new connection in parallel to test
access – only once that works do you close the old session. If you can&rsquo;t get in at all, the
VNC console under <strong>Display</strong> in the SCP helps.</div>
</div>
<h3 id="step-5-ready-made-templates-for-common-services">Step 5: Ready-made templates for common services</h3>
<p>Exactly following the pattern from step 3, here are ready-made templates for the most
common self-hosting services. Each is its <strong>own small template</strong>, all rules are <strong>INBOUND</strong>
and <strong>ACCEPT</strong>. Build only the ones you really need and plug them, as in step 4, into
<code>Serverküche Base</code> + <code>Serverküche SSH</code>.</p>
<div class="not-prose my-6 rounded-lg border-l-4 p-4 border-sky-300 bg-sky-50 dark:border-sky-800 dark:bg-sky-900/20">
  <p class="mb-1 flex items-center gap-2 font-semibold text-slate-900 dark:text-white">
    <span aria-hidden="true">ℹ️</span>For UDP services: destination port, not source port
  </p>
  <div class="prose-kitchen text-sm">For UDP services you <strong>offer yourself</strong> (VPN, TURN, your own DNS server), the port is in the
<strong>destination port (Dst)</strong> – because here clients connect <em>to your server</em>. That&rsquo;s the
<strong>opposite</strong> of the DNS/NTP rules from the base template: there the port is in the <strong>source
port (Src)</strong>, because your server is the <em>querying client</em> whose reply comes back. TCP
replies aren&rsquo;t affected by this (the firewall state only matters for UDP); outbound is
allowed anyway.</div>
</div>
<h4 id="mail-server-mailcow--co">Mail server (mailcow &amp; co.)</h4>
<table>
	<thead>
			<tr>
					<th>Description</th>
					<th>Protocol</th>
					<th>Source port (Src)</th>
					<th>Destination port (Dst)</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>SMTP (mail acceptance from others)</td>
					<td>TCP</td>
					<td>–</td>
					<td><strong>25</strong></td>
			</tr>
			<tr>
					<td>Submission (STARTTLS)</td>
					<td>TCP</td>
					<td>–</td>
					<td><strong>587</strong></td>
			</tr>
			<tr>
					<td>Submission (implicit TLS)</td>
					<td>TCP</td>
					<td>–</td>
					<td><strong>465</strong></td>
			</tr>
			<tr>
					<td>IMAP (STARTTLS)</td>
					<td>TCP</td>
					<td>–</td>
					<td><strong>143</strong></td>
			</tr>
			<tr>
					<td>IMAPS</td>
					<td>TCP</td>
					<td>–</td>
					<td><strong>993</strong></td>
			</tr>
			<tr>
					<td>POP3 (STARTTLS)</td>
					<td>TCP</td>
					<td>–</td>
					<td><strong>110</strong></td>
			</tr>
			<tr>
					<td>POP3S</td>
					<td>TCP</td>
					<td>–</td>
					<td><strong>995</strong></td>
			</tr>
			<tr>
					<td>ManageSieve (filter rules)</td>
					<td>TCP</td>
					<td>–</td>
					<td><strong>4190</strong></td>
			</tr>
	</tbody>
</table>
<p>Two things that <strong>additionally</strong> belong to a mail server:</p>
<ul>
<li><strong>Web UI and certificates:</strong> mailcow needs <code>80</code>/<code>443</code> for the web interface and the
Let&rsquo;s Encrypt retrieval – just assign the <code>Serverküche Web</code> template along with it.</li>
<li><strong>Enable outbound SMTP:</strong> a mail server must be able to deliver on <strong>port 25 outbound</strong>.
netcup blocks that with the default policy &ldquo;netcup Mail block&rdquo; – you have to <strong>remove</strong> it
on the server (see &ldquo;When things go wrong&rdquo;). And without a correct
<a href="/en/tutorials/connect-domain-to-server/">PTR/reverse-DNS entry</a> your mails land in spam.</li>
</ul>
<h4 id="wireguard-vpn">WireGuard VPN</h4>
<table>
	<thead>
			<tr>
					<th>Description</th>
					<th>Protocol</th>
					<th>Source port (Src)</th>
					<th>Destination port (Dst)</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>WireGuard</td>
					<td>UDP</td>
					<td>–</td>
					<td><strong>51820</strong></td>
			</tr>
	</tbody>
</table>
<p><code>51820</code> is the usual default – use the value from your <code>ListenPort</code>. Only this one inbound
rule is needed; the replies to the clients go out outbound.</p>
<h4 id="openvpn">OpenVPN</h4>
<table>
	<thead>
			<tr>
					<th>Description</th>
					<th>Protocol</th>
					<th>Source port (Src)</th>
					<th>Destination port (Dst)</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>OpenVPN (UDP, default)</td>
					<td>UDP</td>
					<td>–</td>
					<td><strong>1194</strong></td>
			</tr>
			<tr>
					<td>OpenVPN (TCP fallback)</td>
					<td>TCP</td>
					<td>–</td>
					<td><strong>1194</strong></td>
			</tr>
	</tbody>
</table>
<p>The default is <strong>UDP 1194</strong>. The TCP rule only if you deliberately run OpenVPN over TCP
(some additionally put it on <code>TCP 443</code> to get through restrictive foreign networks) –
otherwise leave it out.</p>
<h4 id="zabbix-monitoring">Zabbix monitoring</h4>
<p>Here it depends on the server&rsquo;s role:</p>
<table>
	<thead>
			<tr>
					<th>Role</th>
					<th>Description</th>
					<th>Protocol</th>
					<th>Destination port (Dst)</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><strong>Monitored host</strong> (Zabbix agent)</td>
					<td>passive checks from the server</td>
					<td>TCP</td>
					<td><strong>10050</strong></td>
			</tr>
			<tr>
					<td><strong>Zabbix server</strong></td>
					<td>trapper (active agents/proxies)</td>
					<td>TCP</td>
					<td><strong>10051</strong></td>
			</tr>
	</tbody>
</table>
<p>The Zabbix server additionally needs <code>80</code>/<code>443</code> for the web frontend (<code>Serverküche Web</code>). If
you run <strong>active</strong> checks, the agent connects outbound to the server on <code>10051</code> – for that,
<strong>no</strong> inbound rule is needed on the agent host.</p>
<h4 id="checkmk">Checkmk</h4>
<table>
	<thead>
			<tr>
					<th>Role</th>
					<th>Description</th>
					<th>Protocol</th>
					<th>Destination port (Dst)</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><strong>Monitored host</strong> (agent)</td>
					<td>agent controller, pull mode</td>
					<td>TCP</td>
					<td><strong>6556</strong></td>
			</tr>
			<tr>
					<td><strong>Checkmk server</strong> (optional)</td>
					<td>agent receiver (push/registration)</td>
					<td>TCP</td>
					<td><strong>8000</strong></td>
			</tr>
			<tr>
					<td><strong>Checkmk server</strong> (optional)</td>
					<td>Livestatus (distributed monitoring)</td>
					<td>TCP</td>
					<td><strong>6557</strong></td>
			</tr>
	</tbody>
</table>
<p>In the <strong>default pull mode</strong>, the Checkmk server fetches the data actively – so it connects
outbound to <code>6556</code> of the agents. Inbound, therefore, only the <strong>monitored host</strong> needs port
<code>6556</code>. The Checkmk server itself gets by with <code>80</code>/<code>443</code> (<code>Serverküche Web</code>); <code>8000</code> and
<code>6557</code> only if you use push mode or distributed monitoring.</p>
<h4 id="coturn--turn-server-nextcloud-talk-matrix">Coturn / TURN server (Nextcloud Talk, Matrix)</h4>
<table>
	<thead>
			<tr>
					<th>Description</th>
					<th>Protocol</th>
					<th>Source port (Src)</th>
					<th>Destination port (Dst)</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>STUN/TURN</td>
					<td>TCP</td>
					<td>–</td>
					<td><strong>3478</strong></td>
			</tr>
			<tr>
					<td>STUN/TURN</td>
					<td>UDP</td>
					<td>–</td>
					<td><strong>3478</strong></td>
			</tr>
			<tr>
					<td>STUN/TURN over TLS</td>
					<td>TCP</td>
					<td>–</td>
					<td><strong>5349</strong></td>
			</tr>
			<tr>
					<td>STUN/TURN over TLS</td>
					<td>UDP</td>
					<td>–</td>
					<td><strong>5349</strong></td>
			</tr>
			<tr>
					<td>Media relay (audio/video)</td>
					<td>UDP</td>
					<td>–</td>
					<td><strong>49152–65535</strong></td>
			</tr>
	</tbody>
</table>
<p>The large UDP relay range is the default – the actual audio/video streams run over it. You
can narrow it in the coturn configuration (<code>min-port</code>/<code>max-port</code>) and then set the firewall
rule to the same, smaller range.</p>
<h4 id="your-own-dns-server-adguard-home-pi-hole-unbound">Your own DNS server (AdGuard Home, Pi-hole, Unbound)</h4>
<table>
	<thead>
			<tr>
					<th>Description</th>
					<th>Protocol</th>
					<th>Source port (Src)</th>
					<th>Destination port (Dst)</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>DNS queries</td>
					<td>UDP</td>
					<td>–</td>
					<td><strong>53</strong></td>
			</tr>
			<tr>
					<td>DNS queries (large replies/TCP)</td>
					<td>TCP</td>
					<td>–</td>
					<td><strong>53</strong></td>
			</tr>
			<tr>
					<td>DNS-over-TLS (DoT)</td>
					<td>TCP</td>
					<td>–</td>
					<td><strong>853</strong></td>
			</tr>
	</tbody>
</table>
<p>Careful, this is exactly the <strong>opposite direction</strong> to the base template: there <code>Src 53</code>
allows the <em>replies</em> to your own DNS queries; here <code>Dst 53</code> allows the <em>queries of foreign
clients</em> to your DNS server. Both exist side by side without problems.</p>
<div class="not-prose my-6 rounded-lg border-l-4 p-4 border-amber-400 bg-amber-50 dark:border-amber-700 dark:bg-amber-900/20">
  <p class="mb-1 flex items-center gap-2 font-semibold text-slate-900 dark:text-white">
    <span aria-hidden="true">⚠️</span>No open resolver
  </p>
  <div class="prose-kitchen text-sm">A globally open recursive DNS server is abused for <strong>DNS amplification attacks</strong>. Restrict
access to your own networks (set the source address in the rule) or offer DNS exclusively
encrypted (DoT/DoH) for registered clients – never open <code>53</code> &ldquo;just quickly&rdquo; for the whole
world.</div>
</div>
<h4 id="remote-database-access-emergency-only">Remote database access (emergency only)</h4>
<table>
	<thead>
			<tr>
					<th>Description</th>
					<th>Protocol</th>
					<th>Source port (Src)</th>
					<th>Destination port (Dst)</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>PostgreSQL</td>
					<td>TCP</td>
					<td>–</td>
					<td><strong>5432</strong></td>
			</tr>
			<tr>
					<td>MySQL / MariaDB</td>
					<td>TCP</td>
					<td>–</td>
					<td><strong>3306</strong></td>
			</tr>
	</tbody>
</table>
<div class="not-prose my-6 rounded-lg border-l-4 p-4 border-paprika-400 bg-paprika-50 dark:border-paprika-700 dark:bg-paprika-900/20">
  <p class="mb-1 flex items-center gap-2 font-semibold text-slate-900 dark:text-white">
    <span aria-hidden="true">🔥</span>Databases don&#39;t belong on the open internet
  </p>
  <div class="prose-kitchen text-sm">A directly reachable database is a preferred attack target. The <strong>right</strong> way is to <strong>not</strong>
open the port at all and instead access it via a <a href="/en/#wireguard-vpn">WireGuard tunnel</a> or an
SSH tunnel (<code>ssh -L 5432:localhost:5432 …</code>). If you must open the port anyway, then <strong>only</strong>
with a source address restricted to your fixed admin IP in the netcup rule – never for
everyone.</div>
</div>
<h2 id="when-things-go-wrong">When things go wrong</h2>
<div class="troubleshoot not-prose">
<p><strong>After activating, name resolution stops working (<code>apt update</code> hangs, <code>ping domain.de</code>
fails, but <code>ping 1.1.1.1</code> works).</strong> The DNS <strong>replies</strong> are being blocked. Check the rule in
the base template <em>INBOUND UDP ACCEPT, Src port 53</em>. Important: <strong>source</strong> port, not
destination port.</p>
<p><strong>The clock drifts, or TLS certificates are rejected due to the wrong time.</strong> The NTP
replies are missing. Add <em>INBOUND UDP ACCEPT, Src port 123</em>.</p>
<p><strong>IPv6 no longer works (v4 does).</strong> The <strong>ICMPv6</strong> rule is missing. Without Neighbor
Discovery, the server can&rsquo;t even find its neighbor (router) over IPv6.</p>
<p><strong>After activating, you can no longer get in via SSH.</strong> The SSH rule is missing or names the
wrong port. Via the <strong>VNC console</strong> (SCP → Display) you can still reach the server; correct
the policy and save again. That&rsquo;s exactly what the &ldquo;keep a second session open&rdquo; rule above
helps against.</p>
<p><strong>The server can&rsquo;t send emails (outbound port 25 doesn&rsquo;t work).</strong> That&rsquo;s <strong>not</strong> an error in
your policy, but netcup&rsquo;s <strong>default policy &ldquo;netcup Mail block&rdquo;</strong> – it blocks outbound SMTP
(ports 25/465/587) as spam protection. For real mail sending you have to disable this netcup
template on the server.</p>
<p><strong>The server initially runs normally and is suddenly offline after one or two weeks.</strong> If
the server uses DHCP, the <strong>lease renewal</strong> is blocked by the whitelist – the DHCP reply
comes from UDP source port <strong>67</strong>, which no rule allows, and UDP is stateless. Add <code>INBOUND · UDP · ACCEPT · Src 67</code> to the base template. Statically configured netcup VPS (the
default) aren&rsquo;t affected.</p>

</div>

<h2 id="maintenance--backups">Maintenance &amp; backups</h2>
<ul>
<li><strong>Test access after every change.</strong> Firewall rules are the classic way to lock yourself
out. Keep a second session open, check a new connection, only then finish.</li>
<li><strong>New services = new template.</strong> If you later need another port (game server, WireGuard
VPN over UDP, database), create a small template of your own and assign it additionally.
The existing building blocks stay untouched.</li>
<li><strong>Mind the order.</strong> netcup evaluates the rules <strong>top to bottom</strong>; the <strong>first</strong> matching
rule wins. For pure ACCEPT rules that doesn&rsquo;t matter – but as soon as you use your own DROP
rules, watch the order relative to the ACCEPTs.</li>
<li><strong>Know netcup&rsquo;s default policies.</strong> &ldquo;netcup Mail block&rdquo; (outbound SMTP on ports 25/465/587
blocked) and &ldquo;netcup Ping allow&rdquo; are predefined. Via <strong>Restore default policies</strong> you can,
in an emergency, get back to a known, working baseline if you locked yourself out with your
own rules – together with the VNC console, your second safety net.</li>
</ul>
]]></content:encoded></item></channel></rss>