Visas sistēmas darbojas Tavs IP: 216.73.216.190 info@cloudhosting.lv +371 66 66 29 69 Klientu zona

← Visi jautājumi

AlmaLinux 9 ugunsmūris: firewalld un nftables

Svaigi uzlikts AlmaLinux 9 serveris startē ar ieslēgtu firewalld un praktiski aizvērtiem portiem, un pirmā doma daudziem administratoriem ir to izslēgt, lai lietotne beidzot atbild. Uz mašīnas ar publisku IP adresi šī doma maksā vairāk, nekā ietaupa. Atvērt tieši to, kas vajadzīgs, aizņem apmēram minūti, bet izdarīt to caur SSH, nepazaudējot pieeju, prasa vienu papildu komandu.

Kas AlmaLinux 9 patiesībā strādā

Trīs slāņi, kurus regulāri sajauc. firewalld 1.x ir politikas dēmons, ko jūs labojat, nftables ir tas, kurā politika tiek kompilēta, netfilter ir kodola āķis, kas to izpilda. EL9 noklusējuma aizmugursistēma ir nftables (FirewallBackend=nftables failā /etc/firewalld/firewalld.conf), un tajā pašā failā joprojām var izvēlēties arī iptables aizmugursistēmu, kas skaitās novecojusi un nākotnē tiks izņemta. Savukārt iptables komandas, ko varbūt atceraties, ir savietojamības slānis (iptables-nft), kas RHEL 9 un tā atvasinājumos arī skaitās novecojis. Vecais iptables binārais fails, kas nestrādāja caur nft, no distributīva ir izņemts, tāpēc CentOS 7 pamācībai ar service iptables save vairs nav ar ko runāt.

systemctl is-active firewalld
firewall-cmd --state
firewall-cmd --version

Minimālajās instalācijās un mākoņa instancēs firewalld dažkārt vispār nav. Ja firewall-cmd trūkst, palaidiet dnf install firewalld un systemctl enable --now firewalld. Palaišana parasti sesiju nepārtrauc, jo noklusējuma zona public atļauj ssh servisu, tomēr pārbaudiet --list-all pirms termināļa aizvēršanas, nevis pēc tās.

Zonas un kāpēc uz VPS svarīga ir tikai public

Zona ir nosaukts kārtulu komplekts, kas piesaistīts saskarnēm vai avota adresēm. AlmaLinux 9 katru jaunu saskarni ievieto zonā public; pārējās zonas domātas portatīvajiem datoriem un maršrutētājiem, kas pārvietojas starp tīkliem. Uz VPS ar vienu tīkla karti public būs vienīgā, ko aiztiksiet.

firewall-cmd --get-default-zone
firewall-cmd --get-active-zones
firewall-cmd --zone=public --list-all

Slazds: firewall-cmd --list-all bez --zone rāda noklusējuma zonu, kas ne vienmēr ir tā zona, kurā patiesībā atrodas jūsu saskarne. Pārbaudiet ar --get-active-zones. Piesaisti pārvalda NetworkManager, tāpēc saskarni pārceļ tur, un vispirms noskaidrojiet profila nosaukumu: EL9 NetworkManager profilus glabā mapē /etc/NetworkManager/system-connections, nevis vecajā /etc/sysconfig/network-scripts, un profila nosaukums parasti atbilst ierīcei (ens3, eth0) vai ir "Wired connection 1", nevis "System eth0" kā EL6 un EL7 laikos. Pēdējā komanda profilu aktivizē no jauna, un saskarne uz brīdi nokrīt, tāpēc dariet to, kad hostinga paneļa konsole ir pa rokai.

nmcli -g NAME connection show
nmcli connection modify "Wired connection 1" connection.zone internal
nmcli connection up "Wired connection 1"

