Skip to content

Commit fd3c748

Browse files
authored
Simplify search for iptables executable (#382)
* fix safe exec * fix black format * iptables simplify * iptables search * Remove unused import
1 parent 2509734 commit fd3c748

File tree

5 files changed

+19
-60
lines changed

5 files changed

+19
-60
lines changed

bin/opencanary.tac

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import sys
44
from twisted.application import service
55
from pkg_resources import iter_entry_points
66

7-
from opencanary.config import config, is_docker, detectIPTables
7+
from opencanary.config import config, is_docker
88
from opencanary.logger import getLogger
99
from opencanary.modules.http import CanaryHTTP
1010
from opencanary.modules.https import CanaryHTTPS
@@ -84,8 +84,6 @@ if sys.platform.startswith("linux"):
8484
if config.moduleEnabled("portscan") and is_docker():
8585
# Remove portscan if running in DOCKER (specified in Dockerfile)
8686
print("Can't use portscan in Docker. Portscan module disabled.")
87-
elif config.moduleEnabled("portscan") and not detectIPTables():
88-
print("Can't use portscan without iptables. Please install iptables.")
8987
else:
9088
from opencanary.modules.portscan import CanaryPortscan
9189

docs/starting/configuration.rst

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ For this configuration, you will need to set up your own Windows File Share. Ple
4141

4242
`portscan` - a log watcher that works with iptables to monitor when your Opencanary is being scanned.
4343
At this stage, the portscan module supports the detection of Nmap OS, Nmap FIN, Nmap OS, Nmap NULL, and normal port scans.
44-
`portscan.iptables_path` is available for you to specify the path to your `iptables` binary.
4544

4645
Logger Configuration
4746
--------------------

opencanary/__init__.py

Lines changed: 1 addition & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,5 @@
11
import os
2-
import subprocess
32

43
__version__ = "0.9.5"
54

6-
from os import PathLike
7-
from typing import Union
8-
9-
BIN_LOCATIONS = ["/usr/bin", "/bin", "/usr/sbin", "/sbin"]
10-
11-
12-
def _check_file_exists_and_executable(path: Union[PathLike, str]) -> bool:
13-
if not os.path.isfile(path):
14-
return False
15-
else:
16-
return os.access(path, os.X_OK)
17-
18-
19-
def safe_exec(binary_name: str, args: list) -> bytes:
20-
"""
21-
Executes the given binary with the given arguments as a subprocess. What makes this safe is that the binary name
22-
is not executed as an alias, and only binaries that live in trusted system locations are executed. This means that
23-
only system-wide binaries are executable.
24-
"""
25-
exec_path = None
26-
for prefix in BIN_LOCATIONS:
27-
bin_path = os.path.join(prefix, binary_name)
28-
if _check_file_exists_and_executable(os.path.join(prefix, binary_name)):
29-
exec_path = bin_path
30-
break
31-
if exec_path is None:
32-
raise Exception(f"Could not find executable ${binary_name}")
33-
else:
34-
return subprocess.check_output(args, shell=True, executable=exec_path)
5+
STDPATH = os.pathsep.join(["/usr/bin", "/bin", "/usr/sbin", "/sbin"])

opencanary/config.py

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,10 @@
33
import json
44
import itertools
55
import string
6-
import shutil
76
import re
87
from os.path import expanduser
98
from pkg_resources import resource_filename
109
from pathlib import Path
11-
from . import safe_exec
1210

1311
SAMPLE_SETTINGS = resource_filename(__name__, "data/settings.json")
1412
SETTINGS = "opencanary.conf"
@@ -36,13 +34,6 @@ def is_docker():
3634
)
3735

3836

39-
def detectIPTables():
40-
if shutil.which("iptables"):
41-
return True
42-
else:
43-
return False
44-
45-
4637
SERVICE_REGEXES = {
4738
"ssh.version": r"(SSH-(2.0|1.5|1.99|1.0)-([!-,\-./0-~]+(:?$|\s))(?:[ -~]*)){1,253}$",
4839
}
@@ -77,7 +68,6 @@ def __init__(self, configfile=SETTINGS):
7768
print("[-] Failed to open %s for reading (%s)" % (fname, e))
7869
except ValueError as e:
7970
print("[-] Failed to decode json from %s (%s)" % (fname, e))
80-
safe_exec("cp", ["-r", fname, "/var/tmp/config-err-$(date +%%s)"])
8171
except Exception as e:
8272
print("[-] An error occurred loading %s (%s)" % (fname, e))
8373
if self.__config is None:

opencanary/modules/portscan.py

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
from opencanary.modules import CanaryService
22
from opencanary.modules import FileSystemWatcher
3-
from opencanary import safe_exec
3+
from opencanary import STDPATH
44
import os
5+
import subprocess
56
import shutil
67

78

@@ -67,10 +68,6 @@ def handleLines(self, lines=None): # noqa: C901
6768
self.logger.log(data)
6869

6970

70-
def detectNFTables():
71-
return b"nf_tables" in safe_exec("iptables", ["--version"])
72-
73-
7471
class CanaryPortscan(CanaryService):
7572
NAME = "portscan"
7673

@@ -85,18 +82,8 @@ def __init__(self, config=None, logger=None):
8582
"portscan.ignore_localhost", default=False
8683
)
8784
self.ignore_ports = config.getVal("portscan.ignore_ports", default=[])
88-
self.iptables_path = self.config.getVal("portscan.iptables_path", False)
8985
self.config = config
9086

91-
def getIptablesPath(self):
92-
if self.iptables_path:
93-
return self.iptables_path
94-
95-
if detectNFTables():
96-
return shutil.which("iptables-legacy")
97-
98-
return shutil.which("iptables") or "/sbin/iptables"
99-
10087
def startYourEngines(self, reactor=None):
10188
# Logging rules for loopback interface.
10289
# This is separate from the canaryfw rule as the canary watchdog was
@@ -117,7 +104,21 @@ def configUpdated(
117104
pass
118105

119106
def set_iptables_rules(self):
120-
iptables_path = self.getIptablesPath()
107+
iptables_path = shutil.which("iptables-legacy", path=STDPATH)
108+
109+
if not iptables_path:
110+
iptables_path = shutil.which("iptables", path=STDPATH)
111+
112+
if not iptables_path:
113+
err = "Portscan module failed to start as iptables cannot be found. Please install iptables."
114+
print(err)
115+
raise Exception(err)
116+
117+
if b"nf_tables" in subprocess.check_output([iptables_path, "--version"]):
118+
err = "Portscan module failed to start as iptables-legacy cannot be found. Please install iptables-legacy"
119+
print(err)
120+
raise Exception(err)
121+
121122
os.system(
122123
'sudo {0} -t mangle -D PREROUTING -p tcp -i lo -j LOG --log-level=warning --log-prefix="canaryfw: " -m limit --limit="{1}/hour"'.format(
123124
iptables_path, self.lorate

0 commit comments

Comments
 (0)