[server] Added FLUSH_IPFW_AT_INIT and FLUSH_IPFW_AT_EXIT
authorMichael Rash <mbr@cipherdyne.org>
Sat, 11 Aug 2012 01:48:02 +0000 (21:48 -0400)
committerMichael Rash <mbr@cipherdyne.org>
Sat, 11 Aug 2012 01:48:02 +0000 (21:48 -0400)
Added FLUSH_IPFW_AT_INIT and FLUSH_IPFW_AT_EXIT for ipfw firewalls to emulate
the corresponding functionality that is implemented for iptables firewalls.

Bug fix for ipfw firewalls to ensure that if the ipfw expire set is zero, then
do not disable this set whenever the FLUSH_IPFW* variables are enabled.

These changes were suggested by Jonathan Schulz.

server/cmd_opts.h
server/config_init.c
server/fw_util_ipfw.c
server/fwknopd.conf
server/fwknopd_common.h

index 68e59bb..05dc9ca 100644 (file)
@@ -79,6 +79,8 @@ static char *config_map[NUMBER_OF_CONFIG_ENTRIES] = {
     "IPT_SNAT_ACCESS",
     "IPT_MASQUERADE_ACCESS",
 #elif FIREWALL_IPFW
+    "FLUSH_IPFW_AT_INIT",
+    "FLUSH_IPFW_AT_EXIT",
     "IPFW_START_RULE_NUM",
     "IPFW_MAX_RULES",
     "IPFW_ACTIVE_SET_NUM",
index ef83750..f83ce20 100644 (file)
@@ -43,7 +43,7 @@ range_check(fko_srv_options_t *opts, char *var, char *val, int low, int high)
 {
     if (low > atoi(val) || high < atoi(val))
     {
-        fprintf(stderr, "[*] var %s value '%s' not in the range %d-%d",
+        fprintf(stderr, "[*] var %s value '%s' not in the range %d-%d\n",
             var, val, low, high);
         clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
     }
@@ -150,6 +150,19 @@ validate_int_var_ranges(fko_srv_options_t *opts)
         opts->config[CONF_IPFW_EXPIRE_PURGE_INTERVAL],
         1, RCHK_MAX_IPFW_PURGE_INTERVAL);
 
+    /* Make sure the active and expire sets are not identical whenever
+     * they are non-zero
+    */
+    if((opts->config[CONF_IPFW_ACTIVE_SET_NUM] > 0
+            && opts->config[CONF_IPFW_EXPIRE_SET_NUM] > 0)
+            && (opts->config[CONF_IPFW_ACTIVE_SET_NUM]
+                == opts->config[CONF_IPFW_EXPIRE_SET_NUM]))
+    {
+        fprintf(stderr,
+                "[*] Cannot set identical ipfw active and expire sets.\n");
+        clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
+    }
+
 #elif FIREWALL_PF
     range_check(opts, "PF_EXPIRE_INTERVAL", opts->config[CONF_PF_EXPIRE_INTERVAL],
         1, RCHK_MAX_PF_EXPIRE_INTERVAL);
@@ -446,6 +459,17 @@ validate_options(fko_srv_options_t *opts)
             DEF_IPT_MASQUERADE_ACCESS);
 
 #elif FIREWALL_IPFW
+
+    /* Flush ipfw rules at init.
+    */
+    if(opts->config[CONF_FLUSH_IPFW_AT_INIT] == NULL)
+        set_config_entry(opts, CONF_FLUSH_IPFW_AT_INIT, DEF_FLUSH_IPFW_AT_INIT);
+
+    /* Flush ipfw rules at exit.
+    */
+    if(opts->config[CONF_FLUSH_IPFW_AT_EXIT] == NULL)
+        set_config_entry(opts, CONF_FLUSH_IPFW_AT_EXIT, DEF_FLUSH_IPFW_AT_EXIT);
+
     /* Set IPFW start rule number.
     */
     if(opts->config[CONF_IPFW_START_RULE_NUM] == NULL)
index ae44168..89eb26c 100644 (file)
@@ -212,7 +212,8 @@ fw_initialize(const fko_srv_options_t *opts)
 
     /* For now, we just call fw_cleanup to start with clean slate.
     */
-    res = fw_cleanup(opts);
+    if(strncasecmp(opts->config[CONF_FLUSH_IPFW_AT_INIT], "Y", 1) == 0)
+        res = fw_cleanup(opts);
 
     if(res != 0)
     {
@@ -261,26 +262,30 @@ fw_initialize(const fko_srv_options_t *opts)
             log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err_buf);
     }
 
-    /* Make sure our expire set is disabled.
-    */
-    zero_cmd_buffers();
+    if(fwc.expire_set_num > 0
+            && (strncasecmp(opts->config[CONF_FLUSH_IPFW_AT_INIT], "Y", 1) == 0))
+    {
+        /* Make sure our expire set is disabled.
+        */
+        zero_cmd_buffers();
 
-    snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPFW_DISABLE_SET_ARGS,
-        fwc.fw_command,
-        fwc.expire_set_num
-    );
+        snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPFW_DISABLE_SET_ARGS,
+            fwc.fw_command,
+            fwc.expire_set_num
+        );
 
