Aplikowanie zmiennych sysctl przy pomocy udev'a

Spis treści

Kernele linux'owe mają dość sporo opcji, które możemy zmienić przy pomocy pliku /etc/sysctl.conf . Niby nic nadzwyczajnego ale co w przypadku tych zmiennych, które muszą być ustawione, z tym, że moduł, który stworzy odpowiednie ścieżki w katalogu /proc/sys/ , nie został załadowany z jakichś względów przy starcie systemu? Zmienne te nie zostaną ustawione, a w logu pojawi się komunikat informujący nas o nieodnalezieniu określonego pliku. Okazuje się, że jesteśmy w stanie aplikować określone ustawienia sysctl w momencie ładowania określonych modułów i temu mechanizmowi się przyjrzymy bliżej w tym wpisie.

Komunikaty zwracane przez systemd-sysctl

Przeglądając log systemowy, doszukałem się kilku komunikatów, których treść jest podobna do tej poniższej linijki::

# journalctl --no-tail -b -u systemd-sysctl
...
systemd-sysctl[430]: Couldn't write '30' to 'net/netfilter/nf_conntrack_icmpv6_timeout', ignoring: No such file or directory
...

Problem udało się rozwiązać i winne były dwa moduły, konkretnie nf_conntrack_ipv4 oraz nf_conntrack_ipv6 , które nie ładowały się przy starcie systemu -- no bo nie było ich wpisanych do pliku /etc/modules . Te dwa moduły były ładowane w późniejszej fazie startu systemu ale ustawienia, które powinny zostać zaaplikowane, zostały zwyczajnie zignorowane.

Możemy naturalnie wpisać wszystkie niezbędne moduły (te, których wartości są określone w pliku sysctl.conf) do pliku /etc/modules . Chodzi o to, że w systemd mamy dwie usługi odpowiedzialne za ustawianie zmiennych kernela: systemd-modules-load.service , która ładuje moduły oraz systemd-sysctl.service , która nakłada ustawienia z pliku sysctl.conf . Druga z nich ma wyraźnie określoną zależność After=systemd-modules-load.service , dlatego też wszystkie moduły muszą być pierw załadowane, by te zmienne mogły zostać zaaplikowane. Nie zawsze jest to jednak idealne rozwiązanie.

Reguły udev'a dla określonych modułów

Co w przypadku gdy nie chcemy ładować wszystkich modułów przy starcie systemu? Przecie część z nich możemy ładować w trakcie jego pracy, oczywiście, jeśli zachodzi taka potrzeba. W takim przypadku musimy skorzystać z udev'a i napisać regułkę, która w chwili ładowania takiego modułu ustawi określone dla niego opcje. W manualu sysctl.d jest przykład takiej reguły i ja na jej podstawie stworzyłem plik /etc/udev/rules.d/99-sysctl.rules o poniższej treści:

ACTION=="add", SUBSYSTEM=="module", KERNEL=="nf_conntrack", \
      RUN+="/lib/systemd/systemd-sysctl --prefix=/net/netfilter"

ACTION=="add", SUBSYSTEM=="module", KERNEL=="nf_conntrack_ipv4", \
      RUN+="/lib/systemd/systemd-sysctl --prefix=/net/netfilter"

ACTION=="add", SUBSYSTEM=="module", KERNEL=="nf_conntrack_ipv6", \
      RUN+="/lib/systemd/systemd-sysctl --prefix=/net/netfilter"

Opcja ACTION oraz SUBSYSTEM zawsze pozostaje bez zmian. Z kolei na pozycji KERNEL wpisujemy nazwę modułu, tego, który zwykle ładowany jest przy pomocy modprobe lub też może zostać wyświetlony via lsmod . W RUN następuje wywołanie odpowiedniego narzędzia dostarczanego przez systemd z opcją --prefix, która odpowiada za lokalizację plików modułu w katalogu /proc/sys/ . W tym przypadku, konfiguracja powyższych modułów znajduje się pod /proc/sys/net/netfilter/ , zatem wszystkie wpisy w /etc/sysctl.conf odwołujące się do net.netfilter będą aplikowane przy ładowaniu tych modułów.

Mikhail Morfikov avatar
Mikhail Morfikov
Po ponad 10 latach spędzonych z różnej maści linux'ami (Debian/Ubuntu, OpenWRT, Android) mogę śmiało powiedzieć, że nie ma rzeczy niemożliwych i problemów, których nie da się rozwiązać. Jedną umiejętność, którą ludzki umysł musi posiąść, by wybrnąć nawet z tej najbardziej nieprzyjemniej sytuacji, to zdolność logicznego rozumowania.