Merge branch '0.11'

pull/2642/head
sebres 2020-02-07 13:57:00 +01:00
commit 65ce64ba6d
6 changed files with 71 additions and 24 deletions

View File

@ -35,7 +35,8 @@ logSys = getLogger("fail2ban")
def output(s): # pragma: no cover
print(s)
CONFIG_PARAMS = ("socket", "pidfile", "logtarget", "loglevel", "syslogsocket",)
# Config parameters required to start fail2ban which can be also set via command line (overwrite fail2ban.conf),
CONFIG_PARAMS = ("socket", "pidfile", "logtarget", "loglevel", "syslogsocket")
# Used to signal - we are in test cases (ex: prevents change logging params, log capturing, etc)
PRODUCTION = True
@ -94,9 +95,10 @@ class Fail2banCmdLine():
output("and bans the corresponding IP addresses using firewall rules.")
output("")
output("Options:")
output(" -c <DIR> configuration directory")
output(" -s <FILE> socket path")
output(" -p <FILE> pidfile path")
output(" -c, --conf <DIR> configuration directory")
output(" -s, --socket <FILE> socket path")
output(" -p, --pidfile <FILE> pidfile path")
output(" --pname <NAME> name of the process (main thread) to identify instance (default fail2ban-server)")
output(" --loglevel <LEVEL> logging level")
output(" --logtarget <TARGET> logging target, use file-name or stdout, stderr, syslog or sysout.")
output(" --syslogsocket auto|<FILE>")
@ -129,17 +131,15 @@ class Fail2banCmdLine():
"""
for opt in optList:
o = opt[0]
if o == "-c":
if o in ("-c", "--conf"):
self._conf["conf"] = opt[1]
elif o == "-s":
elif o in ("-s", "--socket"):
self._conf["socket"] = opt[1]
elif o == "-p":
elif o in ("-p", "--pidfile"):
self._conf["pidfile"] = opt[1]
elif o.startswith("--log") or o.startswith("--sys"):
self._conf[ o[2:] ] = opt[1]
elif o in ["-d", "--dp", "--dump-pretty"]:
elif o in ("-d", "--dp", "--dump-pretty"):
self._conf["dump"] = True if o == "-d" else 2
elif o == "-t" or o == "--test":
elif o in ("-t", "--test"):
self.cleanConfOnly = True
self._conf["test"] = True
elif o == "-v":
@ -163,12 +163,14 @@ class Fail2banCmdLine():
from ..server.mytime import MyTime
output(MyTime.str2seconds(opt[1]))
return True
elif o in ["-h", "--help"]:
elif o in ("-h", "--help"):
self.dispUsage()
return True
elif o in ["-V", "--version"]:
elif o in ("-V", "--version"):
self.dispVersion(o == "-V")
return True
elif o.startswith("--"): # other long named params (see also resetConf)
self._conf[ o[2:] ] = opt[1]
return None
def initCmdLine(self, argv):
@ -185,6 +187,7 @@ class Fail2banCmdLine():
try:
cmdOpts = 'hc:s:p:xfbdtviqV'
cmdLongOpts = ['loglevel=', 'logtarget=', 'syslogsocket=', 'test', 'async',
'conf=', 'pidfile=', 'pname=', 'socket=',
'timeout=', 'str2sec=', 'help', 'version', 'dp', '--dump-pretty']
optList, self._args = getopt.getopt(self._argv[1:], cmdOpts, cmdLongOpts)
except getopt.GetoptError:
@ -227,7 +230,8 @@ class Fail2banCmdLine():
if not conf:
self.configurator.readEarly()
conf = self.configurator.getEarlyOptions()
self._conf[o] = conf[o]
if o in conf:
self._conf[o] = conf[o]
logSys.info("Using socket file %s", self._conf["socket"])

View File

@ -709,6 +709,7 @@ class Fail2banRegex(object):
def exec_command_line(*args):
logging.exitOnIOError = True
parser = get_opt_parser()
(opts, args) = parser.parse_args(*args)
errors = []

View File

@ -208,6 +208,25 @@ class FormatterWithTraceBack(logging.Formatter):
return logging.Formatter.format(self, record)
logging.exitOnIOError = False
def __stopOnIOError(logSys=None, logHndlr=None): # pragma: no cover
if logSys and len(logSys.handlers):
logSys.removeHandler(logSys.handlers[0])
if logHndlr:
logHndlr.close = lambda: None
logging.StreamHandler.flush = lambda self: None
#sys.excepthook = lambda *args: None
if logging.exitOnIOError:
try:
sys.stderr.close()
except:
pass
sys.exit(0)
try:
BrokenPipeError
except NameError: # pragma: 3.x no cover
BrokenPipeError = IOError
__origLog = logging.Logger._log
def __safeLog(self, level, msg, args, **kwargs):
"""Safe log inject to avoid possible errors by unsafe log-handlers,
@ -223,6 +242,10 @@ def __safeLog(self, level, msg, args, **kwargs):
try:
# if isEnabledFor(level) already called...
__origLog(self, level, msg, args, **kwargs)
except (BrokenPipeError, IOError) as e: # pragma: no cover
if e.errno == 32: # closed / broken pipe
__stopOnIOError(self)
raise
except Exception as e: # pragma: no cover - unreachable if log-handler safe in this python-version
try:
for args in (
@ -237,6 +260,18 @@ def __safeLog(self, level, msg, args, **kwargs):
pass
logging.Logger._log = __safeLog
__origLogFlush = logging.StreamHandler.flush
def __safeLogFlush(self):
"""Safe flush inject stopping endless logging on closed streams (redirected pipe).
"""
try:
__origLogFlush(self)
except (BrokenPipeError, IOError) as e: # pragma: no cover
if e.errno == 32: # closed / broken pipe
__stopOnIOError(None, self)
raise
logging.StreamHandler.flush = __safeLogFlush
def getLogger(name):
"""Get logging.Logger instance with Fail2Ban logger name convention
"""

View File

@ -81,8 +81,6 @@ class Server:
'Linux': '/dev/log',
}
self.__prev_signals = {}
# replace real thread name with short process name (for top/ps/pstree or diagnostic):
prctl_set_th_name('f2b/server')
def __sigTERMhandler(self, signum, frame): # pragma: no cover - indirect tested
logSys.debug("Caught signal %d. Exiting", signum)
@ -113,6 +111,9 @@ class Server:
logSys.error(err)
raise ServerInitializationError(err)
# We are daemon.
# replace main thread (and process) name to identify server (for top/ps/pstree or diagnostic):
prctl_set_th_name(conf.get("pname", "fail2ban-server"))
# Set all logging parameters (or use default if not specified):
self.__verbose = conf.get("verbose", None)

