Load iptables rules from systemd unit file, not from nether program 63/104863/6
authorRafal Krypa <r.krypa@samsung.com>
Wed, 28 Dec 2016 10:42:29 +0000 (11:42 +0100)
committerRafal Krypa <r.krypa@samsung.com>
Fri, 26 May 2017 12:09:00 +0000 (14:09 +0200)
Drop nether support for loading iptables rules. Such rules should ideally be
managed from a central place that implements multiple requirements, not only
nether. It is not right for nether to be the manager of iptables policy.

For now nether daemon will stop managing the rules, they will be loaded from
systemd unit files. It is already done for ip6tables rules, as nether never
handled ip6tables for IPv6, only iptables for IPv4.

Change-Id: Icb0cf1f42b54e0859c182a6a4baac42e85294388

README.md
conf/nether_ipv6.rules
conf/systemd/nether.service.in
include/nether_Manager.h
include/nether_Types.h
packaging/nether.spec
src/CMakeLists.txt
src/nether_Main.cpp
src/nether_Manager.cpp

index f0ec576..979fefa 100644 (file)
--- a/README.md
+++ b/README.md
@@ -16,7 +16,6 @@ backend stops working.
 Usage: nether [OPTIONS]
 
   -d,--daemon                          Run as daemon in the background (default:no)
-  -x,--no-rules                                Don't load iptables rules on start (default:no)
   -c,--copy-packets                    Copy entire packets, needed to read TCP/IP information (default:no)
   -I,--interface-info                  Get interface info for every packet (default:no)
   -R,--relaxed                         Run in relaxed mode, instrad of deny do ACCEPT_LOG(default:no)
@@ -34,8 +33,6 @@ Usage: nether [OPTIONS]
   -m,--mark-deny=<mark>                        Packet mark to use for DENY verdicts (default:3)
   -M,--mark-allow-log=<mark>           Packet mark to use for ALLOW_LOG verdicts (default:4)
   -a,--enable-audit                    Enable the auditing subsystem (default: no)