Viena firewalld 1.0 izmaiņa sāp tiem, kas pārceļ vecas konfigurācijas: zonu dreifs ir noņemts, tāpēc pakete, kas atbilst uz avota adresi balstītai zonai, tiek apstrādāta tikai tajā zonā un vairs neaizkrīt līdz saskarnes zonai. Vienīgā tiešām noderīgā otrā zona uz VPS ir privātā saskarne zonā internal, kur datubāze atvērta tikai tur un nekur citur.

Kā atvērt to, kas vajadzīgs

firewall-cmd --permanent --zone=public --add-service=http
firewall-cmd --permanent --zone=public --add-service=https
firewall-cmd --reload

--permanent ieraksta /etc/firewalld/zones/public.xml un aktīvo kārtulu kopu neskar, --reload to piemēro. Aizmirstiet --permanent, un kārtula pazudīs pēc pārstartēšanas. Aizmirstiet --reload, un tā sāks strādāt tikai pēc nākamās pārstartēšanas. Lielākā daļa pieteikumu stilā "atvēru portu, bet savienojums joprojām tiek noraidīts" ir viens no šiem diviem gadījumiem.

firewall-cmd --permanent --zone=public --add-port=8443/tcp
firewall-cmd --permanent --zone=public --add-port=30000-30010/udp
firewall-cmd --reload

Servisi ir vienkārši XML faili mapē /usr/lib/firewalld/services. Savs serviss ļauj zonu izlasīt arī pēc pusgada:

firewall-cmd --permanent --new-service=nodeapp
firewall-cmd --permanent --service=nodeapp --set-short="Node app"
firewall-cmd --permanent --service=nodeapp --add-port=3000/tcp
firewall-cmd --reload
firewall-cmd --permanent --zone=public --add-service=nodeapp
firewall-cmd --reload

Pirmais reload nav pārrakstīšanās: firewalld pārbauda servisa nosaukumu brīdī, kad zona uz to atsaucas, tāpēc definīcijai jau jābūt ielādētai. Noņemšanai kalpo --remove-service un --remove-port. Savukārt --runtime-to-permanent saglabā visu, kas šobrīd ir aktīvs, un tas ir rupjš instruments: tas saglabās arī pagaidu kārtulu, ko pievienojāt atkļūdošanai.

Kā ierobežot portu uz vienu avotu

Parasts --add-port atver portu visam internetam. Datubāzei vai monitoringa aģentam paplašinātā kārtula (rich rule) to ierobežo līdz vienam avotam:

firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="203.0.113.10/32" port port="5432" protocol="tcp" accept'
firewall-cmd --reload
firewall-cmd --zone=public --list-rich-rules

Divas biežas kļūdas. Ja 5432 joprojām ir parastajā portu sarakstā, rich rule neko nemaina, jo portu kārtula jau pieņem savienojumus no visurienes: pārbaudiet --list-ports un noņemiet to. Un family="ipv4" attiecas tikai uz IPv4, bet jūsu VPS gandrīz noteikti ir arī maršrutējama IPv6 adrese, tāpēc pievienojiet atbilstošu kārtulu ar family="ipv6", citādi ierobežojums ir tikai puse ierobežojuma. Ja rich rule nesatur adresi, family atribūts nav vajadzīgs un kārtula sedz abus protokolus:

firewall-cmd --permanent --zone=public --add-rich-rule='rule service name="ssh" accept limit value="10/m"'
firewall-cmd --reload

Šis ierobežojums sāk darboties tikai tad, kad no zonas ir izņemts parastais serviss ssh, tā paša iemesla dēļ, kas iepriekš aprakstīts portam 5432. Izņemiet to tikai ar nākamajā sadaļā aprakstīto drošības tīklu, nekad vienkārši tāpat.

Kārtulu secība zonā nav tā, kādā tās ievadījāt: ar vienādu prioritāti firewalld vispirms piemēro žurnalēšanas kārtulas, tad aizliegumus, tad atļaujas, tāpēc rich rule ar aizliegumu ņem virsroku pār parastu --add-service. Precīzai kontrolei izmantojiet atribūtu priority. Lai redzētu, kas tiek noraidīts:

firewall-cmd --set-log-denied=all
journalctl -k -f

Kad esat beiguši, atgrieziet firewall-cmd --set-log-denied=off, citādi uz publiskas adreses žurnāls piepildās ar skeneru troksni.

Kā redzēt, kas tiešām ir atvērts

firewall-cmd --zone=public --list-all rāda nodomu: mērķi, saskarnes, avotus, servisus, portus, masquerade, rich rules. ss rāda realitāti.

ss -tulpen
nft list chain inet firewalld filter_IN_public_allow

Lasiet abus kopā. Ugunsmūrī atvērts ports, uz kura neviens neklausās, praksē ir slēgts; dēmons, kas piesaistīts 0.0.0.0, ir vienas drukas kļūdas attālumā no publiskas pieejamības, bet tas, kas piesaistīts 127.0.0.1, ir drošs neatkarīgi no ugunsmūra, un ligzda uz [::] parasti pieņem arī IPv4. Pārbaudiet ar nc -zv jusu.servera.ip 443 no citas mašīnas, nekad no paša servera.

AlmaLinux specifika: SELinux pēc noklusējuma ir enforcing režīmā, un porta 8081 atvēršana ugunsmūrī vēl neļauj nginx tam piesaistīties. Ja dēmons tūlīt pēc porta atvēršanas neuzstartē, iemesls parasti ir tieši šis. Pirms maināt iezīmi, apskatiet, kas portam jau piešķirts: http_port_t sedz 80, 81, 443, 488, 8008, 8009, 8443 un 9000, bet tcp/8081 standarta politikā jau pieder citam tipam (transproxy_port_t). Portam, kuram tips jau ir, iezīmi maina ar -m, un -a der tikai portam bez tipa, citādi semanage apstājas ar kļūdu "Port tcp/8081 already defined".

dnf install policycoreutils-python-utils
semanage port -l | grep 8081
semanage port -m -t http_port_t -p tcp 8081
ausearch -m avc -ts recent

Kā mainīt kārtulu un nepazaudēt SSH

Nekad nelabojiet pastāvīgās kārtulas, kas skar SSH, un pēc tam nepārlādējiet konfigurāciju, ja jums nav otra ceļa iekšā. Strādājiet runtime līmenī ar taimautu un nostipriniet izmaiņas tikai tad, kad esat tās pārbaudījuši. Pati rich rule vēl neko neierobežo: public zonā joprojām ir atļauts serviss ssh, tāpēc SSH paliek atvērts visam internetam, un tas ir tieši tas pats slazds, kas iepriekš aprakstīts portam 5432. Ierobežojums sākas tikai brīdī, kad šo servisu arī noņemat:

firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" source address="203.0.113.10/32" service name="ssh" accept' --timeout=10m
firewall-cmd --zone=public --remove-service=ssh
systemd-run --on-active=5m --unit=fw-rollback firewall-cmd --reload

--timeout darbojas tikai runtime, nav savienojams ar --permanent un attiecas tikai uz pievienoto kārtulu, nevis uz servisa noņemšanu: serviss ssh pats no sevis neatgriezīsies. systemd-run rinda ir drošinātājs: pēc piecām minūtēm tā pārlādē firewalld un atmet visas runtime izmaiņas, un tieši šī pārlāde atjauno servisu no pastāvīgās konfigurācijas, ja pārbaude neizdodas. Tagad no cita termināļa atveriet jaunu SSH sesiju. Tieši tas ir būtiskākais solis, jo pārlāde saglabā savienojumu izsekošanas stāvokli, tāpēc esošā sesija izdzīvo pat tad, ja jaunas kārtulas jaunu savienojumu bloķētu. Ja jaunā sesija strādā, nekavējoties atceliet atgriešanos un saglabājiet, krietni pirms taimauta beigām:

systemctl stop fw-rollback.timer
firewall-cmd --runtime-to-permanent

Laiks šeit ir svarīgs. Servisa ssh noņemšanai taimauta nav, rich rule tāds ir, tāpēc, ja kārtulai taimauts beidzas, pirms paspējat saglabāt, runtime vairs nav ne servisa, ne kārtulas, un --runtime-to-permanent ieraksta tieši to: pastāvīgu piekļuves zaudēšanu, ko esošā sesija noslēpj. Ja laiks aizskrējis, pirms saglabāšanas pievienojiet rich rule no jauna vai izpildiet firewall-cmd --reload un sāciet no sākuma.

Attālināti izvairieties no divām komandām: --complete-reload, kas atmet savienojumu izsekošanu un pārtrauc jau izveidotās sesijas, un --panic-on, kas bloķē visu, arī jūs. Turiet atvērtu konsoli hostinga panelī. Ja mašīna mūsu Rīgas datu centrā tomēr kļūst nesasniedzama, mūsu inženieri ir pieejami visu diennakti, un šādus darbus mēs darām arī kā IT atbalstu.

nftables tieši un kā tas sadzīvo ar firewalld

firewalld izveido vienu tabulu, inet firewalld, un tās filtra bāzes ķēdes karājas pie prioritātes filter + 10, apzināti pēc klasiskās filtra prioritātes, tāpēc ar roku rakstīta tabula standarta prioritātē tiek izvērtēta pirmā. Šeit svarīgi saprast verdiktus: drop ir galīgs uzreiz, bet accept beidz tikai savu ķēdi, un pakete joprojām iziet pārējās bāzes ķēdes tajā pašā āķī, tāpēc abām kārtulu kopām tā jāizlaiž cauri. Nekad nelabojiet inet firewalld ar roku, firewalld to pārraksta katrā pārlādē.

Ja tuvāks ir tīrs nftables, izvēlieties vienu vai otru un sagatavojiet aizvietotāju, pirms nolaižat strādājošo ugunsmūri. Serviss ielādē tieši vienu failu, /etc/sysconfig/nftables.conf, un piegādātajā veidolā tas neielādē neko citu: rinda, kas pievienotu /etc/nftables/main.nft, ir aizkomentēta, bet pats parauga fails atļauj tikai ssh un 9090. Tāpēc vispirms ierakstiet savu kārtulu kopu failā /etc/nftables/main.nft, parauga vietā. Sāciet to ar flush ruleset, citādi faila atkārtota piemērošana pievieno dublikātus, nevis aizstāj. Darbojošs minimums:

flush ruleset

table inet filter {
  chain input {
    type filter hook input priority filter; policy drop;
    ct state established,related accept
    ct state invalid drop
    iif lo accept
    ip protocol icmp accept
    ip6 nexthdr ipv6-icmp accept
    tcp dport 22 accept
    tcp dport { 80, 443 } accept
  }
  chain forward { type filter hook forward priority filter; policy drop; }
  chain output { type filter hook output priority filter; policy accept; }
}

Tagad norādiet failam, kuru lasa serviss, uz jūsu kārtulu kopu, pārbaudiet, ko tas tiešām ielādēs, un palaidiet servisu. grep izvadā jāparādās include rindai: ja izvade ir tukša, sed neatrada šablonu un rinda failā /etc/sysconfig/nftables.conf jāieraksta ar roku. flush ruleset faila sākumā notīra arī firewalld izveidoto tabulu, un, aizstājot ugunsmūri, tieši tas arī ir vajadzīgs, tāpēc no šī brīža starp mašīnu un internetu stāv tikai jūsu kārtulas:

dnf install nftables
sed -i 's|^#include "/etc/nftables/main.nft"|include "/etc/nftables/main.nft"|' /etc/sysconfig/nftables.conf
grep -n '^include' /etc/sysconfig/nftables.conf
nft -c -f /etc/sysconfig/nftables.conf
systemctl enable --now nftables
nft list ruleset

