<?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>Iptables on DevOps Way - Практические гайды</title>
    <link>https://devopsway.ru/tags/iptables/</link>
    <description>Recent content in Iptables on DevOps Way - Практические гайды</description>
    <image>
      <title>DevOps Way - Практические гайды</title>
      <url>https://devopsway.ru/images/devopsway-og.png</url>
      <link>https://devopsway.ru/images/devopsway-og.png</link>
    </image>
    <generator>Hugo -- 0.164.0</generator>
    <language>ru</language>
    <lastBuildDate>Sat, 08 Aug 2026 15:31:17 +0300</lastBuildDate>
    <atom:link href="https://devopsway.ru/tags/iptables/feed.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Networking 20/80, уровень 5: Firewall и сетевая безопасность</title>
      <link>https://devopsway.ru/posts/networking-05-firewall/</link>
      <pubDate>Sat, 08 Aug 2026 14:00:00 +0300</pubDate>
      <guid>https://devopsway.ru/posts/networking-05-firewall/</guid>
      <description>Шестой уровень: iptables (таблицы, цепочки, правила и почему их порядок критичен), DROP против REJECT, Kubernetes NetworkPolicy, Security Groups в облаках, чеклист диагностики межсетевого экрана. Подвохи с собеса и код-челлендж на написание NetworkPolicy.</description>
      <content:encoded><![CDATA[<p>Шестой из семи уровней. Ты умеешь пускать трафик – теперь про то, как его фильтровать. Межсетевой экран (firewall) – не &quot;стена&quot;, а решение для каждого пакета: пропустить, отбросить молча или отказать явно. Разница между DROP и REJECT однажды сэкономит тебе час отладки &quot;зависшего&quot; клиента.</p>
<blockquote>
<p>&quot;Межсетевой экран – не стена, а фильтр. Он не &quot;блокирует всё&quot;, а решает для каждого пакета: пропустить (ACCEPT), отбросить молча (DROP) или отказать явно (REJECT).&quot;</p>
</blockquote>
<hr>
<h2 id="откуда-это-пошло">Откуда это пошло</h2>
<p><strong>1988 – первый сетевой червь</strong> (Morris Worm). Заразил ~6000 машин из ~60000 подключённых к интернету. Мир осознал: сети нужна защита.</p>
<p><strong>1989–1992 – пакетные фильтры (packet filter firewalls).</strong> DEC, AT&amp;T Bell Labs. Идея: проверять каждый пакет по набору правил (src/dst IP, порт, протокол). Если правило совпало – пропустить или заблокировать.</p>
<p><strong>1998 – iptables</strong> (Rusty Russell). Замена ipchains, в ядре с Linux 2.4 (2001). Стал стандартом на 20 лет. Netfilter – подсистема ядра, iptables – интерфейс к ней.</p>
<p><strong>2014 – nftables.</strong> Замена iptables: единый синтаксис, лучшая производительность, атомарные обновления. В 2026 году – стандарт в RHEL 9, Debian 12.</p>
<p><strong>2017 – Kubernetes NetworkPolicy.</strong> Межсетевой экран как код: YAML вместо правил iptables. Calico, Cilium – реализации.</p>
<hr>
<h2 id="iptables--фундамент-до-сих-пор-на-собесах">iptables – фундамент (до сих пор на собесах)</h2>
<h3 id="архитектура-таблицы--цепочки--правила">Архитектура: таблицы → цепочки → правила</h3>
<p>Пакет проходит через цепочки Netfilter в строгом порядке – на каждой его можно отфильтровать или подменить ему адрес:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">Пакет приходит
</span></span><span class="line"><span class="cl">      │
</span></span><span class="line"><span class="cl">      ▼
</span></span><span class="line"><span class="cl">┌─────────────┐
</span></span><span class="line"><span class="cl">│  PREROUTING │  ← DNAT (подменить dst IP)
</span></span><span class="line"><span class="cl">└──────┬──────┘
</span></span><span class="line"><span class="cl">       │
</span></span><span class="line"><span class="cl">  ┌────▼────┐   Для этого хоста?
</span></span><span class="line"><span class="cl">  │ Routing │───── Нет ──→ FORWARD → POSTROUTING → наружу
</span></span><span class="line"><span class="cl">  └────┬────┘                  (транзит: хост как роутер)
</span></span><span class="line"><span class="cl">       │ Да
</span></span><span class="line"><span class="cl">       ▼
</span></span><span class="line"><span class="cl">┌──────────────┐
</span></span><span class="line"><span class="cl">│    INPUT     │  ← фильтрация входящего трафика
</span></span><span class="line"><span class="cl">└──────┬───────┘
</span></span><span class="line"><span class="cl">       │
</span></span><span class="line"><span class="cl">   [Приложение]
</span></span><span class="line"><span class="cl">       │
</span></span><span class="line"><span class="cl">       ▼
</span></span><span class="line"><span class="cl">┌──────────────┐
</span></span><span class="line"><span class="cl">│    OUTPUT    │  ← фильтрация исходящего трафика
</span></span><span class="line"><span class="cl">└──────┬───────┘
</span></span><span class="line"><span class="cl">       ▼
</span></span><span class="line"><span class="cl">┌──────────────┐
</span></span><span class="line"><span class="cl">│ POSTROUTING  │  ← SNAT/MASQUERADE (подменить src IP)
</span></span><span class="line"><span class="cl">└──────────────┘
</span></span></code></pre></div><p>Практическое правило: свои порты закрываешь в <strong>INPUT</strong>, а Docker/K8s и NAT живут в <strong>FORWARD</strong> и <strong>POSTROUTING</strong>. Транзитный трафик (когда хост работает маршрутизатором) минует INPUT/OUTPUT.</p>
<h3 id="базовые-команды">Базовые команды</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Показать все правила:</span>
</span></span><span class="line"><span class="cl">sudo iptables -L -n -v --line-numbers
</span></span><span class="line"><span class="cl"><span class="c1"># -L = list, -n = числовые адреса, -v = verbose, --line-numbers = номера</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Показать NAT-правила:</span>
</span></span><span class="line"><span class="cl">sudo iptables -t nat -L -n -v
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Разрешить ответы на уже установленные соединения – СТАВИТЬ ПЕРВЫМ</span>
</span></span><span class="line"><span class="cl"><span class="c1"># (большинство пакетов попадёт сюда и не будет проверять правила ниже):</span>
</span></span><span class="line"><span class="cl">sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
</span></span><span class="line"><span class="cl"><span class="c1"># (-m state --state ESTABLISHED,RELATED – устаревший синоним, всё ещё работает)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Разрешить SSH (порт 22):</span>
</span></span><span class="line"><span class="cl">sudo iptables -A INPUT -p tcp --dport <span class="m">22</span> -j ACCEPT
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Разрешить HTTP/HTTPS:</span>
</span></span><span class="line"><span class="cl">sudo iptables -A INPUT -p tcp --dport <span class="m">80</span> -j ACCEPT
</span></span><span class="line"><span class="cl">sudo iptables -A INPUT -p tcp --dport <span class="m">443</span> -j ACCEPT
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Заблокировать всё остальное (доходят только новые входящие, не покрытые выше):</span>
</span></span><span class="line"><span class="cl">sudo iptables -A INPUT -j DROP
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Удалить правило по номеру:</span>
</span></span><span class="line"><span class="cl">sudo iptables -D INPUT <span class="m">3</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Сбросить все правила:</span>
</span></span><span class="line"><span class="cl">sudo iptables -F
</span></span></code></pre></div><h3 id="порядок-правил--критически-важен">Порядок правил – КРИТИЧЕСКИ ВАЖЕН</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># ПРАВИЛА ПРОВЕРЯЮТСЯ СВЕРХУ ВНИЗ, ПЕРВОЕ СОВПАДЕНИЕ ПОБЕЖДАЕТ</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Правильно:</span>
</span></span><span class="line"><span class="cl">iptables -A INPUT -p tcp --dport <span class="m">22</span> -j ACCEPT     <span class="c1"># 1. SSH – ОК</span>
</span></span><span class="line"><span class="cl">iptables -A INPUT -p tcp --dport <span class="m">80</span> -j ACCEPT     <span class="c1"># 2. HTTP – ОК</span>
</span></span><span class="line"><span class="cl">iptables -A INPUT -j DROP                          <span class="c1"># 3. Всё остальное – DROP</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Неправильно (заблокирует ВСЁ, включая SSH):</span>
</span></span><span class="line"><span class="cl">iptables -A INPUT -j DROP                          <span class="c1"># 1. DROP всё ← !!! SSH тоже</span>
</span></span><span class="line"><span class="cl">iptables -A INPUT -p tcp --dport <span class="m">22</span> -j ACCEPT     <span class="c1"># 2. Никогда не достигнется</span>
</span></span></code></pre></div><blockquote>
<p><strong>20/80:</strong> 90% iptables работы – это цепочка INPUT с ACCEPT для нужных портов и DROP/REJECT по умолчанию.</p>
</blockquote>
<hr>
<h2 id="drop-против-reject--почему-это-важно">DROP против REJECT – почему это важно</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># DROP – молча отбросить пакет:</span>
</span></span><span class="line"><span class="cl">iptables -A INPUT -p tcp --dport <span class="m">8080</span> -j DROP
</span></span><span class="line"><span class="cl"><span class="c1"># Клиент: &#34;Connection timed out&#34; (ждёт 30+ секунд)</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Атакующий: не знает, есть ли хост</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># REJECT – отправить RST/ICMP:</span>
</span></span><span class="line"><span class="cl">iptables -A INPUT -p tcp --dport <span class="m">8080</span> -j REJECT
</span></span><span class="line"><span class="cl"><span class="c1"># Клиент: &#34;Connection refused&#34; (мгновенно)</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Атакующий: знает, что хост жив</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Рекомендация:</span>
</span></span><span class="line"><span class="cl"><span class="c1"># - Внешний firewall (internet-facing): DROP (не раскрывать информацию)</span>
</span></span><span class="line"><span class="cl"><span class="c1"># - Внутренний firewall (между сервисами): REJECT (быстрая диагностика)</span>
</span></span></code></pre></div><hr>
<h2 id="kubernetes-networkpolicy">Kubernetes NetworkPolicy</h2>
<h3 id="без-networkpolicy--всё-открыто">Без NetworkPolicy – всё открыто</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">По умолчанию в K8s: ЛЮБОЙ pod может общаться с ЛЮБЫМ pod-ом.
</span></span><span class="line"><span class="cl">Это как офис без дверей – удобно, но небезопасно.
</span></span></code></pre></div><h3 id="с-networkpolicy--белый-список-whitelist">С NetworkPolicy – белый список (whitelist)</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="c"># Разрешить трафик к api ТОЛЬКО от frontend (namespace=prod):</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">networking.k8s.io/v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">NetworkPolicy</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">api-allow-frontend</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">namespace</span><span class="p">:</span><span class="w"> </span><span class="l">prod</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">podSelector</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">matchLabels</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">app</span><span class="p">:</span><span class="w"> </span><span class="l">api                 </span><span class="w"> </span><span class="c"># применяется к pod-ам с label app=api</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">policyTypes</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">Ingress</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">ingress</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">from</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">podSelector</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">matchLabels</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">app</span><span class="p">:</span><span class="w"> </span><span class="l">frontend    </span><span class="w"> </span><span class="c"># разрешить от frontend</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">ports</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">protocol</span><span class="p">:</span><span class="w"> </span><span class="l">TCP</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">port</span><span class="p">:</span><span class="w"> </span><span class="m">8080</span><span class="w">
</span></span></span></code></pre></div><h3 id="типичные-networkpolicy-для-devops">Типичные NetworkPolicy для DevOps</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="c"># 1. Deny all ingress (потом разрешать явно):</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">networking.k8s.io/v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">NetworkPolicy</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">deny-all-ingress</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">namespace</span><span class="p">:</span><span class="w"> </span><span class="l">prod</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">podSelector</span><span class="p">:</span><span class="w"> </span>{}<span class="w">               </span><span class="c"># все pod-ы в namespace</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">policyTypes</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">Ingress                  </span><span class="w"> </span><span class="c"># блокировать входящий</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># ingress: [] – пустой список = ничего не разрешено</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nn">---</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c"># 2. Egress ТОЛЬКО на DNS. ВНИМАНИЕ: в одиночку эта политика отрежет ВЕСЬ</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c">#    остальной исходящий трафик у выбранных pod-ов. Применять в паре с</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c">#    default-deny-egress как &#34;дырку&#34; для DNS (иначе pod-ы не резолвят имена):</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">networking.k8s.io/v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">NetworkPolicy</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">allow-dns</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">namespace</span><span class="p">:</span><span class="w"> </span><span class="l">prod</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">podSelector</span><span class="p">:</span><span class="w"> </span>{}<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">policyTypes</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">Egress</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">egress</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">to</span><span class="p">:</span><span class="w"> </span><span class="p">[]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">ports</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">protocol</span><span class="p">:</span><span class="w"> </span><span class="l">UDP</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">port</span><span class="p">:</span><span class="w"> </span><span class="m">53</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">protocol</span><span class="p">:</span><span class="w"> </span><span class="l">TCP</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">port</span><span class="p">:</span><span class="w"> </span><span class="m">53</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nn">---</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c"># 3. Разрешить трафик из monitoring namespace:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">networking.k8s.io/v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">NetworkPolicy</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">allow-prometheus-scrape</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">namespace</span><span class="p">:</span><span class="w"> </span><span class="l">prod</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">podSelector</span><span class="p">:</span><span class="w"> </span>{}<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">policyTypes</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">Ingress</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">ingress</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">from</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">namespaceSelector</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">matchLabels</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">kubernetes.io/metadata.name</span><span class="p">:</span><span class="w"> </span><span class="l">monitoring</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">ports</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">protocol</span><span class="p">:</span><span class="w"> </span><span class="l">TCP</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">port</span><span class="p">:</span><span class="w"> </span><span class="m">9090</span><span class="w">
</span></span></span></code></pre></div><blockquote>
<p><strong>Важно:</strong> NetworkPolicy работает только если CNI-плагин поддерживает их. <strong>Calico</strong>, <strong>Cilium</strong> – поддерживают. Flannel – НЕ поддерживает (политика создастся, но действовать не будет).</p>
</blockquote>
<hr>
<h2 id="security-groups-облака--межсетевой-экран-для-виртуальных-машин-vm">Security Groups (облака) – межсетевой экран для виртуальных машин (VM)</h2>
<table>
	<thead>
			<tr>
					<th>Правило Security Group (AWS)</th>
					<th>Эквивалент в iptables</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Inbound: TCP 22 из 0.0.0.0/0</td>
					<td><code>iptables -A INPUT -p tcp --dport 22 -j ACCEPT</code></td>
			</tr>
			<tr>
					<td>Inbound: TCP 80 из 0.0.0.0/0</td>
					<td><code>iptables -A INPUT -p tcp --dport 80 -j ACCEPT</code></td>
			</tr>
			<tr>
					<td>Inbound: TCP 8080 из 10.0.0.0/16</td>
					<td><code>iptables -A INPUT -s 10.0.0.0/16 -p tcp --dport 8080 -j ACCEPT</code></td>
			</tr>
			<tr>
					<td>Outbound: всё из 0.0.0.0/0</td>
					<td><code>iptables -A OUTPUT -j ACCEPT</code></td>
			</tr>
	</tbody>
</table>
<p><strong>Ключевое отличие от iptables:</strong></p>
<ul>
<li>Security Groups – <strong>с учётом состояния (stateful)</strong>: если разрешён входящий TCP 80, ответные пакеты автоматически разрешены</li>
<li>iptables по умолчанию – <strong>без учёта состояния (stateless)</strong>: нужно явно разрешать <code>ESTABLISHED,RELATED</code></li>
</ul>
<hr>
<h2 id="диагностика-межсетевого-экрана--чеклист">Диагностика межсетевого экрана – чеклист</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 1. Проверить, есть ли подключение БЕЗ firewall:</span>
</span></span><span class="line"><span class="cl">nc -zv target-host <span class="m">8080</span>
</span></span><span class="line"><span class="cl"><span class="c1"># timeout → firewall DROP или хост недоступен</span>
</span></span><span class="line"><span class="cl"><span class="c1"># refused → порт не слушает (firewall не при чём)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 2. Проверить iptables INPUT:</span>
</span></span><span class="line"><span class="cl">sudo iptables -L INPUT -n -v --line-numbers <span class="p">|</span> grep <span class="m">8080</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Если нет правила ACCEPT для порта → заблокировано</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 3. Проверить K8s NetworkPolicy:</span>
</span></span><span class="line"><span class="cl">kubectl get networkpolicy -n prod
</span></span><span class="line"><span class="cl">kubectl describe networkpolicy api-allow-frontend -n prod
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 4. Снять блокировку для диагностики (ТОЛЬКО временно, ОПАСНО в production!):</span>
</span></span><span class="line"><span class="cl">sudo iptables -F INPUT           <span class="c1"># сбросить ВСЕ правила цепочки INPUT</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Осторожно: &#34;iptables -P INPUT ACCEPT&#34; меняет лишь политику по умолчанию и НЕ</span>
</span></span><span class="line"><span class="cl"><span class="c1"># поможет, если трафик режется явным правилом &#34;-j DROP&#34; (оно сработает раньше)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 5. Логировать отбрасываемые пакеты. LOG не терминальный, поэтому пару</span>
</span></span><span class="line"><span class="cl"><span class="c1">#    &#34;LOG, затем DROP&#34; добавляют в КОНЕЦ цепочки – LOG обязан идти ПЕРЕД DROP,</span>
</span></span><span class="line"><span class="cl"><span class="c1">#    иначе пакет отбросится раньше, чем залогируется:</span>
</span></span><span class="line"><span class="cl">sudo iptables -A INPUT -j LOG --log-prefix <span class="s2">&#34;DROPPED: &#34;</span> --log-level <span class="m">4</span>
</span></span><span class="line"><span class="cl">sudo iptables -A INPUT -j DROP
</span></span><span class="line"><span class="cl"><span class="c1"># Логи: dmesg | grep DROPPED</span>
</span></span></code></pre></div><hr>
<h2 id="подвохи-для-собеса">Подвохи для собеса</h2>
<h3 id="подвох-1-чем-iptables-отличается-от-security-groups">Подвох 1: &quot;Чем iptables отличается от Security Groups?&quot;</h3>
<table>
	<thead>
			<tr>
					<th></th>
					<th>iptables</th>
					<th>Security Groups</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><strong>Где</strong></td>
					<td>Linux-хост</td>
					<td>Облачная ВМ (AWS, GCP, Azure)</td>
			</tr>
			<tr>
					<td><strong>Учёт состояния</strong></td>
					<td>Без состояния (stateless)</td>
					<td>С учётом состояния (stateful)</td>
			</tr>
			<tr>
					<td><strong>Управление</strong></td>
					<td>CLI (<code>iptables -A</code>)</td>
					<td>API / консоль</td>
			</tr>
			<tr>
					<td><strong>Сохранность</strong></td>
					<td>Не сохраняется при перезагрузке</td>
					<td>Сохраняется всегда</td>
			</tr>
			<tr>
					<td><strong>Детализация</strong></td>
					<td>Пакет, интерфейс, цепочка</td>
					<td>Только правила входящего/исходящего</td>
			</tr>
			<tr>
					<td><strong>Производительность</strong></td>
					<td>Деградирует при &gt;10K правил</td>
					<td>Оптимизировано облаком</td>
			</tr>
	</tbody>
</table>
<p><strong>На собесе:</strong> &quot;iptables – межсетевой экран на уровне хоста (host-level) в ядре Linux, без учёта состояния (stateless) по умолчанию, требует явного разрешения ответных пакетов. Security Groups – облачный межсетевой экран, с учётом состояния (stateful), автоматически разрешает ответы. В K8s NetworkPolicy – ещё один уровень, работающий на уровне подов (pod-level) через CNI (Calico/Cilium).&quot;</p>
<hr>
<h3 id="подвох-2-почему-после-добавления-networkpolicy-pod-перестал-работать">Подвох 2: &quot;Почему после добавления NetworkPolicy pod перестал работать?&quot;</h3>
<p><strong>Ответ:</strong></p>
<p>NetworkPolicy – <strong>белый список (whitelist)</strong>. Как только хотя бы одна NetworkPolicy применяется к pod-у, <strong>весь не-описанный трафик блокируется</strong>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="c"># Добавили deny-all → pod не может:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c"># - резолвить DNS (нет egress на UDP 53)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c"># - ходить к другим сервисам (нет egress rules)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c"># - получать health check от kubelet (нет ingress от node)</span><span class="w">
</span></span></span></code></pre></div><p><strong>Частые ошибки:</strong></p>
<ol>
<li>Забыли разрешить DNS (UDP 53)</li>
<li>Забыли разрешить проверку живости (health check) от kubelet</li>
<li>Забыли разрешить egress к внешним сервисам</li>
<li>Неправильный селектор меток (label selector) – политика не применяется к нужным pod-ам</li>
</ol>
<p><strong>На собесе:</strong> &quot;NetworkPolicy – аддитивный белый список (additive whitelist). Первая политика блокирует всё неявное. Типичная ошибка – забыть DNS egress: pod не может резолвить имена и все HTTP-вызовы падают с &quot;Name or service not known&quot;, хотя это проблема сети, а не DNS.&quot;</p>
<hr>
<h2 id="код-челлендж">Код-челлендж</h2>
<p><strong>Задача:</strong> напиши Kubernetes NetworkPolicy, которая:</p>
<ol>
<li>Применяется к pod-ам с меткой (label) <code>app: database</code> в namespace <code>prod</code></li>
<li>Разрешает ingress ТОЛЬКО от pod-ов с меткой <code>app: api</code> на порту TCP 5432</li>
<li>Разрешает ingress от Prometheus (namespace <code>monitoring</code>) на порту TCP 9187</li>
<li>Блокирует весь остальной ingress</li>
</ol>
<details>
<summary>Решение</summary>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">networking.k8s.io/v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">NetworkPolicy</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">database-ingress</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">namespace</span><span class="p">:</span><span class="w"> </span><span class="l">prod</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">podSelector</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">matchLabels</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">app</span><span class="p">:</span><span class="w"> </span><span class="l">database</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">policyTypes</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">Ingress</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">ingress</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># Разрешить API → Database:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">from</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">podSelector</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">matchLabels</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">app</span><span class="p">:</span><span class="w"> </span><span class="l">api</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">ports</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">protocol</span><span class="p">:</span><span class="w"> </span><span class="l">TCP</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">port</span><span class="p">:</span><span class="w"> </span><span class="m">5432</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># Разрешить Prometheus → Database (metrics):</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">from</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">namespaceSelector</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">matchLabels</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">kubernetes.io/metadata.name</span><span class="p">:</span><span class="w"> </span><span class="l">monitoring</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">ports</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">protocol</span><span class="p">:</span><span class="w"> </span><span class="l">TCP</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">port</span><span class="p">:</span><span class="w"> </span><span class="m">9187</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># Всё остальное неявно заблокировано</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># (потому что policyTypes содержит Ingress)</span><span class="w">
</span></span></span></code></pre></div></details>
<hr>
<h2 id="дальше--уровень-6">Дальше → Уровень 6</h2>
<p>Ты умеешь настраивать межсетевой экран: iptables для хостов, NetworkPolicy для K8s. Понимаешь DROP против REJECT, разницу &quot;с учётом состояния&quot; и &quot;без&quot; (stateful/stateless), подход белого списка (whitelist).</p>
<p>Но в проде трафик идёт не напрямую к pod-у. Между клиентом и приложением – балансировщик нагрузки (L4 или L7), обратный прокси (reverse proxy, nginx), Ingress-контроллер. В сервисной сетке (service mesh) – ещё и прокси-контейнер (sidecar, Envoy). Как всё это работает вместе?</p>
<p><strong>→ Уровень 6: Балансировка нагрузки и сети Kubernetes</strong></p>
]]></content:encoded>
    </item>
  </channel>
</rss>