-    res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, 0);
+        res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, 0);
 
-    if (opts->verbose)
-        log_msg(LOG_INFO, "fw_initialize() CMD: '%s' (res: %d, err: %s)",
-            cmd_buf, res, err_buf);
+        if (opts->verbose)
+            log_msg(LOG_INFO, "fw_initialize() CMD: '%s' (res: %d, err: %s)",
+                cmd_buf, res, err_buf);
 
-    if(EXTCMD_IS_SUCCESS(res))
-        log_msg(LOG_INFO, "Set ipfw expire set %u to disabled.",
-            fwc.expire_set_num);
-    else
-        log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err_buf);
+        if(EXTCMD_IS_SUCCESS(res))
+            log_msg(LOG_INFO, "Set ipfw expire set %u to disabled.",
+                fwc.expire_set_num);
+        else
+            log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err_buf);
+    }
 
     /* Now read the expire set in case there are existing
      * rules to track.
@@ -351,6 +356,13 @@ fw_cleanup(const fko_srv_options_t *opts)
 {
     int     res, got_err = 0;
 
+    if(strncasecmp(opts->config[CONF_FLUSH_IPFW_AT_EXIT], "N", 1) == 0)
+    {
+        if(fwc.rule_map != NULL)
+            free(fwc.rule_map);
+        return(0);
+    }
+
     zero_cmd_buffers();
 
     if(fwc.active_set_num > 0
index 2b6e268..6aed85e 100644 (file)
 # the pcap loop.  The default is 100000 microseconds, or 1/10th of a second.
 #PCAP_LOOP_SLEEP                100000;
 
-# Allow SPA clients to request access to services through an iptables
-# firewall instead of just to it (i.e. access through the FWKNOP_FORWARD
-# chain instead of the INPUT chain).
-#
-#ENABLE_IPT_FORWARDING       N;
-
-# Allow SPA clients to request access to a local socket via NAT.  This still
-# puts an ACCEPT rule into the FWKNOP_INPUT chain, but a different port is
-# translated via DNAT rules to the real one.  So, the user would do
-# "ssh -p <port>" to access the local service (see the --NAT-local and
-# --NAT-rand-port on the fwknop client command line).
-#
-#ENABLE_IPT_LOCAL_NAT        Y;
-
-# By default, if forwarding access is enabled (see the ENABLE_IPT_FORWARDING
-# variable above), then fwknop creates DNAT rules for incoming connections,
-# but does not also complement these rules with SNAT rules at the same time.
-# In some situations, internal systems may not have a route back out for the
-# source address of the incoming connection, so it is necessary to also
-# apply SNAT rules so that the internal systems see the IP of the internal
-# interface where fwknopd is running.  This functionality is only enabled
-# when ENABLE_IPT_SNAT is set to "Y", and by default SNAT rules are built
-# with the MASQUERADE target (since then the internal IP does not have to be
-# defined here in the fwknop.conf file), but if you want fwknopd to use the
-# SNAT target then also defined an IP address with the SNAT_TRANSLATE_IP
-# variable.
-#
-#ENABLE_IPT_SNAT             N;
-#SNAT_TRANSLATE_IP           __CHANGEME__;
-
-# Add ACCEPT rules to the FWKNOP_OUTPUT chain. This is usually only useful
-# if there are no state tracking rules to allow connection responses out and
-# the OUTPUT chain has a default-drop stance.
-#
-#ENABLE_IPT_OUTPUT           N;
-
 # Specify the the maximum number of bytes to sniff per frame - 1500
 # is a good default
 #
 #MAX_SNIFF_BYTES             1500;
 
-# Flush all existing rules in the fwknop chains at fwknop start time and/or
-# exit time. They default to Y and it is recommended setting for both.
-#
-#FLUSH_IPT_AT_INIT           Y;
-#FLUSH_IPT_AT_EXIT           Y;
-
 # If GPG keys are used instead of a Rijndael symmetric key, this is
 # the default GPG keys directory.  Note that each access block in
 # fwknop access.conf can specify its own GPG directory to override
 # accept incoming TCP request.  This server only accepts the
 # request.  It does not otherwise communicate. This is only to allow the
 # incoming SPA over TCP packet which is detected via PCAP. The connection
-# is closed after 1 second regardless. 
+# is closed after 1 second regardless.
 # Note that fwknopd still only gets its data via pcap, so the filter
 # defined by PCAP_FILTER needs to be updated to include this TCP port.
 #
 
 ##############################################################################
 # Parameters specific to iptables:
+
+# Flush all existing rules in the fwknop chains at fwknop start time and/or
+# exit time. They default to Y and it is a recommended setting for both.
 #
+#FLUSH_IPT_AT_INIT           Y;
+#FLUSH_IPT_AT_EXIT           Y;
+#
+
+# Allow SPA clients to request access to services through an iptables
+# firewall instead of just to it (i.e. access through the FWKNOP_FORWARD
+# chain instead of the INPUT chain).
+#
+#ENABLE_IPT_FORWARDING       N;
+
+# Allow SPA clients to request access to a local socket via NAT.  This still
+# puts an ACCEPT rule into the FWKNOP_INPUT chain, but a different port is
+# translated via DNAT rules to the real one.  So, the user would do
+# "ssh -p <port>" to access the local service (see the --NAT-local and
+# --NAT-rand-port on the fwknop client command line).
+#
+#ENABLE_IPT_LOCAL_NAT        Y;
+
+# By default, if forwarding access is enabled (see the ENABLE_IPT_FORWARDING
+# variable above), then fwknop creates DNAT rules for incoming connections,
+# but does not also complement these rules with SNAT rules at the same time.
+# In some situations, internal systems may not have a route back out for the
+# source address of the incoming connection, so it is necessary to also
+# apply SNAT rules so that the internal systems see the IP of the internal
+# interface where fwknopd is running.  This functionality is only enabled
+# when ENABLE_IPT_SNAT is set to "Y", and by default SNAT rules are built
+# with the MASQUERADE target (since then the internal IP does not have to be
+# defined here in the fwknop.conf file), but if you want fwknopd to use the
+# SNAT target then also defined an IP address with the SNAT_TRANSLATE_IP
+# variable.
+#
+#ENABLE_IPT_SNAT             N;
+#SNAT_TRANSLATE_IP           __CHANGEME__;
+
+# Add ACCEPT rules to the FWKNOP_OUTPUT chain. This is usually only useful
+# if there are no state tracking rules to allow connection responses out and
+# the OUTPUT chain has a default-drop stance.
+#
+#ENABLE_IPT_OUTPUT           N;
+
 # fwknopd adds allow rules to a custom iptables chain "FWKNOP_INPUT".
 # This chain is called from the INPUT chain, and by default no other
 # iptables chains are used.  However, additional chains can be added
 #
 #IPFW_MAX_RULES              1000;
 
+# Flush all existing rules in the fwknop ipfw sets at fwknop start time and/or
+# exit time. They default to Y and it is a recommended setting for both.
+#
+#FLUSH_IPFW_AT_INIT           Y;
+#FLUSH_IPFW_AT_EXIT           Y;
+
 # This variable defines the rule set fwknopd uses for active rules. By
-# default, it is set 0, but can be set to any number between 0 and 31 in
-# case you want to keep fwknopd generated rules segregated from the default
-# ruleset.
+# default, it is set 1 and fwknopd assumes that it has full control over this
+# set.  That is, fwknopd routinely creates and deletes rules in this set, and
+# the entire set itself is also created/deleted during routine operations.
+# You have some measure of control over whether the entire set is deleted at
+# init/exit with the FLUSH_IPFW_AT_INIT and FLUSH_IPFW_AT_EXIT, but in general
+# it is recommended to leave these variables set to the default "Y" setting.
 #
 #IPFW_ACTIVE_SET_NUM         1;
 
 # This variable defines the rule set that will be used to store expired rules
 # that still have a dynamic rule associated to them. That set will be disabled
 # by fwknop and should not be enabled while fwknop is running. Not used when
-# ipfw isn't using dynamic rules.
+# ipfw isn't using dynamic rules.  By default, it is set 2, but can be anything
+# in the range 1-31 except that it shouldn't be the same as
+# IPFW_ACTIVE_SET_NUM.  Note that fwknopd disables this set through routine
+# operations according to the FLUSH_IPFW_AT_INIT and FLUSH_IPFW_AT_EXIT
+# variables.
 #
 #IPFW_EXPIRE_SET_NUM         2;
 
index d5abd74..3ba797d 100644 (file)
 */
 #elif FIREWALL_IPFW
 
+  #define DEF_FLUSH_IPFW_AT_INIT         "Y"
+  #define DEF_FLUSH_IPFW_AT_EXIT         "Y"
   #define DEF_IPFW_START_RULE_NUM        "10000"
   #define DEF_IPFW_MAX_RULES             "1000"
   #define DEF_IPFW_ACTIVE_SET_NUM        "1"
@@ -200,6 +202,8 @@ enum {
     CONF_IPT_SNAT_ACCESS,
     CONF_IPT_MASQUERADE_ACCESS,
 #elif FIREWALL_IPFW
+    CONF_FLUSH_IPFW_AT_INIT,
+    CONF_FLUSH_IPFW_AT_EXIT,
     CONF_IPFW_START_RULE_NUM,
     CONF_IPFW_MAX_RULES,
     CONF_IPFW_ACTIVE_SET_NUM,