Vispirms izlasiet pēdējo izvadi: tur jābūt jūsu input ķēdei, tās policy drop un rindai ar portu 22. Pēc tam no cita termināļa atveriet jaunu SSH sesiju, tieši tāpat kā firewalld sadaļā. Ja tā nestrādā vai kārtulu kopa nav tā, ko rakstījāt, ejiet atpakaļ: systemctl stop nftables un systemctl restart firewalld atgriež vecās kārtulas. Nepieņemiet, ka apturēšana kaut ko notīra: apskatiet systemctl cat nftables, jo kārtulu kopas notīrīšana pie stop ir atkarīga no jūsu versijas unit faila, un, ja tās nav, pirms firewalld palaišanas izpildiet nft flush ruleset manuāli.

Veco ugunsmūri drīkst noņemt tikai tad, kad jaunā sesija strādā:

systemctl disable --now firewalld
systemctl mask firewalld

Divas piezīmes no prakses: konteineru dzinēji raksta savas netfilter kārtulas, un firewalld pārlāde var izdzēst to, ko ielika Docker, tāpēc, ja publicētais ports mirst tūlīt pēc pārlādes, pārstartējiet dzinēju. Un fail2ban ir atsevišķas darbības firewalld un nftables gadījumam, turklāt nosaukumi mainījās starp 0.11 un 1.0, tāpēc ieskatieties /etc/fail2ban/action.d/ un pārliecinieties, ka bloķējumi tiešām parādās nft list ruleset izvadē.

Šaurais gadījums, kad izslēgšana ir attaisnojama

Viens gadījums ir attaisnojams: mašīnai nav globāli maršrutējamas adreses, un tā atrodas aiz aparatūras ugunsmūra vai malas ACL, ko pārvaldāt paši un varat pārbaudīt. Tas apraksta nomātu serveri privātā VLAN aiz jūsu pašu iekārtas. Šaurāks variants ir mezgls, kura pakešu ceļu pilnībā pārvalda cits kontrolieris, piemēram, Kubernetes CNI, kur firewalld tikai cīnās ar to.

systemctl disable --now firewalld
systemctl mask firewalld
nft list ruleset

No pēdējās komandas sagaidiet tukšu izvadi. Maskējiet, nevis tikai atslēdziet, citādi pakotņu atjauninājums to var klusi palaist atpakaļ. Un tāpat piesaistiet dēmonus privātajai adresei (listen_addresses PostgreSQL, bind-address MySQL), jo apgalvojums "priekšā taču ir ugunsmūris" ir viena nepareizi konfigurēta komutatora porta attālumā no nepatiesības. Nav attaisnojami: izslēgt tāpēc, ka ports neatvērās, tāpēc, ka tā rakstīts 2014. gada pamācībā, vai tāpēc, ka konteineru dzinējs strīdējās. Visus trīs var diagnosticēt tik ilgā laikā, cik aizņem ss -tulpen un --list-all.

Ja joprojām nestrādā

SimptomsKo pārbaudīt
Kārtula pievienota, savienojums noraidītsVai kāds klausās, vai zona pareiza, vai bija reload, SELinux porta iezīme
No biroja strādā, no mājām nēRich rule family, CIDR maska vai mainīta interneta operatora adrese
Pēc pārstartēšanas viss atgriezāsKārtula bija tikai runtime, bez --permanent
Ports atvērts, no ārpuses klusumsFiltrs virs mašīnas: malas ACL vai maršrutētājs
Bloķējumi neko nedarafail2ban darbība neatbilst tam ugunsmūrim, ko tiešām lieto
Gribi, lai to darām mēs?
VPS. NVMe virtuālie serveri, gatavi minūtes laikā.
Uzzināt vairāk

Gatavs sākt?

Palaid dažās minūtēs vai aprunājies ar inženieri par piemērotāko risinājumu.