View File

@ -1,5 +1,5 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.4.
.TH FAIL2BAN-CLIENT "1" "January 2020" "fail2ban-client v1.0.1.dev1" "User Commands"
.TH FAIL2BAN-CLIENT "1" "February 2020" "fail2ban-client v1.0.1.dev1" "User Commands"
.SH NAME
fail2ban-client \- configure and control the server
.SH SYNOPSIS
@ -10,15 +10,18 @@ Fail2Ban v1.0.1.dev1 reads log file that contains password failure report
and bans the corresponding IP addresses using firewall rules.
.SH OPTIONS
.TP
\fB\-c\fR <DIR>
\fB\-c\fR, \fB\-\-conf\fR <DIR>
configuration directory
.TP
\fB\-s\fR <FILE>
\fB\-s\fR, \fB\-\-socket\fR <FILE>
socket path
.TP
\fB\-p\fR <FILE>
\fB\-p\fR, \fB\-\-pidfile\fR <FILE>
pidfile path
.TP
\fB\-\-pname\fR <NAME>
name of the process (main thread) to identify instance (default fail2ban\-server)
.TP
\fB\-\-loglevel\fR <LEVEL>
logging level
.TP

View File

@ -1,5 +1,5 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.4.
.TH FAIL2BAN-SERVER "1" "January 2020" "fail2ban-server v1.0.1.dev1" "User Commands"
.TH FAIL2BAN-SERVER "1" "February 2020" "fail2ban-server v1.0.1.dev1" "User Commands"
.SH NAME
fail2ban-server \- start the server
.SH SYNOPSIS
@ -10,15 +10,18 @@ Fail2Ban v1.0.1.dev1 reads log file that contains password failure report
and bans the corresponding IP addresses using firewall rules.
.SH OPTIONS
.TP
\fB\-c\fR <DIR>
\fB\-c\fR, \fB\-\-conf\fR <DIR>
configuration directory
.TP
\fB\-s\fR <FILE>
\fB\-s\fR, \fB\-\-socket\fR <FILE>
socket path
.TP
\fB\-p\fR <FILE>
\fB\-p\fR, \fB\-\-pidfile\fR <FILE>
pidfile path
.TP
\fB\-\-pname\fR <NAME>
name of the process (main thread) to identify instance (default fail2ban\-server)
.TP
\fB\-\-loglevel\fR <LEVEL>
logging level
.TP