-  -r,--rules-path=<path>               Path to iptables rules file (default:/etc/nether/nether.rules)
-  -i,--iptables-restore-path=<path>    Path to iptables-restore command (default:/usr/sbin/iptables-restore)
   -h,--help                            show help information
 ```
 
@@ -57,8 +54,6 @@ Usage: nether [OPTIONS]
 There is just one argument that is the path to the location of the policy file.
 
 ## Details:
--x - by default nether loads iptables rules needed for nethet to catch packets it should make descisions about, the default set of rules can be found in CMAKE_INSTALL_PREFIX/etc/nether/nether.rules. Default rules catch first packets of each TCP/IP connection and ignore all traffic on the loopback interface. If you wish to change the default set of rules, edit this file. Or set the rules on your own and start nether with this option
-
 -c - by default nether does not receive the entire network packet, it's not needed to get the meta information about a packet (UID/GID and the security context of each packet). But if you policy backend needs more information about the network specifc part of a packet, setting this option will provide TCP/IP information to the backend (destination and source interface if available, destination and source IP address, destination and source PORT if the protocol is TCP/UDP). This option is used to gain more performance if the policy backend does not require network information.
 
 -I - same as -c but for network interface information
@@ -81,10 +76,6 @@ There is just one argument that is the path to the location of the policy file.
 
 -a - if audit headers are available, nether will activate auditing on start
 
--r - the path to the default set of rules nether should apply on start, by default this is set to ${CMAKE_INSTALL_DIR}/etc/nether/nether.rules
-
--i - the path to the iptables-restore program, it's needed to set the initial nether rules. No api is provided by netfilter to set the rules. iptables-restore is a preferred way to restore rules in the system.
-
 ## Poking holes in cynara policy:
 
 In order to exclude some traffic from the cynara policy, you can define custom privileges and paths they should take inside iptables. This is done by specifying a custom cynara.policy file with privilege|mark pairs. If a defined privilege gets a ALLOW response the packet that was beeing matched gets marked with the defined mark. Using the initial nether.rules you can add custom rules for those matched packets and do whatever you want with them.
index 185d746..5976193 100644 (file)
@@ -16,7 +16,7 @@
 #  limitations under the License
 #
 
-# nether iptables rules
+# nether ip6tables rules
 *mangle
 :PREROUTING ACCEPT
 :INPUT ACCEPT
index a3b776b..ac99fb4 100644 (file)
@@ -21,16 +21,18 @@ Description=nether service
 
 [Service]
 Type=simple
-ExecStart=${CMAKE_INSTALL_PREFIX}/bin/nether -l JOURNAL -P policy=${SYSCONF_INSTALL_DIR}/nether/cynara.policy -B ${SYSCONF_INSTALL_DIR}/nether/file.policy -r ${SYSCONF_INSTALL_DIR}/nether/nether.rules
-ExecStartPost=${SBIN_INSTALL_DIR}/ip6tables-restore ${SYSCONF_INSTALL_DIR}/nether/nether_ipv6.rules
+ExecStartPre=${SBIN_INSTALL_DIR}/iptables-restore ${SYSCONF_INSTALL_DIR}/nether/nether.rules
+ExecStartPre=${SBIN_INSTALL_DIR}/ip6tables-restore ${SYSCONF_INSTALL_DIR}/nether/nether_ipv6.rules
+ExecStart=${CMAKE_INSTALL_PREFIX}/bin/nether -l JOURNAL -P policy=${SYSCONF_INSTALL_DIR}/nether/cynara.policy -B ${SYSCONF_INSTALL_DIR}/nether/file.policy
 Restart=always
 ExecReload=/bin/kill -HUP $MAINPID
 User=security_fw
 Group=security_fw
 SecureBits=keep-caps
-Capabilities=cap_net_admin,cap_net_raw=eip
-CapabilityBoundingSet=CAP_NET_RAW CAP_NET_ADMIN
+Capabilities=cap_net_admin=i
+CapabilityBoundingSet=CAP_NET_ADMIN
 SmackProcessLabel=System
+PermissionsStartOnly=true
 
 [Install]
 WantedBy=multi-user.target
index 23e7557..9ba67ab 100644 (file)
@@ -41,10 +41,8 @@ class NetherManager : public NetherVerdictListener, public NetherProcessedPacket
                static NetherPolicyBackend *getPolicyBackend(const NetherConfig &netherConfig, const bool primary = true);
                bool verdictCast(const u_int32_t packetId, const NetherVerdict verdict, int mark);
                void packetReceived(const NetherPacket &packet);
-               bool restoreRules();
 
        private:
-               static bool isCommandAvailable(const std::string &command);
                void handleSignal();
                bool handleNetlinkpacket();
                void setupSelectSockets(fd_set &watchedReadDescriptorsSet, fd_set &watchedWriteDescriptorsSet, struct timeval &timeoutSpecification);
index 07c6edf..7a85bb8 100644 (file)
 
 #define NETLINK_INTERFACE_INFO                 0
 
-#ifndef NETHER_RULES_PATH
-#define NETHER_RULES_PATH                              "/etc/nether/nether.rules"
-#endif // NETHER_RULES_PATH
-
 #ifndef NETHER_POLICY_FILE
 #define NETHER_POLICY_FILE                             "/etc/nether/file.policy"
 #endif // NETHER_POLICY_FILE
 #define NETLINK_ALLOWLOG_MARK                  4
 #define NETLINK_QUEUE_NUM                              0
 #define NETHER_LOG_BACKEND                             NetherLogBackendType::stderrBackend
-#define NETHER_IPTABLES_RESTORE_PATH   "/usr/sbin/iptables-restore"
 
 enum class NetherPolicyBackendType : std::uint8_t
 {
@@ -183,13 +178,10 @@ struct NetherConfig
        int daemonMode                                                          = 0;
        int queueNumber                                                         = NETLINK_QUEUE_NUM;
        int enableAudit                                                         = 0;
-       int noRules                                                                     = 0;
        int copyPackets                                                         = NETLINK_COPY_PACKETS;
        int relaxed                                                                     = 0;
        int interfaceInfo                                                       = NETLINK_INTERFACE_INFO;
        std::string backupBackendArgs                           = NETHER_POLICY_FILE;
-       std::string rulesPath                                           = NETHER_RULES_PATH;
-       std::string iptablesRestorePath                         = NETHER_IPTABLES_RESTORE_PATH;
        std::string primaryBackendArgs;
        std::string logBackendArgs;
 };
index f24bb36..252cd1c 100755 (executable)
@@ -16,7 +16,7 @@ This is a network privilege enforcing service.
 %files
 %license LICENSE
 %defattr(644,root,root,755)
-%caps(cap_net_admin,cap_net_raw=ei) %attr(755,root,root) %{_bindir}/nether
+%caps(cap_net_admin=ei) %attr(755,root,root) %{_bindir}/nether
 %dir %{_sysconfdir}/nether
 %config %{_sysconfdir}/nether/file.policy
 %config %{_sysconfdir}/nether/nether.rules
index 7662092..3056da1 100644 (file)
@@ -80,7 +80,6 @@ TARGET_LINK_LIBRARIES (nether
        "-pie"
 )
 
-ADD_DEFINITIONS (-DNETHER_RULES_PATH="${CMAKE_INSTALL_DIR}/etc/nether/nether.rules"
-               -DNETHER_POLICY_FILE="${CMAKE_INSTALL_DIR}/etc/nether/file.policy")
+ADD_DEFINITIONS (-DNETHER_POLICY_FILE="${CMAKE_INSTALL_DIR}/etc/nether/file.policy")
 
 INSTALL (TARGETS nether RUNTIME DESTINATION bin)
index 7a815ed..203d0d8 100644 (file)
@@ -42,7 +42,6 @@ int main(int argc, char *argv[])
                {"enable-audit",            no_argument,        &netherConfig.enableAudit,              0},
 #endif
                {"daemon",                  no_argument,        &netherConfig.daemonMode,               0},
-               {"no-rules",                no_argument,        &netherConfig.noRules,                  0},
                {"copy-packets",                        no_argument,            &netherConfig.copyPackets,              0},
                {"interface-info",                      no_argument,            &netherConfig.interfaceInfo,    0},
                {"relaxed",                                     no_argument,            &netherConfig.relaxed,                  0},
@@ -56,8 +55,6 @@ int main(int argc, char *argv[])
                {"queue-num",               required_argument,  0,                                                              'q'},
                {"mark-deny",               required_argument,  0,                                                              'm'},
                {"mark-allow-log",          required_argument,  0,                                                              'M'},
-               {"rules-path",              required_argument,  0,                                                              'r'},
-               {"iptables-restore-path",   required_argument,  0,                                                              'i'},
                {"help",                    no_argument,        0,                                                              'h'},
                {0, 0, 0, 0}
        };
@@ -78,10 +75,6 @@ int main(int argc, char *argv[])
                                netherConfig.daemonMode             = 1;
                                break;
 
-                       case 'x':
-                               netherConfig.noRules                = 1;
-                               break;
-
                        case 'c':
                                netherConfig.copyPackets                        = 1;
                                break;
@@ -154,14 +147,6 @@ int main(int argc, char *argv[])
                                netherConfig.markAllowAndLog        = atoi(optarg);
                                break;
 
-                       case 'r':
-                               netherConfig.rulesPath              = optarg;
-                               break;
-
-                       case 'i':
-                               netherConfig.iptablesRestorePath    = optarg;
-                               break;
-
                        case 'h':
                                showHelp(argv[0]);
                                exit(1);
@@ -203,12 +188,9 @@ int main(int argc, char *argv[])
                 << " mark-allow-log="                  << (int)netherConfig.markAllowAndLog);
        LOGD("log-backend="                                     << logBackendTypeToString(netherConfig.logBackend)
                 << " log-backend-args="                << netherConfig.logBackendArgs);
-       LOGD("enable-audit="                            << (netherConfig.enableAudit ? "yes" : "no")
-                << " rules-path="                              << netherConfig.rulesPath);
-       LOGD("no-rules="                                        << (netherConfig.noRules ? "yes" : "no")
-                << " iptables-restore-path="   << netherConfig.iptablesRestorePath);
-       LOGD("interface-info="                          << (netherConfig.interfaceInfo ? "yes" : "no")
-               << " copy-packets="                             << (netherConfig.copyPackets ? "yes" : "no"));
+       LOGD("enable-audit="                            << (netherConfig.enableAudit ? "yes" : "no"));
+       LOGD("interface-info="                          << (netherConfig.interfaceInfo ? "yes" : "no"));
+       LOGD("copy-packets="                            << (netherConfig.copyPackets ? "yes" : "no"));
        LOGD("relaxed="                                         << (netherConfig.relaxed ? "yes" : "no"));
 
        NetherManager manager(netherConfig);
@@ -246,7 +228,6 @@ void showHelp(char *arg)
 {
        cout<< "Usage:\t"<< arg << " [OPTIONS]\n\n";
        cout<< "  -d,--daemon\t\t\t\tRun as daemon in the background (default:no)\n";
-       cout<< "  -x,--no-rules\t\t\t\tDon't load iptables rules on start (default:no)\n";
        cout<< "  -c,--copy-packets\t\t\tCopy entire packets, needed to read TCP/IP information (default:no)\n";
        cout<< "  -I,--interface-info\t\t\tGet interface info for every packet (default:no)\n";
        cout<< "  -R,--relaxed\t\t\t\tRun in relaxed mode, instead of deny do ACCEPT_LOG(default:no)\n";
@@ -275,8 +256,6 @@ void showHelp(char *arg)
 #if defined(HAVE_AUDIT)
        cout<< "  -a,--enable-audit\t\t\tEnable the auditing subsystem (default: no)\n";
 #endif
-       cout<< "  -r,--rules-path=<path>\t\tPath to iptables rules file (default:" << NETHER_RULES_PATH << ")\n";
-       cout<< "  -i,--iptables-restore-path=<path>\tPath to iptables-restore command (default:" << NETHER_IPTABLES_RESTORE_PATH << ")\n";
        cout<< "  -h,--help\t\t\t\tshow help information\n";
 }
 
index efe1094..1b0725c 100644 (file)
@@ -113,14 +113,6 @@ bool NetherManager::initialize()
                return (false);
        }
 
-       /* Load the rules as last, in case we have a problem with any
-               above subsystems, we won't leave hanging useless rules */
-       if(netherConfig.noRules == 0 && restoreRules() == false)
-       {
-               LOGE("Failed to setup iptables rules");
-               return (false);
-       }
-
        if((backendDescriptor = netherPrimaryPolicyBackend->getDescriptor()) == -1)
        {
                LOGI("Policy backend does not provide descriptor for select()");
@@ -321,44 +313,3 @@ void NetherManager::packetReceived(const NetherPacket &packet)
        LOGW("All policy backends failed, using DUMMY backend");
        netherFallbackPolicyBackend->enqueueVerdict(packet);
 }
-
-bool NetherManager::restoreRules()
-{
-       if(!isCommandAvailable(netherConfig.iptablesRestorePath))
-       {
-               return (false);
-       }
-
-       std::stringstream cmdline;
-       cmdline << netherConfig.iptablesRestorePath;
-       cmdline << " ";
-       cmdline << netherConfig.rulesPath;
-
-       if(system(cmdline.str().c_str()))
-       {
-               LOGE("system() failed for: " << cmdline.str());
-               return (false);
-       }
-
-       LOGD("iptables-restore succeeded with rules from: " << netherConfig.rulesPath);
-       return (true);
-}
-
-bool NetherManager::isCommandAvailable(const std::string &command)
-{
-       struct stat iptablesRestoreStat;
-
-       if(stat(command.c_str(), &iptablesRestoreStat) == 0)
-       {
-               if(! (iptablesRestoreStat.st_mode & S_IXUSR))
-               {
-                       LOGE("Execute bit is not set for owner on:" << command);
-                       return (false);
-               }
-
-               return (true);
-       }
-
-       LOGE("Failed to stat command at: " << command << " error: " << strerror(errno));
-       return (false);
-}