diff --git a/src/freedombone-app-dlna b/src/freedombone-app-dlna
index f62672f9610131ff6ecfd95f3eb58ce86a1db35a..74c046228bcfea476feb7abe29f9ec938e8da278 100755
--- a/src/freedombone-app-dlna
+++ b/src/freedombone-app-dlna
@@ -87,13 +87,9 @@ function configure_firewall_for_dlna {
         # docker does its own firewalling
         return
     fi
-    iptables -A INPUT -p udp --dport 1900 -j ACCEPT
-    iptables -A INPUT -p tcp --dport 8200 -j ACCEPT
-    function_check save_firewall_settings
-    save_firewall_settings
 
-    OPEN_PORTS+=('DLNA     1900')
-    OPEN_PORTS+=('DLNA     8200')
+    firewall_add DLNA 1900 udp
+    firewall_add DLNA 8200 tcp
     mark_completed $FUNCNAME
 }
 
@@ -162,11 +158,9 @@ function remove_dlna {
     if [ -f /etc/minidlna.conf ]; then
         rm /etc/minidlna.conf
     fi
-    iptables -D INPUT -p udp --dport 1900 -j ACCEPT
-    iptables -D INPUT -p tcp --dport 8200 -j ACCEPT
-    function_check save_firewall_settings
-    save_firewall_settings
     remove_completion_param install_dlna
+    firewall_remove 1900 udp
+    firewall_remove 8200 tcp
 }
 
 function install_dlna_main {
diff --git a/src/freedombone-app-ipfs b/src/freedombone-app-ipfs
index fa34b40afd469c2da3f71251575d5bb11b108e6e..89cfb152068e613c46abbf3c544b3c48898d7a6c 100755
--- a/src/freedombone-app-ipfs
+++ b/src/freedombone-app-ipfs
@@ -164,9 +164,7 @@ function remove_ipfs_go {
     systemctl daemon-reload
     rm /etc/systemd/system/ipfs.service
     rm -rf $GOPATH/src/github.com/ipfs
-    iptables -D INPUT -p tcp --dport $IPFS_PORT -j ACCEPT
-    function_check save_firewall_settings
-    save_firewall_settings
+    firewall_remove $IPFS_PORT tcp
     remove_completion_param install_ipfs
     remove_completion_param configure_firewall_for_ipfs
     sed -i '/ipfs/d' $COMPLETION_FILE
@@ -181,9 +179,7 @@ function remove_ipfs_js {
     npm uninstall ipfs --global
     npm uninstall ronin --global
 
-    iptables -D INPUT -p tcp --dport $IPFS_PORT -j ACCEPT
-    function_check save_firewall_settings
-    save_firewall_settings
+    firewall_remove $IPFS_PORT tcp
     sed -i '/install_ipfs/d' $COMPLETION_FILE
     sed -i '/ipfs/d' $COMPLETION_FILE
     sed -i '/configure_firewall_for_ipfs/d' $COMPLETION_FILE
@@ -201,11 +197,8 @@ function configure_firewall_for_ipfs {
     if [[ $ONION_ONLY != "no" ]]; then
         return
     fi
-    iptables -A INPUT -p tcp --dport $IPFS_PORT -j ACCEPT
-    function_check save_firewall_settings
-    save_firewall_settings
 
-    OPEN_PORTS+=("IPFS     $IPFS_PORT")
+    firewall_add IPFS $IPFS_PORT tcp
     mark_completed $FUNCNAME
 }
 
diff --git a/src/freedombone-app-irc b/src/freedombone-app-irc
index 149635bd29ded182253bd21b3930638c5156728d..c8642b84d308f38090412e447b5fee71a5156ba4 100755
--- a/src/freedombone-app-irc
+++ b/src/freedombone-app-irc
@@ -244,10 +244,12 @@ function remove_irc {
     if [ -d /etc/ngircd ]; then
         rm -rf /etc/ngircd
     fi
-    iptables -D INPUT -p tcp --dport ${IRC_PORT}  -j ACCEPT
+
     iptables -D INPUT -p tcp --dport 1024:65535 --sport ${IRC_PORT} -j ACCEPT
     function_check save_firewall_settings
     save_firewall_settings
+    firewall_remove ${IRC_PORT} tcp
+
     function_check remove_onion_service
     remove_onion_service irc ${IRC_ONION_PORT}
     remove_completion_param install_irc
@@ -269,12 +271,11 @@ function configure_firewall_for_irc {
     if [[ ${ONION_ONLY} != "no" ]]; then
         return
     fi
-    iptables -A INPUT -p tcp --dport ${IRC_PORT}  -j ACCEPT
     iptables -I INPUT -p tcp --dport 1024:65535 --sport ${IRC_PORT} -j ACCEPT
     function_check save_firewall_settings
     save_firewall_settings
 
-    OPEN_PORTS+=("IRC      $IRC_PORT")
+    firewall_add IRC ${IRC_PORT} tcp
     echo 'configure_firewall_for_irc' >> ${COMPLETION_FILE}
 }
 
diff --git a/src/freedombone-app-librevault b/src/freedombone-app-librevault
index b88e76fb6a84bfd71ebbaa7fe8ee3213cb913415..69ed3ecbe68e4557c2dffc5adf818d7b17a23488 100755
--- a/src/freedombone-app-librevault
+++ b/src/freedombone-app-librevault
@@ -109,11 +109,7 @@ function restore_remote_librevault {
 }
 
 function remove_librevault {
-    iptables -D INPUT -p udp --dport $LIBREVAULT_PORT -j ACCEPT
-    iptables -D INPUT -p tcp --dport $LIBREVAULT_PORT -j ACCEPT
-    function_check save_firewall_settings
-    save_firewall_settings
-
+    firewall_remove ${LIBREVAULT_PORT}
     systemctl stop librevault
     systemctl disable librevault
     rm /etc/systemd/system/librevault.service
@@ -125,11 +121,7 @@ function configure_firewall_for_librevault {
     if [[ $(is_completed $FUNCNAME) == "1" ]]; then
         return
     fi
-    iptables -A INPUT -p udp --dport $LIBREVAULT_PORT -j ACCEPT
-    iptables -A INPUT -p tcp --dport $LIBREVAULT_PORT -j ACCEPT
-    function_check save_firewall_settings
-    save_firewall_settings
-    OPEN_PORTS+=("Librevault $LIBREVAULT_PORT")
+    firewall_add Librevault ${LIBREVAULT_PORT}
     mark_completed $FUNCNAME
 }
 
diff --git a/src/freedombone-app-mumble b/src/freedombone-app-mumble
index 500905a18349a5b36fa9d673b89c64eb31872c2d..03c5284e577004d05a71eb67e997a0061492f90a 100755
--- a/src/freedombone-app-mumble
+++ b/src/freedombone-app-mumble
@@ -158,10 +158,7 @@ function restore_remote_mumble {
 function remove_mumble {
     apt-get -y remove --purge mumble-server
     if [[ $ONION_ONLY == "no" ]]; then
-        iptables -D INPUT -p udp --dport $MUMBLE_PORT -j ACCEPT
-        iptables -D INPUT -p tcp --dport $MUMBLE_PORT -j ACCEPT
-        function_check save_firewall_settings
-        save_firewall_settings
+        firewall_remove ${MUMBLE_PORT}
     fi
     if [ -f /etc/mumble-server.ini ]; then
         rm /etc/mumble-server.ini
@@ -189,12 +186,7 @@ function configure_firewall_for_mumble {
     if [[ $ONION_ONLY != "no" ]]; then
         return
     fi
-    iptables -A INPUT -p udp --dport $MUMBLE_PORT -j ACCEPT
-    iptables -A INPUT -p tcp --dport $MUMBLE_PORT -j ACCEPT
-    function_check save_firewall_settings
-    save_firewall_settings
-
-    OPEN_PORTS+=("Mumble   $MUMBLE_PORT")
+    firewall_add Mumble ${MUMBLE_PORT}
     mark_completed $FUNCNAME
 }
 
diff --git a/src/freedombone-app-pihole b/src/freedombone-app-pihole
index db3049efa9247922e28ba08fae952a14e9dbe7ad..3d4e1a0a78c4ee93e8bb99354c1a417cbdd927a2 100755
--- a/src/freedombone-app-pihole
+++ b/src/freedombone-app-pihole
@@ -207,13 +207,7 @@ function configure_firewall_for_pihole {
     if [[ $(is_completed $FUNCNAME) == "1" ]]; then
         return
     fi
-    #iptables -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
-    iptables -A INPUT -p tcp -m tcp --dport 53 -j ACCEPT
-    iptables -A INPUT -p udp -m udp --dport 53 -j ACCEPT
-    function_check save_firewall_settings
-    save_firewall_settings
-
-    OPEN_PORTS+=('DNS      53')
+    firewall_add DNS 53
     mark_completed $FUNCNAME
 }
 
@@ -324,6 +318,7 @@ function remove_pihole {
         rm /etc/cron.d/pihole
     fi
 
+    firewall_remove 53
     userdel -r pihole
 }
 
diff --git a/src/freedombone-app-sip b/src/freedombone-app-sip
index 3163c66b5856e274012fbb8f5bf6c1e3eecea44d..0db524c5654e3c43b63b1fc7b5f444b481934a03 100755
--- a/src/freedombone-app-sip
+++ b/src/freedombone-app-sip
@@ -158,16 +158,10 @@ function restore_remote_sip {
 }
 
 function remove_sip {
-    iptables -D INPUT -p udp --dport $TURN_PORT -j ACCEPT
-    iptables -D INPUT -p tcp --dport $TURN_PORT -j ACCEPT
-    iptables -D INPUT -p tcp --dport $TURN_TLS_PORT -j ACCEPT
-
-    iptables -D INPUT -p udp --dport $SIP_PORT -j ACCEPT
-    iptables -D INPUT -p tcp --dport $SIP_PORT -j ACCEPT
-    iptables -D INPUT -p udp --dport $SIP_TLS_PORT -j ACCEPT
-    iptables -D INPUT -p tcp --dport $SIP_TLS_PORT -j ACCEPT
-    function_check save_firewall_settings
-    save_firewall_settings
+    firewall_remove ${TURN_PORT}
+    firewall_remove ${TURN_TLS_PORT} tcp
+    firewall_remove ${SIP_PORT}
+    firewall_remove ${SIP_TLS_PORT}
 
     function_check remove_onion_service
     remove_onion_service sip ${SIP_PORT}
@@ -192,14 +186,8 @@ function configure_firewall_for_turn {
     if [[ $ONION_ONLY != "no" ]]; then
         return
     fi
-    iptables -A INPUT -p udp --dport $TURN_PORT -j ACCEPT
-    iptables -A INPUT -p tcp --dport $TURN_PORT -j ACCEPT
-    iptables -A INPUT -p tcp --dport $TURN_TLS_PORT -j ACCEPT
-    function_check save_firewall_settings
-    save_firewall_settings
-
-    OPEN_PORTS+=("TURN     $TURN_PORT")
-    OPEN_PORTS+=("TURN TLS $TURN_TLS_PORT")
+    firewall_add TURN ${TURN_PORT}
+    firewall_add "TURN TLS" ${TURN_TLS_PORT} tcp
     mark_completed $FUNCNAME
 }
 
@@ -211,15 +199,8 @@ function configure_firewall_for_sip4 {
     if [[ $ONION_ONLY != "no" ]]; then
         return
     fi
-    iptables -A INPUT -p udp --dport $SIP_PORT -j ACCEPT
-    iptables -A INPUT -p tcp --dport $SIP_PORT -j ACCEPT
-    iptables -A INPUT -p udp --dport $SIP_TLS_PORT -j ACCEPT
-    iptables -A INPUT -p tcp --dport $SIP_TLS_PORT -j ACCEPT
-    function_check save_firewall_settings
-    save_firewall_settings
-
-    OPEN_PORTS+=("SIP      $SIP_PORT")
-    OPEN_PORTS+=("SIP TLS  $SIP_TLS_PORT")
+    firewall_add SIP ${SIP_PORT}
+    firewall_add "SIP TLS" ${SIP_TLS_PORT}
     mark_completed $FUNCNAME
 }
 
diff --git a/src/freedombone-app-syncthing b/src/freedombone-app-syncthing
index 08f28d6a3479bddafb1b3df14d21c3b417435cee..d4dc22d292223ca6135050f7506062dd2dbfb701 100755
--- a/src/freedombone-app-syncthing
+++ b/src/freedombone-app-syncthing
@@ -462,11 +462,7 @@ function restore_remote_syncthing {
 }
 
 function remove_syncthing {
-    iptables -D INPUT -p udp --dport $SYNCTHING_PORT -j ACCEPT
-    iptables -D INPUT -p tcp --dport $SYNCTHING_PORT -j ACCEPT
-    function_check save_firewall_settings
-    save_firewall_settings
-
+    firewall_remove ${SYNCTHING_PORT}
     systemctl stop syncthing
     systemctl disable syncthing
     apt-get -y remove --purge syncthing
@@ -482,12 +478,7 @@ function configure_firewall_for_syncthing {
         return
     fi
 
-    iptables -A INPUT -p udp --dport $SYNCTHING_PORT -j ACCEPT
-    iptables -A INPUT -p tcp --dport $SYNCTHING_PORT -j ACCEPT
-    function_check save_firewall_settings
-    save_firewall_settings
-
-    OPEN_PORTS+=("Syncthing $SYNCTHING_PORT")
+    firewall_add Syncthing ${SYNCTHING_PORT}
     mark_completed $FUNCNAME
 }
 
diff --git a/src/freedombone-app-tahoelafs b/src/freedombone-app-tahoelafs
index 9965b8f755a4873823089c3364a60f3d8f16485b..4cf0d450f86cee87dcc5d27b2f06f2d97cd900b8 100755
--- a/src/freedombone-app-tahoelafs
+++ b/src/freedombone-app-tahoelafs
@@ -186,10 +186,7 @@ function restore_remote_tahoelafs {
 }
 
 function remove_tahoelafs {
-    iptables -D INPUT -p udp --dport $TAHOELAFS_PORT -j ACCEPT
-    iptables -D INPUT -p tcp --dport $TAHOELAFS_PORT -j ACCEPT
-    function_check save_firewall_settings
-    save_firewall_settings
+    firewall_remove ${TAHOELAFS_PORT}
 
     for d in /home/*/ ; do
         USERNAME=$(echo "$d" | awk -F '/' '{print $3}')
@@ -209,11 +206,7 @@ function configure_firewall_for_tahoelafs {
     if [[ $(is_completed $FUNCNAME) == "1" ]]; then
         return
     fi
-    iptables -A INPUT -p udp --dport $TAHOELAFS_PORT -j ACCEPT
-    iptables -A INPUT -p tcp --dport $TAHOELAFS_PORT -j ACCEPT
-    function_check save_firewall_settings
-    save_firewall_settings
-    OPEN_PORTS+=("Tahoe-LAFS $TAHOELAFS_PORT")
+    firewall_add Tahoe-LAFS ${TAHOELAFS_PORT}
     mark_completed $FUNCNAME
 }
 
diff --git a/src/freedombone-app-tox b/src/freedombone-app-tox
index 1cbdb4acbb9c1ac4efb5caf742691d571eba51b7..c886e08c2527424354f11dc5df103eb29f596ef0 100755
--- a/src/freedombone-app-tox
+++ b/src/freedombone-app-tox
@@ -242,10 +242,7 @@ function restore_remote_tox {
 }
 
 function remove_tox_node {
-    iptables -D INPUT -p tcp --dport $TOX_PORT -j ACCEPT
-    iptables -D INPUT -p udp --dport $TOX_PORT -j ACCEPT
-    function_check save_firewall_settings
-    save_firewall_settings
+    firewall_remove ${TOX_PORT}
 
     function_check remove_onion_service
     remove_onion_service tox ${TOX_PORT}
@@ -307,12 +304,7 @@ function configure_firewall_for_tox {
         exit 32856
     fi
 
-    iptables -A INPUT -p tcp --dport $TOX_PORT -j ACCEPT
-    iptables -A INPUT -p udp --dport $TOX_PORT -j ACCEPT
-    function_check save_firewall_settings
-    save_firewall_settings
-
-    OPEN_PORTS+=("Tox      $TOX_PORT")
+    firewall_add Tox ${TOX_PORT}
     mark_completed $FUNCNAME
 }
 
diff --git a/src/freedombone-app-xmpp b/src/freedombone-app-xmpp
index 156f6ed0b8d3244777a7e83d8c07be6b1481afb1..151dcc277adac1f10a7f409453585fd000541f12 100755
--- a/src/freedombone-app-xmpp
+++ b/src/freedombone-app-xmpp
@@ -251,15 +251,11 @@ function configure_firewall_for_xmpp {
     if [[ $ONION_ONLY != "no" ]]; then
         return
     fi
-    iptables -A INPUT -p tcp --dport 5222:5223 -j ACCEPT
-    iptables -A INPUT -p tcp --dport 5269 -j ACCEPT
-    iptables -A INPUT -p tcp --dport 5280:5281 -j ACCEPT
-    function_check save_firewall_settings
-    save_firewall_settings
-
-    OPEN_PORTS+=('XMPP     5222-5223')
-    OPEN_PORTS+=('XMPP     5269')
-    OPEN_PORTS+=('XMPP     5280-5281')
+    firewall_add XMPP 5222 tcp
+    firewall_add XMPP 5223 tcp
+    firewall_add XMPP 5269 tcp
+    firewall_add XMPP 5280 tcp
+    firewall_add XMPP 5281 tcp
     mark_completed $FUNCNAME
 }
 
@@ -271,11 +267,11 @@ function remove_xmpp_client {
 
 function remove_xmpp {
     remove_xmpp_client
-    iptables -D INPUT -p tcp --dport 5222:5223 -j ACCEPT
-    iptables -D INPUT -p tcp --dport 5269 -j ACCEPT
-    iptables -D INPUT -p tcp --dport 5280:5281 -j ACCEPT
-    function_check save_firewall_settings
-    save_firewall_settings
+    firewall_remove 5222 tcp
+    firewall_remove 5223 tcp
+    firewall_remove 5269 tcp
+    firewall_remove 5280 tcp
+    firewall_remove 5281 tcp
 
     function_check remove_onion_service
     remove_onion_service xmpp 5222 5223 5269
diff --git a/src/freedombone-app-zeronet b/src/freedombone-app-zeronet
index 7a2e21ede6daa053c7d3d0b0eff4f3826a79fa71..92a5fcbf4d927842e6b5d148341aaf90ca27613c 100755
--- a/src/freedombone-app-zeronet
+++ b/src/freedombone-app-zeronet
@@ -126,13 +126,11 @@ function remove_zeronet {
     remove_zeronet_blog
     remove_zeronet_mail
     remove_zeronet_forum
-    iptables -D INPUT -i $WIFI_INTERFACE -p udp --dport $ZERONET_PORT -j ACCEPT
-    iptables -D INPUT -i $WIFI_INTERFACE -p tcp --dport $ZERONET_PORT -j ACCEPT
-    iptables -D INPUT -i $WIFI_INTERFACE -p udp --dport $TRACKER_PORT -j ACCEPT
-    iptables -D INPUT -i $WIFI_INTERFACE -p tcp --dport $TRACKER_PORT -j ACCEPT
-    iptables -D INPUT -i $WIFI_INTERFACE -p udp --dport 1900 -j ACCEPT
-    function_check save_firewall_settings
-    save_firewall_settings
+
+    firewall_remove ${ZERONET_PORT}
+    firewall_remove ${TRACKER_PORT}
+    firewall_remove 1900 udp
+
     ${PROJECT_NAME}-mesh-install -f zeronet --remove yes
     remove_completion_param install_zeronet
     remove_completion_param configure_firewall_for_zeronet
@@ -143,16 +141,9 @@ function configure_firewall_for_zeronet {
     if [[ $(is_completed $FUNCNAME) == "1" ]]; then
         return
     fi
-    iptables -A INPUT -i $WIFI_INTERFACE -p udp --dport $ZERONET_PORT -j ACCEPT
-    iptables -A INPUT -i $WIFI_INTERFACE -p tcp --dport $ZERONET_PORT -j ACCEPT
-    iptables -A INPUT -i $WIFI_INTERFACE -p udp --dport $TRACKER_PORT -j ACCEPT
-    iptables -A INPUT -i $WIFI_INTERFACE -p tcp --dport $TRACKER_PORT -j ACCEPT
-    iptables -A INPUT -i $WIFI_INTERFACE -p udp --dport 1900 -j ACCEPT
-    function_check save_firewall_settings
-    save_firewall_settings
-
-    OPEN_PORTS+=("ZeroNet  $ZERONET_PORT")
-    OPEN_PORTS+=("Tracker  $TRACKER_PORT")
+    firewall_add ZeroNet ${ZERONET_PORT}
+    firewall_add Tracker ${TRACKER_PORT}
+    firewall_add Tracker 1900 udp
     mark_completed $FUNCNAME
 }
 
diff --git a/src/freedombone-base-email b/src/freedombone-base-email
index b4433581570055d98831640b54091483fb3604f8..4550068d1b451a8f6b2250a6239b522069f15a73 100755
--- a/src/freedombone-base-email
+++ b/src/freedombone-base-email
@@ -93,17 +93,11 @@ function configure_firewall_for_email {
     if [[ $ONION_ONLY != "no" ]]; then
         return
     fi
-    iptables -A INPUT -p tcp --dport 25 -j ACCEPT
-    iptables -A INPUT -p tcp --dport 587 -j ACCEPT
-    iptables -A INPUT -p tcp --dport 465 -j ACCEPT
-    iptables -A INPUT -p tcp --dport 993 -j ACCEPT
-    function_check save_firewall_settings
-    save_firewall_settings
-
-    OPEN_PORTS+=('Email    25')
-    OPEN_PORTS+=('Email    587')
-    OPEN_PORTS+=('Email    465')
-    OPEN_PORTS+=('Email    993')
+
+    firewall_add Email 25 tcp
+    firewall_add Email 587 tcp
+    firewall_add Email 465 tcp
+    firewall_add Imap 993 tcp
     mark_completed $FUNCNAME
 }
 
diff --git a/src/freedombone-utils-final b/src/freedombone-utils-final
index 03314d89f486d3c631342b9527addd42082474e9..aaf25a706122202fcac62baa86a8bff37502055a 100755
--- a/src/freedombone-utils-final
+++ b/src/freedombone-utils-final
@@ -28,8 +28,6 @@
 # You should have received a copy of the GNU Affero General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-OPEN_PORTS=()
-
 function install_final {
     if [[ $(is_completed $FUNCNAME) == "1" ]]; then
         return
@@ -50,10 +48,6 @@ function install_final {
 
     Ensure that these ports are forwarded from your internet router
 "
-    for p in "${OPEN_PORTS[@]}"
-    do
-        echo "  $p"
-    done
     echo ''
 
     if [ -f "/home/$MY_USERNAME/README" ]; then
diff --git a/src/freedombone-utils-firewall b/src/freedombone-utils-firewall
index 36ec3984fb4373ec8bfec4f4eebefd9726cd4764..5685c732361efcbd6852cb551de882b228c45cf7 100755
--- a/src/freedombone-utils-firewall
+++ b/src/freedombone-utils-firewall
@@ -28,6 +28,8 @@
 # You should have received a copy of the GNU Affero General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+FIREWALL_CONFIG=$HOME/firewall.cfg
+
 function save_firewall_settings {
     iptables-save > /etc/firewall.conf
     ip6tables-save > /etc/firewall6.conf
@@ -156,11 +158,8 @@ function configure_firewall_for_web_access {
     if [[ $ONION_ONLY != "no" ]]; then
         return
     fi
-    iptables -A INPUT -p tcp --dport 32768:61000 --sport 80 -j ACCEPT
-    iptables -A INPUT -p tcp --dport 32768:61000 --sport 443 -j ACCEPT
-    function_check save_firewall_settings
-    save_firewall_settings
-
+    firewall_remove 80 tcp
+    firewall_remove 443 tcp
     mark_completed $FUNCNAME
 }
 
@@ -175,13 +174,9 @@ function configure_firewall_for_web_server {
     if [[ $ONION_ONLY != "no" ]]; then
         return
     fi
-    iptables -A INPUT -p tcp --dport 80 -j ACCEPT
-    iptables -A INPUT -p tcp --dport 443 -j ACCEPT
-    function_check save_firewall_settings
-    save_firewall_settings
 
-    OPEN_PORTS+=('HTTP     80')
-    OPEN_PORTS+=('HTTPS    443')
+    firewall_add HTTP 80 tcp
+    firewall_add HTTPS 443 tcp
     mark_completed $FUNCNAME
 }
 
@@ -193,12 +188,9 @@ function configure_firewall_for_ssh {
         # docker does its own firewalling
         return
     fi
-    iptables -A INPUT -p tcp --dport 22 -j ACCEPT
-    iptables -A INPUT -p tcp --dport $SSH_PORT -j ACCEPT
-    function_check save_firewall_settings
-    save_firewall_settings
 
-    OPEN_PORTS+=("SSH      $SSH_PORT")
+    firewall_add SSH 22 tcp
+    firewall_add SSH ${SSH_PORT} tcp
     mark_completed $FUNCNAME
 }
 
@@ -213,11 +205,8 @@ function configure_firewall_for_git {
     if [[ $ONION_ONLY != "no" ]]; then
         return
     fi
-    iptables -A INPUT -p tcp --dport 9418 -j ACCEPT
-    function_check save_firewall_settings
-    save_firewall_settings
 
-    OPEN_PORTS+=("Git      9418")
+    firewall_add Git 9418 tcp
     mark_completed $FUNCNAME
 }
 
@@ -314,3 +303,52 @@ function mesh_firewall {
     echo 'WantedBy=multi-user.target' >> $FIREWALL_FILENAME
     chroot "$rootdir" systemctl enable meshfirewall
 }
+
+function firewall_add {
+    firewall_name="$1"
+    firewall_port=$2
+    firewall_protocol="$3"
+
+    if ! grep -q "${firewall_name}=${firewall_port}" $FIREWALL_CONFIG; then
+        echo "${firewall_name}=${firewall_port}" >> $FIREWALL_CONFIG
+        if [ ! ${firewall_protocol} ]; then
+            iptables -A INPUT -p udp --dport ${firewall_port} -j ACCEPT
+            iptables -A INPUT -p tcp --dport ${firewall_port} -j ACCEPT
+        else
+            if [[ "${firewall_protocol}" == *"udp"* ]]; then
+                iptables -A INPUT -p udp --dport ${firewall_port} -j ACCEPT
+            fi
+            if [[ "${firewall_protocol}" == *"tcp"* ]]; then
+                iptables -A INPUT -p tcp --dport ${firewall_port} -j ACCEPT
+            fi
+        fi
+        save_firewall_settings
+    fi
+}
+
+function firewall_remove {
+    firewall_port=$1
+    firewall_protocol="$2"
+
+    if [ ! -f $FIREWALL_CONFIG ]; then
+        return
+    fi
+
+    if grep -q "=${firewall_port}" $FIREWALL_CONFIG; then
+        if [ ! ${firewall_protocol} ]; then
+            iptables -D INPUT -p udp --dport ${firewall_port} -j ACCEPT
+            iptables -D INPUT -p tcp --dport ${firewall_port} -j ACCEPT
+        else
+            if [[ "${firewall_protocol}" == *"udp"* ]]; then
+                iptables -D INPUT -p udp --dport ${firewall_port} -j ACCEPT
+            fi
+            if [[ "${firewall_protocol}" == *"tcp"* ]]; then
+                iptables -D INPUT -p tcp --dport ${firewall_port} -j ACCEPT
+            fi
+        fi
+        sed -i "/=${firewall_port}/d" $FIREWALL_CONFIG
+        save_firewall_settings
+    fi
+}
+
+# NOTE: deliberately no exit 0