summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorafro-coder <leon9923@gmail.com>2021-08-17 22:15:00 +0530
committerafro-coder <leon9923@gmail.com>2021-08-18 01:25:12 +0530
commit970529b6a53f7f978019d397c7caab24bd535730 (patch)
treea9b10f2080ad5c6a1c232bae4a2a20e5c0922c26
parentedf9ec38e40bd2471c870c9bbf3b2685d5e45fa7 (diff)
downloadpodman-970529b6a53f7f978019d397c7caab24bd535730.tar.gz
podman-970529b6a53f7f978019d397c7caab24bd535730.tar.bz2
podman-970529b6a53f7f978019d397c7caab24bd535730.zip
Documented ways to fix firewall rules that are lost when firewalld reloads
Closes #5431 Signed-off-by: afro-coder <leon9923@gmail.com>
-rw-r--r--troubleshooting.md135
1 files changed, 135 insertions, 0 deletions
diff --git a/troubleshooting.md b/troubleshooting.md
index 24dcb8e35..dcf1d8715 100644
--- a/troubleshooting.md
+++ b/troubleshooting.md
@@ -746,3 +746,138 @@ an Infra container image for CNI-in-slirp4netns must be created. The
instructions for building the Infra container image can be found for
v2.2.1 [here](https://github.com/containers/podman/tree/v2.2.1-rhel/contrib/rootless-cni-infra),
and for v3.0.1 [here](https://github.com/containers/podman/tree/v3.0.1-rhel/contrib/rootless-cni-infra).
+### 29) Container related firewall rules are lost after reloading firewalld
+Container network can't be reached after `firewall-cmd --reload` and `systemctl restart firewalld` Running `podman network reload` will fix it but it has to be done manually.
+
+#### Symptom
+The firewall rules created by podman are lost when the firewall is reloaded.
+
+#### Solution
+[@ranjithrajaram](https://github.com/containers/podman/issues/5431#issuecomment-847758377) has created a systemd-hook to fix this issue
+
+1) For "firewall-cmd --reload", create a systemd unit file with the following
+```
+[Unit]
+Description=firewalld reload hook - run a hook script on firewalld reload
+Wants=dbus.service
+After=dbus.service
+
+[Service]
+Type=simple
+ExecStart=/bin/bash -c '/bin/busctl monitor --system --match "interface=org.fedoraproject.FirewallD1,member=Reloaded" --match "interface=org.fedoraproject.FirewallD1,member=PropertiesChanged" | while read -r line ; do podman network reload --all ; done'
+
+[Install]
+WantedBy=multi-user.target
+```
+2) For "systemctl restart firewalld", create a systemd unit file with the following
+```
+[Unit]
+Description=podman network reload
+Wants=firewalld.service
+After=firewalld.service
+PartOf=firewalld.service
+
+[Service]
+Type=simple
+RemainAfterExit=yes
+ExecStart=/usr/bin/podman network reload --all
+
+[Install]
+WantedBy=multi-user.target
+```
+However, If you use busctl monitor then you can't get machine-readable output on `RHEL 8`.
+Since it doesn't have `busctl -j` as mentioned here by [@yrro](https://github.com/containers/podman/issues/5431#issuecomment-896943018).
+
+For RHEL 8, you can use the following one-liner bash script.
+```
+[Unit]
+Description=Redo podman NAT rules after firewalld starts or reloads
+Wants=dbus.service
+After=dbus.service
+Requires=firewalld.service
+
+[Service]
+Type=simple
+ExecStart=/bin/bash -c "dbus-monitor --profile --system 'type=signal,sender=org.freedesktop.DBus,path=/org/freedesktop/DBus,interface=org.freedesktop.DBus,member=NameAcquired,arg0=org.fedoraproject.FirewallD1' 'type=signal,path=/org/fedoraproject/FirewallD1,interface=org.fedoraproject.FirewallD1,member=Reloaded' | sed -u '/^#/d' | while read -r type timestamp serial sender destination path interface member _junk; do if [[ $type = '#'* ]]; then continue; elif [[ $interface = org.freedesktop.DBus && $member = NameAcquired ]]; then echo 'firewalld started'; podman network reload --all; elif [[ $interface = org.fedoraproject.FirewallD1 && $member = Reloaded ]]; then echo 'firewalld reloaded'; podman network reload --all; fi; done"
+Restart=Always
+
+[Install]
+WantedBy=multi-user.target
+```
+`busctl-monitor` is almost usable in `RHEL 8`, except that it always outputs two bogus events when it starts up,
+one of which is (in its only machine-readable format) indistinguishable from the `NameOwnerChanged` that you get when firewalld starts up.
+This means you would get an extra `podman network reload --all` when this unit starts.
+
+Apart from this, you can use the following systemd service with the python3 code.
+
+```
+[Unit]
+Description=Redo podman NAT rules after firewalld starts or reloads
+Wants=dbus.service
+Requires=firewalld.service
+After=dbus.service
+
+[Service]
+Type=simple
+ExecStart=/usr/bin/python /path/to/python/code/podman-redo-nat.py
+Restart=always
+
+[Install]
+WantedBy=multi-user.target
+```
+The code reloads podman network twice when you use `systemctl restart firewalld`.
+```
+import dbus
+from gi.repository import GLib
+from dbus.mainloop.glib import DBusGMainLoop
+import subprocess
+import sys
+
+# I'm a bit confused on the return values in the code
+# Not sure if they are needed.
+
+def reload_podman_network():
+ try:
+ subprocess.run(["podman","network","reload","--all"],timeout=90)
+ # I'm not sure about this part
+ sys.stdout.write("podman network reload done\n")
+ sys.stdout.flush()
+ except subprocess.TimeoutExpired as t:
+ sys.stderr.write(f"Podman reload failed due to Timeout {t}")
+ except subprocess.CalledProcessError as e:
+ sys.stderr.write(f"Podman reload failed due to {e}")
+ except Exception as e:
+ sys.stderr.write(f"Podman reload failed with an Unhandled Exception {e}")
+
+ return False
+
+def signal_handler(*args, **kwargs):
+ if kwargs.get('member') == "Reloaded":
+ reload_podman_network()
+ elif kwargs.get('member') == "NameOwnerChanged":
+ reload_podman_network()
+ else:
+ return None
+ return None
+
+def signal_listener():
+ try:
+ DBusGMainLoop(set_as_default=True)# Define the loop.
+ loop = GLib.MainLoop()
+ system_bus = dbus.SystemBus()
+ # Listens to systemctl restart firewalld with a filter added, will cause podman network to be reloaded twice
+ system_bus.add_signal_receiver(signal_handler,dbus_interface='org.freedesktop.DBus',arg0='org.fedoraproject.FirewallD1',member_keyword='member')
+ # Listens to firewall-cmd --reload
+ system_bus.add_signal_receiver(signal_handler,dbus_interface='org.fedoraproject.FirewallD1',signal_name='Reloaded',member_keyword='member')
+ loop.run()
+ except KeyboardInterrupt:
+ loop.quit()
+ sys.exit(0)
+ except Exception as e:
+ loop.quit()
+ sys.stderr.write(f"Error occured {e}")
+ sys.exit(1)
+
+if __name__ == "__main__":
+ signal_listener()
+```