Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
06ebf97afe | ||
|
|
0785a631f4 | ||
|
|
d8083ef418 | ||
|
|
3ade428344 | ||
|
|
300ea79ede | ||
|
|
79b344b38a | ||
|
|
317c68d39f | ||
|
|
602f47553c | ||
|
|
737b7e7c5b | ||
|
|
b4e2a313cf | ||
|
|
ee2015a57b | ||
|
|
e54becdf20 | ||
|
|
aca5cae6c1 | ||
|
|
0507b336a9 | ||
|
|
0b1182ec3d | ||
|
|
42ff2f5655 | ||
|
|
0b174109ed | ||
|
|
55185c224b | ||
|
|
aea70532bb | ||
|
|
99518c4dc3 | ||
|
|
ccb54bbdc1 | ||
|
|
3f2e388454 | ||
|
|
d38cbca9bb | ||
|
|
4f0b50ba69 | ||
|
|
e914d0ff09 | ||
|
|
11b251a826 | ||
|
|
ea077a7da7 | ||
|
|
e13d134fa3 | ||
|
|
f8f5df39cd | ||
|
|
cf6b27963f | ||
|
|
1250a27bc9 | ||
|
|
ff13d5915e | ||
|
|
11088f25c0 | ||
|
|
ea08a60eb0 | ||
|
|
b8ee170c15 | ||
|
|
5dba68b2cb | ||
|
|
d4c122a5aa | ||
|
|
c2f91b90de | ||
|
|
f6f206255c | ||
|
|
df79202087 | ||
|
|
b78ac466b4 | ||
|
|
d4cbaf5b37 | ||
|
|
bb7d6fdf4f | ||
|
|
3d8ea894b5 | ||
|
|
67e1030312 | ||
|
|
08fba6c0d9 | ||
|
|
293ff25b12 | ||
|
|
5ea24f273b | ||
|
|
ae8210cc28 | ||
|
|
e0ed41a22e | ||
|
|
a729769d51 | ||
|
|
9cea6d662b | ||
|
|
dcbcf5e8bf | ||
|
|
fdca4d13fc | ||
|
|
52d3613a6e | ||
|
|
2232dcf524 | ||
|
|
bb77991363 | ||
|
|
342f04353f | ||
|
|
39b0665efe | ||
|
|
1de0603f08 | ||
|
|
e9a326dfe6 | ||
|
|
6a2d90e16c | ||
|
|
f824d37c4e | ||
|
|
f5e2ae1c02 | ||
|
|
8525586d50 | ||
|
|
a23e39655a | ||
|
|
0e514949da | ||
|
|
11110c3794 | ||
|
|
ef41e1f760 | ||
|
|
11d50af2c2 | ||
|
|
170eee062c | ||
|
|
ec9c741f14 | ||
|
|
1ec4270f2b | ||
|
|
092d582a84 | ||
|
|
227e6e3fda | ||
|
|
462de19aac | ||
|
|
ce6aa54e16 | ||
|
|
6d5ffe58f4 | ||
|
|
2ed445c2d3 | ||
|
|
6d981715a6 | ||
|
|
39a2444a1c | ||
|
|
b96b6bd76a | ||
|
|
e2799fb8c8 | ||
|
|
f0283d1c09 |
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<?eclipse-pydev version="1.0"?>
|
||||
|
||||
<pydev_project>
|
||||
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.4</pydev_property>
|
||||
<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
|
||||
<path>/fail2ban-unstable/client</path>
|
||||
<path>/fail2ban-unstable/server</path>
|
||||
<path>/fail2ban-unstable/testcases</path>
|
||||
<path>/fail2ban-unstable</path>
|
||||
</pydev_pathproperty>
|
||||
</pydev_project>
|
||||
@@ -4,9 +4,63 @@
|
||||
|_| \__,_|_|_/___|_.__/\__,_|_||_|
|
||||
|
||||
=============================================================
|
||||
Fail2Ban (version 0.7.4) 2006/11/01
|
||||
Fail2Ban (version 0.7.7) 2007/02/08
|
||||
=============================================================
|
||||
|
||||
ver. 0.7.7 (2007/02/08) - release candidate
|
||||
----------
|
||||
- Added signal handling in fail2ban-client
|
||||
- Added a wonderful visual effect when waiting on the server
|
||||
- fail2ban-client returns an error code if configuration is
|
||||
not valid
|
||||
- Added new filters/actions. Thanks to Yaroslav Halchenko
|
||||
- Call Python interpreter directly (instead of using "env")
|
||||
- Added file support to fail2ban-regex. Benchmark feature has
|
||||
been removed
|
||||
- Added cacti script and template.
|
||||
- Added IP list in "status <JAIL>". Thanks to Eric Gerbier
|
||||
|
||||
ver. 0.7.6 (2007/01/04) - beta
|
||||
----------
|
||||
- Added a "sleep 1" in redhat-initd. Thanks to Jim Wight
|
||||
- Use /dev/log for SYSLOG output. Thanks to Joerg Sommrey
|
||||
- Use numeric output for iptables in "actioncheck"
|
||||
- Fixed removal of host in hosts.deny. Thanks to René Berber
|
||||
- Added new date format (2006-12-21 06:43:20) and Exim4
|
||||
filter. Thanks to mEDI
|
||||
- Several "failregex" and "ignoreregex" are now accepted.
|
||||
Creation of rules should be easier now.
|
||||
- Added license in COPYING. Thanks to Axel Thimm
|
||||
- Allow comma in action options. The value of the option must
|
||||
be escaped with " or '. Thanks to Yaroslav Halchenko
|
||||
- Now Fail2ban goes in /usr/share/fail2ban instead of
|
||||
/usr/lib/fail2ban. This is more compliant with FHS. Thanks
|
||||
to Axel Thimm and Yaroslav Halchenko
|
||||
|
||||
ver. 0.7.5 (2006/12/07) - beta
|
||||
----------
|
||||
- Do not ban a host that is currently banned. Thanks to
|
||||
Yaroslav Halchenko
|
||||
- The supported tags in "action(un)ban" are <ip>, <failures>
|
||||
and <time>
|
||||
- Fixed refactoring bug (getLastcommand -> getLastAction)
|
||||
- Added option "ignoreregex" in filter scripts and jail.conf.
|
||||
Feature Request #1283304
|
||||
- Fixed a bug in user defined time regex/pattern
|
||||
- Improved documentation
|
||||
- Moved version.py and protocol.py to common/
|
||||
- Merged "maxtime" option with "findtime"
|
||||
- Added "<HOST>" tag support in failregex which matches
|
||||
default IP address/hostname. "(?P<host>\S)" is still valid
|
||||
and supported
|
||||
- Fixed exception when calling fail2ban-server with unknown
|
||||
option
|
||||
- Fixed Debian bug 400162. The "socket" option is now handled
|
||||
correctly by fail2ban-client
|
||||
- Fixed RedHat init script. Thanks to Justin Shore
|
||||
- Changed timeout to 30 secondes before assuming the server
|
||||
cannot be started. Thanks to Joël Bertrand
|
||||
|
||||
ver. 0.7.4 (2006/11/01) - beta
|
||||
----------
|
||||
- Improved configuration files. Thanks to Yaroslav Halchenko
|
||||
|
||||
@@ -0,0 +1,339 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
@@ -1,6 +1,7 @@
|
||||
README
|
||||
CHANGELOG
|
||||
TODO
|
||||
COPYING
|
||||
fail2ban-client
|
||||
fail2ban-server
|
||||
fail2ban-testcases
|
||||
@@ -39,6 +40,8 @@ server/dateepoch.py
|
||||
server/banmanager.py
|
||||
server/datetemplate.py
|
||||
server/mytime.py
|
||||
server/regex.py
|
||||
server/failregex.py
|
||||
testcases/banmanagertestcase.py
|
||||
testcases/failmanagertestcase.py
|
||||
testcases/clientreadertestcase.py
|
||||
@@ -53,7 +56,9 @@ testcases/files/testcase03.log
|
||||
testcases/files/testcase04.log
|
||||
setup.py
|
||||
setup.cfg
|
||||
version.py
|
||||
common/__init__.py
|
||||
common/version.py
|
||||
common/protocol.py
|
||||
config/jail.conf
|
||||
config/filter.d/postfix.conf
|
||||
config/filter.d/vsftpd.conf
|
||||
@@ -65,9 +70,13 @@ config/filter.d/courierlogin.conf
|
||||
config/filter.d/sshd.conf
|
||||
config/filter.d/proftpd.conf
|
||||
config/filter.d/sasl.conf
|
||||
config/filter.d/wuftpd.conf
|
||||
config/action.d/iptables.conf
|
||||
config/action.d/iptables-multiport.conf
|
||||
config/action.d/iptables-new.conf
|
||||
config/action.d/ipfw.conf
|
||||
config/action.d/mail-whois.conf
|
||||
config/action.d/mail-whois-lines.conf
|
||||
config/action.d/mail.conf
|
||||
config/action.d/hostsdeny.conf
|
||||
config/action.d/shorewall.conf
|
||||
@@ -81,3 +90,6 @@ man/fail2ban-regex.h2m
|
||||
man/generate-man
|
||||
files/gentoo-initd
|
||||
files/redhat-initd
|
||||
files/cacti/fail2ban_stats.sh
|
||||
files/cacti/cacti_host_template_fail2ban.xml
|
||||
files/cacti/README
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|_| \__,_|_|_/___|_.__/\__,_|_||_|
|
||||
|
||||
=============================================================
|
||||
Fail2Ban (version 0.7.4) 2006/11/01
|
||||
Fail2Ban (version 0.7.7) 2007/02/08
|
||||
=============================================================
|
||||
|
||||
Fail2Ban scans log files like /var/log/pwdfail and bans IP
|
||||
@@ -13,8 +13,9 @@ rules to reject the IP address. These rules can be defined by
|
||||
the user. Fail2Ban can read multiple log files such as sshd
|
||||
or Apache web server ones.
|
||||
|
||||
Documentation, FAQ, HOWTOs are available on the project
|
||||
website: http://fail2ban.sourceforge.net
|
||||
This README is a quick introduction to Fail2ban. More
|
||||
documentation, FAQ, HOWTOs are available on the project
|
||||
website: http://www.fail2ban.org
|
||||
|
||||
Installation:
|
||||
-------------
|
||||
@@ -27,67 +28,40 @@ Optional:
|
||||
|
||||
To install, just do:
|
||||
|
||||
> tar xvfj fail2ban-0.7.4.tar.bz2
|
||||
> cd fail2ban-0.7.4
|
||||
> tar xvfj fail2ban-0.7.7.tar.bz2
|
||||
> cd fail2ban-0.7.7
|
||||
> python setup.py install
|
||||
|
||||
This will install Fail2Ban into /usr/lib/fail2ban. The
|
||||
This will install Fail2Ban into /usr/share/fail2ban. The
|
||||
executable scripts are placed into /usr/bin.
|
||||
|
||||
Gentoo: ebuilds are available on the website.
|
||||
Debian: Fail2Ban is in Debian unstable.
|
||||
RedHat: packages are available on the website.
|
||||
|
||||
Fail2Ban should now be correctly installed. Just type:
|
||||
Fail2Ban should be correctly installed now. Just type:
|
||||
|
||||
> fail2ban-client -h
|
||||
|
||||
to see if everything is alright.
|
||||
to see if everything is alright. You should always use
|
||||
fail2ban-client and never call fail2ban-server directly.
|
||||
|
||||
Configuration:
|
||||
--------------
|
||||
|
||||
You can configure fail2ban using the files in /etc/fail2ban
|
||||
or using command line. Here are the available command line
|
||||
options (not complete yet):
|
||||
|
||||
Options:
|
||||
-c <DIR> configuration directory
|
||||
-s <FILE> socket path
|
||||
-d dump configuration. For debugging
|
||||
-i interactive mode
|
||||
-v increase verbosity
|
||||
-q decrease verbosity
|
||||
-x force execution of the server
|
||||
-h, --help display this help message
|
||||
-V, --version print the version
|
||||
|
||||
Command:
|
||||
start start the server and the jails
|
||||
reload reload the configuration
|
||||
stop stop all jails and terminate the
|
||||
server
|
||||
status get the current status
|
||||
|
||||
set loglevel <LEVEL> set loglevel to <LEVEL>
|
||||
get loglevel get loglevel
|
||||
set logtarget <TARGET> set log target to <TARGET>
|
||||
get logtarget get log target
|
||||
|
||||
add <JAIL> [BACKEND] create <JAIL> using [BACKEND]
|
||||
set <JAIL> <CMD> set the <CMD> value for <JAIL>
|
||||
get <JAIL> <CMD> get the <CMD> value for <JAIL>
|
||||
start <JAIL> start <JAIL>
|
||||
stop <JAIL> stop <JAIL>. The jail is removed
|
||||
status <JAIL> get the current status of <JAIL>
|
||||
You can configure Fail2ban using the files in /etc/fail2ban.
|
||||
It is possible to configure the server using commands sent to
|
||||
it by fail2ban-client. The available commands are described
|
||||
in the man page of fail2ban-client. Please refer to it or to
|
||||
the website: http://www.fail2ban.org
|
||||
|
||||
Contact:
|
||||
--------
|
||||
|
||||
You need some new features, you found bugs or you just
|
||||
appreciate this program, you can contact me at :
|
||||
appreciate this program, you can contact me at:
|
||||
|
||||
Website: http://fail2ban.sourceforge.net
|
||||
Website: http://www.fail2ban.org
|
||||
|
||||
Cyril Jaquier: <lostcontrol@users.sourceforge.net>
|
||||
|
||||
@@ -98,7 +72,8 @@ Kévin Drapel, Marvin Rouge, Sireyessire, Robert Edeker,
|
||||
Tom Pike, Iain Lea, Andrey G. Grozin, Yaroslav Halchenko,
|
||||
Jonathan Kamens, Stephen Gildea, Markus Hoffmann, Mark
|
||||
Edgington, Patrick Börjesson, kojiro, zugeschmiert, Tyler,
|
||||
Nick Munger, Christoph Haas
|
||||
Nick Munger, Christoph Haas, Justin Shore, Joël Bertrand,
|
||||
René Berber, mEDI, Axel Thimm, Eric Gerbier
|
||||
|
||||
License:
|
||||
--------
|
||||
|
||||
@@ -13,7 +13,29 @@ Legend:
|
||||
# partially done
|
||||
* done
|
||||
|
||||
- Add gettext support (I8N)
|
||||
- Add timeout to external commands (signal alarm, watchdog
|
||||
thread, etc)
|
||||
|
||||
- New backend: pynotify
|
||||
|
||||
- Uniformize filters and actions name. Use the software name
|
||||
(openssh, postfix, proftp)
|
||||
|
||||
- Added <USER> tag for failregex. Add features using this
|
||||
information
|
||||
|
||||
- Look at the memory consumption. Decrease memory usage
|
||||
|
||||
- More detailed statistics
|
||||
|
||||
- Auto-enable function (search for log files), check
|
||||
modification date to see if service is still in use
|
||||
|
||||
- Improve parsing of the action parameters in jailreader.py
|
||||
|
||||
- Better handling of the protocol in transmitter.py
|
||||
|
||||
- Add gettext support (I18N)
|
||||
|
||||
- Fix the cPickle issue with Python 2.5
|
||||
|
||||
@@ -26,14 +48,8 @@ Legend:
|
||||
|
||||
# see Feature Request Tracking System at SourceForge.net
|
||||
|
||||
- improve installation process (better prefix support)
|
||||
|
||||
# improve documentation and website for user
|
||||
|
||||
# better return values in function
|
||||
|
||||
? restart automatically the daemon if an exception occurs.
|
||||
|
||||
- do not close socket after a send
|
||||
|
||||
# refactoring in server.py, actions.py, filter.py
|
||||
|
||||
+20
-8
@@ -16,11 +16,11 @@
|
||||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 288 $
|
||||
# $Revision$
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 288 $"
|
||||
__date__ = "$Date: 2006-08-22 23:59:51 +0200 (Tue, 22 Aug 2006) $"
|
||||
__version__ = "$Revision$"
|
||||
__date__ = "$Date$"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
@@ -70,11 +70,12 @@ class Beautifier:
|
||||
if len(inC) > 1:
|
||||
msg = "Status for the jail: " + inC[1] + "\n"
|
||||
msg = msg + "|- " + response[0][0] + "\n"
|
||||
msg = msg + "| |- " + response[0][1][0][0] + ":\t\t" + `response[0][1][0][1]` + "\n"
|
||||
msg = msg + "| `- " + response[0][1][1][0] + ":\t\t" + `response[0][1][1][1]` + "\n"
|
||||
msg = msg + "| |- " + response[0][1][0][0] + ":\t" + `response[0][1][0][1]` + "\n"
|
||||
msg = msg + "| `- " + response[0][1][1][0] + ":\t" + `response[0][1][1][1]` + "\n"
|
||||
msg = msg + "`- " + response[1][0] + "\n"
|
||||
msg = msg + " |- " + response[1][1][0][0] + ":\t\t" + `response[1][1][0][1]` + "\n"
|
||||
msg = msg + " `- " + response[1][1][1][0] + ":\t\t" + `response[1][1][1][1]`
|
||||
msg = msg + " |- " + response[1][1][0][0] + ":\t" + `response[1][1][0][1]` + "\n"
|
||||
msg = msg + " | `- " + response[1][1][2][0] + ":\t" + `response[1][1][2][1]` + "\n"
|
||||
msg = msg + " `- " + response[1][1][1][0] + ":\t" + `response[1][1][1][1]`
|
||||
else:
|
||||
msg = "Status\n"
|
||||
msg = msg + "|- " + response[0][0] + ":\t" + `response[0][1]` + "\n"
|
||||
@@ -109,7 +110,18 @@ class Beautifier:
|
||||
msg = "These IP addresses/networks are ignored:\n"
|
||||
for ip in response[:-1]:
|
||||
msg = msg + "|- " + ip + "\n"
|
||||
msg = msg + "`- " + response[len(response)-1]
|
||||
msg = msg + "`- " + response[len(response)-1]
|
||||
elif inC[2] in ("failregex", "addfailregex", "delfailregex",
|
||||
"ignoreregex", "addignoreregex", "delignoreregex"):
|
||||
if len(response) == 0:
|
||||
msg = "No regular expression is defined"
|
||||
else:
|
||||
msg = "The following regular expression are defined:\n"
|
||||
c = 0
|
||||
for ip in response[:-1]:
|
||||
msg = msg + "|- [" + str(c) + "]: " + ip + "\n"
|
||||
c += 1
|
||||
msg = msg + "`- [" + str(c) + "]: " + response[len(response)-1]
|
||||
except Exception:
|
||||
logSys.warn("Beautifier error. Please report the error")
|
||||
logSys.error("Beautify " + `response` + " with " + `self.__inputCmd` +
|
||||
|
||||
@@ -69,6 +69,7 @@ class ConfigReader(SafeConfigParser):
|
||||
# 0 -> the type of the option
|
||||
# 1 -> the name of the option
|
||||
# 2 -> the default value for the option
|
||||
|
||||
def getOptions(self, sec, options, pOptions = None):
|
||||
values = dict()
|
||||
for option in options:
|
||||
@@ -88,7 +89,8 @@ class ConfigReader(SafeConfigParser):
|
||||
values[option[1]] = option[2]
|
||||
except NoOptionError:
|
||||
if not option[2] == None:
|
||||
logSys.warn("No '" + option[1] + "' defined in '" + sec + "'")
|
||||
logSys.warn("'%s' not defined in '%s'. Using default value"
|
||||
% (option[1], sec))
|
||||
values[option[1]] = option[2]
|
||||
except ValueError:
|
||||
logSys.warn("Wrong value for '" + option[1] + "' in '" + sec +
|
||||
|
||||
@@ -60,7 +60,7 @@ class Configurator:
|
||||
|
||||
def getAllOptions(self):
|
||||
self.__fail2ban.getOptions()
|
||||
self.__jails.getOptions()
|
||||
return self.__jails.getOptions()
|
||||
|
||||
def convertToProtocol(self):
|
||||
self.__streams["general"] = self.__fail2ban.convert()
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@ class CSocket:
|
||||
|
||||
def send(self, msg):
|
||||
# Convert every list member to string
|
||||
obj = dumps(map(str, msg), HIGHEST_PROTOCOL)
|
||||
obj = dumps([str(m) for m in msg], HIGHEST_PROTOCOL)
|
||||
self.__csock.send(obj + CSocket.END_STRING)
|
||||
ret = self.receive(self.__csock)
|
||||
self.__csock.close()
|
||||
|
||||
+10
-1
@@ -55,6 +55,7 @@ class FilterReader(ConfigReader):
|
||||
def getOptions(self, pOpts):
|
||||
opts = [["string", "timeregex", None],
|
||||
["string", "timepattern", None],
|
||||
["string", "ignoreregex", ""],
|
||||
["string", "failregex", ""]]
|
||||
self.__opts = ConfigReader.getOptions(self, "Definition", opts, pOpts)
|
||||
|
||||
@@ -66,6 +67,14 @@ class FilterReader(ConfigReader):
|
||||
elif opt == "timepattern":
|
||||
stream.append(["set", self.__name, "timepattern", self.__opts[opt]])
|
||||
elif opt == "failregex":
|
||||
stream.append(["set", self.__name, "failregex", self.__opts[opt]])
|
||||
for regex in self.__opts[opt].split('\n'):
|
||||
# Do not send a command if the rule is empty.
|
||||
if regex != '':
|
||||
stream.append(["set", self.__name, "addfailregex", regex])
|
||||
elif opt == "ignoreregex":
|
||||
for regex in self.__opts[opt].split('\n'):
|
||||
# Do not send a command if the rule is empty.
|
||||
if regex != '':
|
||||
stream.append(["set", self.__name, "addignoreregex", regex])
|
||||
return stream
|
||||
|
||||
+37
-5
@@ -60,8 +60,10 @@ class JailReader(ConfigReader):
|
||||
["string", "logpath", "/var/log/messages"],
|
||||
["string", "backend", "auto"],
|
||||
["int", "maxretry", 3],
|
||||
["int", "maxtime", 600],
|
||||
["int", "findtime", 600],
|
||||
["int", "bantime", 600],
|
||||
["string", "failregex", None],
|
||||
["string", "ignoreregex", None],
|
||||
["string", "ignoreip", None],
|
||||
["string", "filter", ""],
|
||||
["string", "action", ""]]
|
||||
@@ -110,11 +112,17 @@ class JailReader(ConfigReader):
|
||||
stream.append(["set", self.__name, "maxretry", self.__opts[opt]])
|
||||
elif opt == "ignoreip":
|
||||
for ip in self.__opts[opt].split():
|
||||
stream.append(["set", self.__name, "addignoreip", ip])
|
||||
elif opt == "maxtime":
|
||||
stream.append(["set", self.__name, "maxtime", self.__opts[opt]])
|
||||
# Do not send a command if the rule is empty.
|
||||
if ip != '':
|
||||
stream.append(["set", self.__name, "addignoreip", ip])
|
||||
elif opt == "findtime":
|
||||
stream.append(["set", self.__name, "findtime", self.__opts[opt]])
|
||||
elif opt == "bantime":
|
||||
stream.append(["set", self.__name, "bantime", self.__opts[opt]])
|
||||
elif opt == "failregex":
|
||||
stream.append(["set", self.__name, "failregex", self.__opts[opt]])
|
||||
elif opt == "ignoreregex":
|
||||
stream.append(["set", self.__name, "ignoreregex", self.__opts[opt]])
|
||||
stream.extend(self.__filter.convert())
|
||||
for action in self.__actions:
|
||||
stream.extend(action.convert())
|
||||
@@ -126,7 +134,31 @@ class JailReader(ConfigReader):
|
||||
m = JailReader.actionCRE.match(action)
|
||||
d = dict()
|
||||
if not m.group(2) == None:
|
||||
for param in m.group(2).split(','):
|
||||
# Huge bad hack :( This method really sucks. TODO Reimplement it.
|
||||
actions = ""
|
||||
escapeChar = None
|
||||
allowComma = False
|
||||
for c in m.group(2):
|
||||
if c in ('"', "'") and not allowComma:
|
||||
# Start
|
||||
escapeChar = c
|
||||
allowComma = True
|
||||
elif c == escapeChar:
|
||||
# End
|
||||
escapeChar = None
|
||||
allowComma = False
|
||||
else:
|
||||
if c == ',' and allowComma:
|
||||
actions += "<COMMA>"
|
||||
else:
|
||||
actions += c
|
||||
|
||||
# Split using ,
|
||||
actionsSplit = actions.split(',')
|
||||
# Replace the tag <COMMA> with ,
|
||||
actionsSplit = [n.replace("<COMMA>", ',') for n in actionsSplit]
|
||||
|
||||
for param in actionsSplit:
|
||||
p = param.split('=')
|
||||
try:
|
||||
d[p[0].strip()] = p[1].strip()
|
||||
|
||||
@@ -54,6 +54,8 @@ class JailsReader(ConfigReader):
|
||||
self.__jails.append(jail)
|
||||
else:
|
||||
logSys.error("Errors in jail '" + sec + "'. Skipping...")
|
||||
return False
|
||||
return True
|
||||
|
||||
def convert(self):
|
||||
stream = list()
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# This file is part of Fail2Ban.
|
||||
#
|
||||
# Fail2Ban is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Fail2Ban is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Fail2Ban; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision$
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision$"
|
||||
__date__ = "$Date$"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
@@ -0,0 +1,136 @@
|
||||
# This file is part of Fail2Ban.
|
||||
#
|
||||
# Fail2Ban is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Fail2Ban is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Fail2Ban; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision$
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision$"
|
||||
__date__ = "$Date$"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
import textwrap
|
||||
|
||||
##
|
||||
# Describes the protocol used to communicate with the server.
|
||||
|
||||
protocol = [
|
||||
['', "BASIC", ""],
|
||||
["start", "starts the server and the jails"],
|
||||
["reload", "reloads the configuration"],
|
||||
["stop", "stops all jails and terminate the server"],
|
||||
["status", "gets the current status of the server"],
|
||||
["ping", "tests if the server is alive"],
|
||||
['', "LOGGING", ""],
|
||||
["set loglevel <LEVEL>", "sets logging level to <LEVEL>. 0 is minimal, 4 is debug"],
|
||||
["get loglevel", "gets the logging level"],
|
||||
["set logtarget <TARGET>", "sets logging target to <TARGET>. Can be STDOUT, STDERR, SYSLOG or a file"],
|
||||
["get logtarget", "gets logging target"],
|
||||
['', "JAIL CONTROL", ""],
|
||||
["add <JAIL> <BACKEND>", "creates <JAIL> using <BACKEND>"],
|
||||
["start <JAIL>", "starts the jail <JAIL>"],
|
||||
["stop <JAIL>", "stops the jail <JAIL>. The jail is removed"],
|
||||
["status <JAIL>", "gets the current status of <JAIL>"],
|
||||
['', "JAIL CONFIGURATION", ""],
|
||||
["set <JAIL> idle on|off", "sets the idle state of <JAIL>"],
|
||||
["set <JAIL> addignoreip <IP>", "adds <IP> to the ignore list of <JAIL>"],
|
||||
["set <JAIL> delignoreip <IP>", "removes <IP> from the ignore list of <JAIL>"],
|
||||
["set <JAIL> addlogpath <FILE>", "adds <FILE> to the monitoring list of <JAIL>"],
|
||||
["set <JAIL> dellogpath <FILE>", "removes <FILE> to the monitoring list of <JAIL>"],
|
||||
["set <JAIL> timeregex <REGEX>", "sets the regular expression <REGEX> to match the date format for <JAIL>. This will disable the autodetection feature."],
|
||||
["set <JAIL> timepattern <PATTERN>", "sets the pattern <PATTERN> to match the date format for <JAIL>. This will disable the autodetection feature."],
|
||||
["set <JAIL> addfailregex <REGEX>", "adds the regular expression <REGEX> which must match failures for <JAIL>"],
|
||||
["set <JAIL> delfailregex <INDEX>", "removes the regular expression at <INDEX> for failregex"],
|
||||
["set <JAIL> addignoreregex <REGEX>", "adds the regular expression <REGEX> which should match pattern to exclude for <JAIL>"],
|
||||
["set <JAIL> delignoreregex <INDEX>", "removes the regular expression at <INDEX> for ignoreregex"],
|
||||
["set <JAIL> findtime <TIME>", "sets the number of seconds <TIME> for which the filter will look back for <JAIL>"],
|
||||
["set <JAIL> bantime <TIME>", "sets the number of seconds <TIME> a host will be banned for <JAIL>"],
|
||||
["set <JAIL> maxretry <RETRY>", "sets the number of failures <RETRY> before banning the host for <JAIL>"],
|
||||
["set <JAIL> addaction <ACT>", "adds a new action named <NAME> for <JAIL>"],
|
||||
["set <JAIL> delaction <ACT>", "removes the action <NAME> from <JAIL>"],
|
||||
["set <JAIL> setcinfo <ACT> <KEY> <VALUE>", "sets <VALUE> for <KEY> of the action <NAME> for <JAIL>"],
|
||||
["set <JAIL> delcinfo <ACT> <KEY>", "removes <KEY> for the action <NAME> for <JAIL>"],
|
||||
["set <JAIL> actionstart <ACT> <CMD>", "sets the start command <CMD> of the action <ACT> for <JAIL>"],
|
||||
["set <JAIL> actionstop <ACT> <CMD>", "sets the stop command <CMD> of the action <ACT> for <JAIL>"],
|
||||
["set <JAIL> actioncheck <ACT> <CMD>", "sets the check command <CMD> of the action <ACT> for <JAIL>"],
|
||||
["set <JAIL> actionban <ACT> <CMD>", "sets the ban command <CMD> of the action <ACT> for <JAIL>"],
|
||||
["set <JAIL> actionunban <ACT> <CMD>", "sets the unban command <CMD> of the action <ACT> for <JAIL>"],
|
||||
['', "JAIL INFORMATION", ""],
|
||||
["get <JAIL> logpath", "gets the list of the monitored files for <JAIL>"],
|
||||
["get <JAIL> ignoreip", "gets the list of ignored IP addresses for <JAIL>"],
|
||||
["get <JAIL> timeregex", "gets the regular expression used for the time detection for <JAIL>"],
|
||||
["get <JAIL> timepattern", "gets the pattern used for the time detection for <JAIL>"],
|
||||
["get <JAIL> failregex", "gets the list of regular expressions which matches the failures for <JAIL>"],
|
||||
["get <JAIL> ignoreregex", "gets the list of regular expressions which matches patterns to ignore for <JAIL>"],
|
||||
["get <JAIL> findtime", "gets the time for which the filter will look back for failures for <JAIL>"],
|
||||
["get <JAIL> bantime", "gets the time a host is banned for <JAIL>"],
|
||||
["get <JAIL> maxretry", "gets the number of failures allowed for <JAIL>"],
|
||||
["get <JAIL> addaction", "gets the last action which has been added for <JAIL>"],
|
||||
["get <JAIL> actionstart <ACT>", "gets the start command for the action <ACT> for <JAIL>"],
|
||||
["get <JAIL> actionstop <ACT>", "gets the stop command for the action <ACT> for <JAIL>"],
|
||||
["get <JAIL> actioncheck <ACT>", "gets the check command for the action <ACT> for <JAIL>"],
|
||||
["get <JAIL> actionban <ACT>", "gets the ban command for the action <ACT> for <JAIL>"],
|
||||
["get <JAIL> actionunban <ACT>", "gets the unban command for the action <ACT> for <JAIL>"],
|
||||
]
|
||||
|
||||
##
|
||||
# Prints the protocol in a "man" format. This is used for the
|
||||
# "-h" output of fail2ban-client.
|
||||
|
||||
def printFormatted():
|
||||
INDENT=4
|
||||
MARGIN=41
|
||||
WIDTH=34
|
||||
firstHeading = False
|
||||
for m in protocol:
|
||||
if m[0] == '' and firstHeading:
|
||||
print
|
||||
firstHeading = True
|
||||
first = True
|
||||
for n in textwrap.wrap(m[1], WIDTH):
|
||||
if first:
|
||||
line = ' ' * INDENT + m[0] + ' ' * (MARGIN - len(m[0])) + n
|
||||
first = False
|
||||
else:
|
||||
line = ' ' * (INDENT + MARGIN) + n
|
||||
print line
|
||||
|
||||
##
|
||||
# Prints the protocol in a "mediawiki" format.
|
||||
|
||||
def printWiki():
|
||||
firstHeading = False
|
||||
for m in protocol:
|
||||
if m[0] == '':
|
||||
if firstHeading:
|
||||
print "|}"
|
||||
__printWikiHeader(m[1], m[2])
|
||||
firstHeading = True
|
||||
else:
|
||||
print "|-"
|
||||
print "| <span style=\"white-space:nowrap;\"><tt>" + m[0] + "</tt></span> || || " + m[1]
|
||||
print "|}"
|
||||
|
||||
def __printWikiHeader(section, desc):
|
||||
print
|
||||
print "=== " + section + " ==="
|
||||
print
|
||||
print desc
|
||||
print
|
||||
print "{|"
|
||||
print "| '''Command''' || || '''Description'''"
|
||||
@@ -24,4 +24,4 @@ __date__ = "$Date$"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
version = "0.7.4"
|
||||
version = "0.7.7"
|
||||
+10
-11
@@ -7,42 +7,41 @@
|
||||
|
||||
[Definition]
|
||||
|
||||
# Option: fwstart
|
||||
# Option: actionstart
|
||||
# Notes.: command executed once at the start of Fail2Ban.
|
||||
# Values: CMD
|
||||
#
|
||||
actionstart = touch /tmp/fail2ban.dummy
|
||||
echo "<init>" >> /tmp/fail2ban.dummy
|
||||
|
||||
# Option: fwend
|
||||
# Option: actionend
|
||||
# Notes.: command executed once at the end of Fail2Ban
|
||||
# Values: CMD
|
||||
#
|
||||
actionstop = rm /tmp/fail2ban.dummy
|
||||
actionstop = rm -f /tmp/fail2ban.dummy
|
||||
|
||||
# Option: fwcheck
|
||||
# Notes.: command executed once before each fwban command
|
||||
# Option: actioncheck
|
||||
# Notes.: command executed once before each actionban command
|
||||
# Values: CMD
|
||||
#
|
||||
actioncheck =
|
||||
|
||||
# Option: fwban
|
||||
# Option: actionban
|
||||
# Notes.: command executed when banning an IP. Take care that the
|
||||
# command is executed with Fail2Ban user rights.
|
||||
# Tags: <ip> IP address
|
||||
# <failures> number of failures
|
||||
# <failtime> unix timestamp of the last failure
|
||||
# <bantime> unix timestamp of the ban time
|
||||
# <time> unix timestamp of the ban time
|
||||
# Values: CMD
|
||||
#
|
||||
actionban = echo "+<ip>" >> /tmp/fail2ban.dummy
|
||||
|
||||
# Option: fwunban
|
||||
# Option: actionunban
|
||||
# Notes.: command executed when unbanning an IP. Take care that the
|
||||
# command is executed with Fail2Ban user rights.
|
||||
# Tags: <ip> IP address
|
||||
# <bantime> unix timestamp of the ban time
|
||||
# <unbantime> unix timestamp of the unban time
|
||||
# <failures> number of failures
|
||||
# <time> unix timestamp of the ban time
|
||||
# Values: CMD
|
||||
#
|
||||
actionunban = echo "-<ip>" >> /tmp/fail2ban.dummy
|
||||
|
||||
@@ -7,47 +7,44 @@
|
||||
|
||||
[Definition]
|
||||
|
||||
# Option: fwstart
|
||||
# Option: actionstart
|
||||
# Notes.: command executed once at the start of Fail2Ban.
|
||||
# Values: CMD
|
||||
#
|
||||
actionstart = touch <tmpfile>
|
||||
|
||||
# Option: fwend
|
||||
# Option: actionend
|
||||
# Notes.: command executed once at the end of Fail2Ban
|
||||
# Values: CMD
|
||||
#
|
||||
actionstop = rm -f <tmpfile>
|
||||
|
||||
# Option: fwcheck
|
||||
# Notes.: command executed once before each fwban command
|
||||
# Option: actioncheck
|
||||
# Notes.: command executed once before each actionban command
|
||||
# Values: CMD
|
||||
#
|
||||
actioncheck =
|
||||
|
||||
# Option: fwban
|
||||
# Option: actionban
|
||||
# Notes.: command executed when banning an IP. Take care that the
|
||||
# command is executed with Fail2Ban user rights.
|
||||
# Tags: <ip> IP address
|
||||
# <failures> number of failures
|
||||
# <failtime> unix timestamp of the last failure
|
||||
# <bantime> unix timestamp of the ban time
|
||||
# <time> unix timestamp of the ban time
|
||||
# Values: CMD
|
||||
#
|
||||
actionban = IP=<ip> &&
|
||||
echo "ALL: $IP" >> <file>
|
||||
|
||||
# Option: fwunban
|
||||
# Option: actionunban
|
||||
# Notes.: command executed when unbanning an IP. Take care that the
|
||||
# command is executed with Fail2Ban user rights.
|
||||
# Tags: <ip> IP address
|
||||
# <bantime> unix timestamp of the ban time
|
||||
# <unbantime> unix timestamp of the unban time
|
||||
# <failures> number of failures
|
||||
# <time> unix timestamp of the ban time
|
||||
# Values: CMD
|
||||
#
|
||||
actionunban = IP=<ip> &&
|
||||
grep -v "ALL: $IP" <file> > <tmpfile> &&
|
||||
mv <tmpfile> <file>
|
||||
actionunban = IP=<ip> && sed -i.old /ALL:\ $IP/d <file>
|
||||
|
||||
[Init]
|
||||
|
||||
@@ -56,10 +53,3 @@ actionunban = IP=<ip> &&
|
||||
# Values: STR Default: /etc/hosts.deny
|
||||
#
|
||||
file = /etc/hosts.deny
|
||||
|
||||
# Option: file
|
||||
# Notes.: hosts.deny temporary file path.
|
||||
# Values: STR Default: /etc/hostsdeny.failban
|
||||
#
|
||||
tmpfile = /tmp/hosts.deny.tmp
|
||||
|
||||
|
||||
+12
-13
@@ -3,53 +3,52 @@
|
||||
# Author: Nick Munger
|
||||
# Modified by: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 254 $
|
||||
# $Revision$
|
||||
#
|
||||
|
||||
[Definition]
|
||||
|
||||
# Option: fwstart
|
||||
# Option: actionstart
|
||||
# Notes.: command executed once at the start of Fail2Ban.
|
||||
# Values: CMD
|
||||
#
|
||||
actionstart =
|
||||
|
||||
|
||||
# Option: fwend
|
||||
# Option: actionend
|
||||
# Notes.: command executed once at the end of Fail2Ban
|
||||
# Values: CMD
|
||||
#
|
||||
actionstop =
|
||||
|
||||
|
||||
# Option: fwcheck
|
||||
# Notes.: command executed once before each fwban command
|
||||
# Option: actioncheck
|
||||
# Notes.: command executed once before each actionban command
|
||||
# Values: CMD
|
||||
#
|
||||
actioncheck =
|
||||
|
||||
|
||||
# Option: fwban
|
||||
# Option: actionban
|
||||
# Notes.: command executed when banning an IP. Take care that the
|
||||
# command is executed with Fail2Ban user rights.
|
||||
# Tags: <ip> IP address
|
||||
# <failures> number of failures
|
||||
# <failtime> unix timestamp of the last failure
|
||||
# <bantime> unix timestamp of the ban time
|
||||
# <time> unix timestamp of the ban time
|
||||
# Values: CMD
|
||||
#
|
||||
actionban = ipfw add deny tcp from <ip> to <localhost> <port>
|
||||
actionban = ipaction add deny tcp from <ip> to <localhost> <port>
|
||||
|
||||
|
||||
# Option: fwunban
|
||||
# Option: actionunban
|
||||
# Notes.: command executed when unbanning an IP. Take care that the
|
||||
# command is executed with Fail2Ban user rights.
|
||||
# Tags: <ip> IP address
|
||||
# <bantime> unix timestamp of the ban time
|
||||
# <unbantime> unix timestamp of the unban time
|
||||
# <failures> number of failures
|
||||
# <time> unix timestamp of the ban time
|
||||
# Values: CMD
|
||||
#
|
||||
actionunban = ipfw delete `ipfw list | grep -i <ip> | awk '{print $1;}'`
|
||||
actionunban = ipaction delete `ipfw list | grep -i <ip> | awk '{print $1;}'`
|
||||
|
||||
[Init]
|
||||
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
# Fail2Ban configuration file
|
||||
#
|
||||
# Author: Cyril Jaquier
|
||||
# Modified by Yaroslav Halchenko for multiport banning
|
||||
# $Revision$
|
||||
#
|
||||
|
||||
[Definition]
|
||||
|
||||
# Option: actionstart
|
||||
# Notes.: command executed once at the start of Fail2Ban.
|
||||
# Values: CMD
|
||||
#
|
||||
actionstart = iptables -N fail2ban-<name>
|
||||
iptables -A fail2ban-<name> -j RETURN
|
||||
iptables -I INPUT -p <protocol> -m multiport --dports <port> -j fail2ban-<name>
|
||||
|
||||
# Option: actionend
|
||||
# Notes.: command executed once at the end of Fail2Ban
|
||||
# Values: CMD
|
||||
#
|
||||
actionstop = iptables -D INPUT -p <protocol> -m multiport --dports <port> -j fail2ban-<name>
|
||||
iptables -F fail2ban-<name>
|
||||
iptables -X fail2ban-<name>
|
||||
|
||||
# Option: actioncheck
|
||||
# Notes.: command executed once before each actionban command
|
||||
# Values: CMD
|
||||
#
|
||||
actioncheck = iptables -n -L INPUT | grep -q fail2ban-<name>
|
||||
|
||||
# Option: actionban
|
||||
# Notes.: command executed when banning an IP. Take care that the
|
||||
# command is executed with Fail2Ban user rights.
|
||||
# Tags: <ip> IP address
|
||||
# <failures> number of failures
|
||||
# <time> unix timestamp of the ban time
|
||||
# Values: CMD
|
||||
#
|
||||
actionban = iptables -I fail2ban-<name> 1 -s <ip> -j DROP
|
||||
|
||||
# Option: actionunban
|
||||
# Notes.: command executed when unbanning an IP. Take care that the
|
||||
# command is executed with Fail2Ban user rights.
|
||||
# Tags: <ip> IP address
|
||||
# <failures> number of failures
|
||||
# <time> unix timestamp of the ban time
|
||||
# Values: CMD
|
||||
#
|
||||
actionunban = iptables -D fail2ban-<name> -s <ip> -j DROP
|
||||
|
||||
[Init]
|
||||
|
||||
# Defaut name of the chain
|
||||
#
|
||||
name = default
|
||||
|
||||
# Option: port
|
||||
# Notes.: specifies port to monitor
|
||||
# Values: [ NUM | STRING ] Default:
|
||||
#
|
||||
port = ssh
|
||||
|
||||
# Option: protocol
|
||||
# Notes.: internally used by config reader for interpolations.
|
||||
# Values: [ tcp | udp | icmp | all ] Default: tcp
|
||||
#
|
||||
protocol = tcp
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
# Fail2Ban configuration file
|
||||
#
|
||||
# Author: Cyril Jaquier
|
||||
# Copied from iptables.conf and modified by Yaroslav Halchenko
|
||||
# to fullfill the needs of bugreporter dbts#350746.
|
||||
#
|
||||
# $Revision$
|
||||
#
|
||||
|
||||
[Definition]
|
||||
|
||||
# Option: actionstart
|
||||
# Notes.: command executed once at the start of Fail2Ban.
|
||||
# Values: CMD
|
||||
#
|
||||
actionstart = iptables -N fail2ban-<name>
|
||||
iptables -A fail2ban-<name> -j RETURN
|
||||
iptables -I INPUT -m state --state NEW -p <protocol> --dport <port> -j fail2ban-<name>
|
||||
|
||||
# Option: actionend
|
||||
# Notes.: command executed once at the end of Fail2Ban
|
||||
# Values: CMD
|
||||
#
|
||||
actionstop = iptables -D INPUT -m state --state NEW -p <protocol> --dport <port> -j fail2ban-<name>
|
||||
iptables -F fail2ban-<name>
|
||||
iptables -X fail2ban-<name>
|
||||
|
||||
# Option: actioncheck
|
||||
# Notes.: command executed once before each actionban command
|
||||
# Values: CMD
|
||||
#
|
||||
actioncheck = iptables -n -L INPUT | grep -q fail2ban-<name>
|
||||
|
||||
# Option: actionban
|
||||
# Notes.: command executed when banning an IP. Take care that the
|
||||
# command is executed with Fail2Ban user rights.
|
||||
# Tags: <ip> IP address
|
||||
# <failures> number of failures
|
||||
# <time> unix timestamp of the ban time
|
||||
# Values: CMD
|
||||
#
|
||||
actionban = iptables -I fail2ban-<name> 1 -s <ip> -j DROP
|
||||
|
||||
# Option: actionunban
|
||||
# Notes.: command executed when unbanning an IP. Take care that the
|
||||
# command is executed with Fail2Ban user rights.
|
||||
# Tags: <ip> IP address
|
||||
# <failures> number of failures
|
||||
# <time> unix timestamp of the ban time
|
||||
# Values: CMD
|
||||
#
|
||||
actionunban = iptables -D fail2ban-<name> -s <ip> -j DROP
|
||||
|
||||
[Init]
|
||||
|
||||
# Defaut name of the chain
|
||||
#
|
||||
name = default
|
||||
|
||||
# Option: port
|
||||
# Notes.: specifies port to monitor
|
||||
# Values: [ NUM | STRING ] Default:
|
||||
#
|
||||
port = ssh
|
||||
|
||||
# Option: protocol
|
||||
# Notes.: internally used by config reader for interpolations.
|
||||
# Values: [ tcp | udp | icmp | all ] Default: tcp
|
||||
#
|
||||
protocol = tcp
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
[Definition]
|
||||
|
||||
# Option: fwstart
|
||||
# Option: actionstart
|
||||
# Notes.: command executed once at the start of Fail2Ban.
|
||||
# Values: CMD
|
||||
#
|
||||
@@ -15,7 +15,7 @@ actionstart = iptables -N fail2ban-<name>
|
||||
iptables -A fail2ban-<name> -j RETURN
|
||||
iptables -I INPUT -p <protocol> --dport <port> -j fail2ban-<name>
|
||||
|
||||
# Option: fwend
|
||||
# Option: actionend
|
||||
# Notes.: command executed once at the end of Fail2Ban
|
||||
# Values: CMD
|
||||
#
|
||||
@@ -23,29 +23,28 @@ actionstop = iptables -D INPUT -p <protocol> --dport <port> -j fail2ban-<name>
|
||||
iptables -F fail2ban-<name>
|
||||
iptables -X fail2ban-<name>
|
||||
|
||||
# Option: fwcheck
|
||||
# Notes.: command executed once before each fwban command
|
||||
# Option: actioncheck
|
||||
# Notes.: command executed once before each actionban command
|
||||
# Values: CMD
|
||||
#
|
||||
actioncheck = iptables -L INPUT | grep -q fail2ban-<name>
|
||||
actioncheck = iptables -n -L INPUT | grep -q fail2ban-<name>
|
||||
|
||||
# Option: fwban
|
||||
# Option: actionban
|
||||
# Notes.: command executed when banning an IP. Take care that the
|
||||
# command is executed with Fail2Ban user rights.
|
||||
# Tags: <ip> IP address
|
||||
# <failures> number of failures
|
||||
# <failtime> unix timestamp of the last failure
|
||||
# <bantime> unix timestamp of the ban time
|
||||
# <time> unix timestamp of the ban time
|
||||
# Values: CMD
|
||||
#
|
||||
actionban = iptables -I fail2ban-<name> 1 -s <ip> -j DROP
|
||||
|
||||
# Option: fwunban
|
||||
# Option: actionunban
|
||||
# Notes.: command executed when unbanning an IP. Take care that the
|
||||
# command is executed with Fail2Ban user rights.
|
||||
# Tags: <ip> IP address
|
||||
# <bantime> unix timestamp of the ban time
|
||||
# <unbantime> unix timestamp of the unban time
|
||||
# <failures> number of failures
|
||||
# <time> unix timestamp of the ban time
|
||||
# Values: CMD
|
||||
#
|
||||
actionunban = iptables -D fail2ban-<name> -s <ip> -j DROP
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
# Fail2Ban configuration file
|
||||
#
|
||||
# Author: Cyril Jaquier
|
||||
# Modified-By: Yaroslav Halchenko to include grepping on IP over log files
|
||||
# $Revision$
|
||||
#
|
||||
|
||||
[Definition]
|
||||
|
||||
# Option: fwstart
|
||||
# Notes.: command executed once at the start of Fail2Ban.
|
||||
# Values: CMD
|
||||
#
|
||||
actionstart = echo -en "Hi,\n
|
||||
The jail <name> has been started successfuly.\n
|
||||
Regards,\n
|
||||
Fail2Ban"|mail -s "[Fail2Ban] <name>: started" <dest>
|
||||
|
||||
# Option: fwend
|
||||
# Notes.: command executed once at the end of Fail2Ban
|
||||
# Values: CMD
|
||||
#
|
||||
actionstop = echo -en "Hi,\n
|
||||
The jail <name> has been stopped.\n
|
||||
Regards,\n
|
||||
Fail2Ban"|mail -s "[Fail2Ban] <name>: stopped" <dest>
|
||||
|
||||
# Option: fwcheck
|
||||
# Notes.: command executed once before each fwban command
|
||||
# Values: CMD
|
||||
#
|
||||
actioncheck =
|
||||
|
||||
# Option: fwban
|
||||
# Notes.: command executed when banning an IP. Take care that the
|
||||
# command is executed with Fail2Ban user rights.
|
||||
# Tags: <ip> IP address
|
||||
# <failures> number of failures
|
||||
# <failtime> unix timestamp of the last failure
|
||||
# <bantime> unix timestamp of the ban time
|
||||
# Values: CMD
|
||||
#
|
||||
actionban = echo -en "Hi,\n
|
||||
The IP <ip> has just been banned by Fail2Ban after
|
||||
<failures> attempts against <name>.\n\n
|
||||
Here are more information about <ip>:\n
|
||||
`whois <ip>`\n\n
|
||||
Lines containing IP:<ip> in <logpath>\n
|
||||
`grep '\<<ip>\>' <logpath>`\n\n
|
||||
Regards,\n
|
||||
Fail2Ban"|mail -s "[Fail2Ban] <name>: banned <ip>" <dest>
|
||||
|
||||
# Option: fwunban
|
||||
# Notes.: command executed when unbanning an IP. Take care that the
|
||||
# command is executed with Fail2Ban user rights.
|
||||
# Tags: <ip> IP address
|
||||
# <bantime> unix timestamp of the ban time
|
||||
# <unbantime> unix timestamp of the unban time
|
||||
# Values: CMD
|
||||
#
|
||||
actionunban =
|
||||
|
||||
[Init]
|
||||
|
||||
# Defaut name of the chain
|
||||
#
|
||||
name = default
|
||||
|
||||
# Destinataire of the mail
|
||||
#
|
||||
dest = root
|
||||
|
||||
# Path to the log files which contain relevant lines for the abuser IP
|
||||
#
|
||||
logpath = /dev/null
|
||||
@@ -2,12 +2,12 @@
|
||||
#
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 254 $
|
||||
# $Revision$
|
||||
#
|
||||
|
||||
[Definition]
|
||||
|
||||
# Option: fwstart
|
||||
# Option: actionstart
|
||||
# Notes.: command executed once at the start of Fail2Ban.
|
||||
# Values: CMD
|
||||
#
|
||||
@@ -16,7 +16,7 @@ actionstart = echo -en "Hi,\n
|
||||
Regards,\n
|
||||
Fail2Ban"|mail -s "[Fail2Ban] <name>: started" <dest>
|
||||
|
||||
# Option: fwend
|
||||
# Option: actionend
|
||||
# Notes.: command executed once at the end of Fail2Ban
|
||||
# Values: CMD
|
||||
#
|
||||
@@ -25,19 +25,18 @@ actionstop = echo -en "Hi,\n
|
||||
Regards,\n
|
||||
Fail2Ban"|mail -s "[Fail2Ban] <name>: stopped" <dest>
|
||||
|
||||
# Option: fwcheck
|
||||
# Notes.: command executed once before each fwban command
|
||||
# Option: actioncheck
|
||||
# Notes.: command executed once before each actionban command
|
||||
# Values: CMD
|
||||
#
|
||||
actioncheck =
|
||||
|
||||
# Option: fwban
|
||||
# Option: actionban
|
||||
# Notes.: command executed when banning an IP. Take care that the
|
||||
# command is executed with Fail2Ban user rights.
|
||||
# Tags: <ip> IP address
|
||||
# <failures> number of failures
|
||||
# <failtime> unix timestamp of the last failure
|
||||
# <bantime> unix timestamp of the ban time
|
||||
# <time> unix timestamp of the ban time
|
||||
# Values: CMD
|
||||
#
|
||||
actionban = echo -en "Hi,\n
|
||||
@@ -48,12 +47,12 @@ actionban = echo -en "Hi,\n
|
||||
Regards,\n
|
||||
Fail2Ban"|mail -s "[Fail2Ban] <name>: banned <ip>" <dest>
|
||||
|
||||
# Option: fwunban
|
||||
# Option: actionunban
|
||||
# Notes.: command executed when unbanning an IP. Take care that the
|
||||
# command is executed with Fail2Ban user rights.
|
||||
# Tags: <ip> IP address
|
||||
# <bantime> unix timestamp of the ban time
|
||||
# <unbantime> unix timestamp of the unban time
|
||||
# <failures> number of failures
|
||||
# <time> unix timestamp of the ban time
|
||||
# Values: CMD
|
||||
#
|
||||
actionunban =
|
||||
@@ -64,7 +63,7 @@ actionunban =
|
||||
#
|
||||
name = default
|
||||
|
||||
# Destinataire of the mail
|
||||
# Destination/Addressee of the mail
|
||||
#
|
||||
dest = root
|
||||
|
||||
|
||||
+11
-12
@@ -2,12 +2,12 @@
|
||||
#
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 254 $
|
||||
# $Revision$
|
||||
#
|
||||
|
||||
[Definition]
|
||||
|
||||
# Option: fwstart
|
||||
# Option: actionstart
|
||||
# Notes.: command executed once at the start of Fail2Ban.
|
||||
# Values: CMD
|
||||
#
|
||||
@@ -16,7 +16,7 @@ actionstart = echo -en "Hi,\n
|
||||
Regards,\n
|
||||
Fail2Ban"|mail -s "[Fail2Ban] <name>: started" <dest>
|
||||
|
||||
# Option: fwend
|
||||
# Option: actionend
|
||||
# Notes.: command executed once at the end of Fail2Ban
|
||||
# Values: CMD
|
||||
#
|
||||
@@ -25,19 +25,18 @@ actionstop = echo -en "Hi,\n
|
||||
Regards,\n
|
||||
Fail2Ban"|mail -s "[Fail2Ban] <name>: stopped" <dest>
|
||||
|
||||
# Option: fwcheck
|
||||
# Notes.: command executed once before each fwban command
|
||||
# Option: actioncheck
|
||||
# Notes.: command executed once before each actionban command
|
||||
# Values: CMD
|
||||
#
|
||||
actioncheck =
|
||||
|
||||
# Option: fwban
|
||||
# Option: actionban
|
||||
# Notes.: command executed when banning an IP. Take care that the
|
||||
# command is executed with Fail2Ban user rights.
|
||||
# Tags: <ip> IP address
|
||||
# <failures> number of failures
|
||||
# <failtime> unix timestamp of the last failure
|
||||
# <bantime> unix timestamp of the ban time
|
||||
# <time> unix timestamp of the ban time
|
||||
# Values: CMD
|
||||
#
|
||||
actionban = echo -en "Hi,\n
|
||||
@@ -46,12 +45,12 @@ actionban = echo -en "Hi,\n
|
||||
Regards,\n
|
||||
Fail2Ban"|mail -s "[Fail2Ban] <name>: banned <ip>" <dest>
|
||||
|
||||
# Option: fwunban
|
||||
# Option: actionunban
|
||||
# Notes.: command executed when unbanning an IP. Take care that the
|
||||
# command is executed with Fail2Ban user rights.
|
||||
# Tags: <ip> IP address
|
||||
# <bantime> unix timestamp of the ban time
|
||||
# <unbantime> unix timestamp of the unban time
|
||||
# <failures> number of failures
|
||||
# <time> unix timestamp of the ban time
|
||||
# Values: CMD
|
||||
#
|
||||
actionunban =
|
||||
@@ -62,7 +61,7 @@ actionunban =
|
||||
#
|
||||
name = default
|
||||
|
||||
# Destinataire of the mail
|
||||
# Destination/Addressee of the mail
|
||||
#
|
||||
dest = root
|
||||
|
||||
|
||||
@@ -2,46 +2,45 @@
|
||||
#
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 394 $
|
||||
# $Revision$
|
||||
#
|
||||
|
||||
[Definition]
|
||||
|
||||
# Option: fwstart
|
||||
# Option: actionstart
|
||||
# Notes.: command executed once at the start of Fail2Ban.
|
||||
# Values: CMD
|
||||
#
|
||||
actionstart =
|
||||
|
||||
# Option: fwend
|
||||
# Option: actionend
|
||||
# Notes.: command executed once at the end of Fail2Ban
|
||||
# Values: CMD
|
||||
#
|
||||
actionstop =
|
||||
|
||||
# Option: fwcheck
|
||||
# Notes.: command executed once before each fwban command
|
||||
# Option: actioncheck
|
||||
# Notes.: command executed once before each actionban command
|
||||
# Values: CMD
|
||||
#
|
||||
actioncheck =
|
||||
|
||||
# Option: fwban
|
||||
# Option: actionban
|
||||
# Notes.: command executed when banning an IP. Take care that the
|
||||
# command is executed with Fail2Ban user rights.
|
||||
# Tags: <ip> IP address
|
||||
# <failures> number of failures
|
||||
# <failtime> unix timestamp of the last failure
|
||||
# <bantime> unix timestamp of the ban time
|
||||
# <time> unix timestamp of the ban time
|
||||
# Values: CMD
|
||||
#
|
||||
actionban = shorewall reject <ip>
|
||||
|
||||
# Option: fwunban
|
||||
# Option: actionunban
|
||||
# Notes.: command executed when unbanning an IP. Take care that the
|
||||
# command is executed with Fail2Ban user rights.
|
||||
# Tags: <ip> IP address
|
||||
# <bantime> unix timestamp of the ban time
|
||||
# <unbantime> unix timestamp of the unban time
|
||||
# <failures> number of failures
|
||||
# <time> unix timestamp of the ban time
|
||||
# Values: CMD
|
||||
#
|
||||
actionunban = shorewall allow <ip>
|
||||
|
||||
@@ -18,14 +18,16 @@
|
||||
loglevel = 3
|
||||
|
||||
# Option: logtarget
|
||||
# Notes.: Set the log target. This could be a file, SYSLOG, STDERR.
|
||||
# Values: STDERR SYSLOG file Default: /var/log/fail2ban.log
|
||||
# Notes.: Set the log target. This could be a file, SYSLOG, STDERR or STDOUT.
|
||||
# Only one log target can be specified.
|
||||
# Values: STDOUT STDERR SYSLOG file Default: /var/log/fail2ban.log
|
||||
#
|
||||
logtarget = /var/log/fail2ban.log
|
||||
|
||||
# Option: socket
|
||||
# Notes.: Set the socket file. This is used to communication with the
|
||||
# daemon.
|
||||
# Notes.: Set the socket file. This is used to communicate with the daemon. Do
|
||||
# not remove this file when Fail2ban runs. It will not be possible to
|
||||
# communicate with the server afterwards.
|
||||
# Values: FILE Default: /tmp/fail2ban.sock
|
||||
#
|
||||
socket = /tmp/fail2ban.sock
|
||||
|
||||
@@ -8,7 +8,16 @@
|
||||
[Definition]
|
||||
|
||||
# Option: failregex
|
||||
# Notes.: regex to match the password failure messages in the logfile.
|
||||
# Notes.: regex to match the password failure messages in the logfile. The
|
||||
# host must be matched by a group named "host". The tag "<HOST>" can
|
||||
# be used for standard IP/hostname matching and is only an alias for
|
||||
# (?:::f{4,6}:)?(?P<host>\S+)
|
||||
# Values: TEXT
|
||||
#
|
||||
failregex = [[]client (?P<host>\S*)[]] user .*(?:: authentication failure|not found)
|
||||
failregex = [[]client <HOST>[]] user .*(?:: authentication failure|not found)
|
||||
|
||||
# Option: ignoreregex
|
||||
# Notes.: regex to ignore. If this regex matches, the line is ignored.
|
||||
# Values: TEXT
|
||||
#
|
||||
ignoreregex =
|
||||
|
||||
@@ -2,13 +2,22 @@
|
||||
#
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 394 $
|
||||
# $Revision$
|
||||
#
|
||||
|
||||
[Definition]
|
||||
|
||||
# Option: failregex
|
||||
# Notes.: regex to match the password failure messages in the logfile.
|
||||
# Notes.: regex to match the password failure messages in the logfile. The
|
||||
# host must be matched by a group named "host". The tag "<HOST>" can
|
||||
# be used for standard IP/hostname matching and is only an alias for
|
||||
# (?:::f{4,6}:)?(?P<host>\S+)
|
||||
# Values: TEXT
|
||||
#
|
||||
failregex = [[]client (?P<host>\S*)[]] File does not exist: .*(\.php|\.asp)
|
||||
failregex = [[]client <HOST>[]] File does not exist: .*(\.php|\.asp)
|
||||
|
||||
# Option: ignoreregex
|
||||
# Notes.: regex to ignore. If this regex matches, the line is ignored.
|
||||
# Values: TEXT
|
||||
#
|
||||
ignoreregex =
|
||||
|
||||
@@ -3,13 +3,22 @@
|
||||
# Author: Christoph Haas
|
||||
# Modified by: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 267 $
|
||||
# $Revision$
|
||||
#
|
||||
|
||||
[Definition]
|
||||
|
||||
# Option: failregex
|
||||
# Notes.: regex to match the password failures messages in the logfile.
|
||||
# Notes.: regex to match the password failures messages in the logfile. The
|
||||
# host must be matched by a group named "host". The tag "<HOST>" can
|
||||
# be used for standard IP/hostname matching and is only an alias for
|
||||
# (?:::f{4,6}:)?(?P<host>\S+)
|
||||
# Values: TEXT
|
||||
#
|
||||
failregex = LOGIN FAILED, ip=\[::ffff:(?P<host>\S*)\]$
|
||||
failregex = LOGIN FAILED, .*, ip=\[<HOST>\]$
|
||||
|
||||
# Option: ignoreregex
|
||||
# Notes.: regex to ignore. If this regex matches, the line is ignored.
|
||||
# Values: TEXT
|
||||
#
|
||||
ignoreregex =
|
||||
|
||||
@@ -2,13 +2,22 @@
|
||||
#
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 267 $
|
||||
# $Revision$
|
||||
#
|
||||
|
||||
[Definition]
|
||||
|
||||
# Option: failregex
|
||||
# Notes.: regex to match the password failures messages in the logfile.
|
||||
# Notes.: regex to match the password failures messages in the logfile. The
|
||||
# host must be matched by a group named "host". The tag "<HOST>" can
|
||||
# be used for standard IP/hostname matching and is only an alias for
|
||||
# (?:::f{4,6}:)?(?P<host>\S+)
|
||||
# Values: TEXT
|
||||
#
|
||||
failregex = error,relay=(?:::f{4,6}:)?(?P<host>\S*),.*550 User unknown
|
||||
failregex = error,relay=<HOST>,.*550 User unknown
|
||||
|
||||
# Option: ignoreregex
|
||||
# Notes.: regex to ignore. If this regex matches, the line is ignored.
|
||||
# Values: TEXT
|
||||
#
|
||||
ignoreregex =
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
# Fail2Ban configuration file
|
||||
#
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision$
|
||||
#
|
||||
|
||||
[Definition]
|
||||
|
||||
# Option: failregex
|
||||
# Notes.: regex to match the password failures messages in the logfile. The
|
||||
# host must be matched by a group named "host". The tag "<HOST>" can
|
||||
# be used for standard IP/hostname matching and is only an alias for
|
||||
# (?:::f{4,6}:)?(?P<host>\S+)
|
||||
# Values: TEXT
|
||||
#
|
||||
failregex = \[<HOST>\] .*(?:rejected by local_scan|Unrouteable address)
|
||||
|
||||
# Option: ignoreregex
|
||||
# Notes.: regex to ignore. If this regex matches, the line is ignored.
|
||||
# Values: TEXT
|
||||
#
|
||||
ignoreregex =
|
||||
@@ -2,13 +2,22 @@
|
||||
#
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 267 $
|
||||
# $Revision$
|
||||
#
|
||||
|
||||
[Definition]
|
||||
|
||||
# Option: failregex
|
||||
# Notes.: regex to match the password failures messages in the logfile.
|
||||
# Notes.: regex to match the password failures messages in the logfile. The
|
||||
# host must be matched by a group named "host". The tag "<HOST>" can
|
||||
# be used for standard IP/hostname matching and is only an alias for
|
||||
# (?:::f{4,6}:)?(?P<host>\S+)
|
||||
# Values: TEXT
|
||||
#
|
||||
failregex = reject: RCPT from (.*)\[(?P<host>\S*)\]: 554
|
||||
failregex = reject: RCPT from (.*)\[<HOST>\]: 554
|
||||
|
||||
# Option: ignoreregex
|
||||
# Notes.: regex to ignore. If this regex matches, the line is ignored.
|
||||
# Values: TEXT
|
||||
#
|
||||
ignoreregex =
|
||||
|
||||
@@ -2,13 +2,22 @@
|
||||
#
|
||||
# Author: Yaroslav Halchenko
|
||||
#
|
||||
# $Revision: 331 $
|
||||
# $Revision$
|
||||
#
|
||||
|
||||
[Definition]
|
||||
|
||||
# Option: failregex
|
||||
# Notes.: regex to match the password failures messages in the logfile.
|
||||
# Notes.: regex to match the password failures messages in the logfile. The
|
||||
# host must be matched by a group named "host". The tag "<HOST>" can
|
||||
# be used for standard IP/hostname matching and is only an alias for
|
||||
# (?:::f{4,6}:)?(?P<host>\S+)
|
||||
# Values: TEXT
|
||||
#
|
||||
failregex = USER \S+: no such user found from \S* ?\[(?P<host>\S+)\] to \S+\s*$
|
||||
failregex = USER \S+: no such user found from \S* ?\[<HOST>\] to \S+\s*$
|
||||
|
||||
# Option: ignoreregex
|
||||
# Notes.: regex to ignore. If this regex matches, the line is ignored.
|
||||
# Values: TEXT
|
||||
#
|
||||
ignoreregex =
|
||||
|
||||
@@ -2,13 +2,22 @@
|
||||
#
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 267 $
|
||||
# $Revision$
|
||||
#
|
||||
|
||||
[Definition]
|
||||
|
||||
# Option: failregex
|
||||
# Notes.: regex to match the password failures messages in the logfile.
|
||||
# Notes.: regex to match the password failures messages in the logfile. The
|
||||
# host must be matched by a group named "host". The tag "<HOST>" can
|
||||
# be used for standard IP/hostname matching and is only an alias for
|
||||
# (?:::f{4,6}:)?(?P<host>\S+)
|
||||
# Values: TEXT
|
||||
#
|
||||
failregex = (?:[\d,.]+[\d,.] rblsmtpd: |421 badiprbl: ip )(?P<host>\S*)
|
||||
failregex = (?:[\d,.]+[\d,.] rblsmtpd: |421 badiprbl: ip )<HOST>
|
||||
|
||||
# Option: ignoreregex
|
||||
# Notes.: regex to ignore. If this regex matches, the line is ignored.
|
||||
# Values: TEXT
|
||||
#
|
||||
ignoreregex =
|
||||
|
||||
@@ -2,13 +2,22 @@
|
||||
#
|
||||
# Author: Yaroslav Halchenko
|
||||
#
|
||||
# $Revision: 331 $
|
||||
# $Revision$
|
||||
#
|
||||
|
||||
[Definition]
|
||||
|
||||
# Option: failregex
|
||||
# Notes.: regex to match the password failures messages in the logfile.
|
||||
# Notes.: regex to match the password failures messages in the logfile. The
|
||||
# host must be matched by a group named "host". The tag "<HOST>" can
|
||||
# be used for standard IP/hostname matching and is only an alias for
|
||||
# (?:::f{4,6}:)?(?P<host>\S+)
|
||||
# Values: TEXT
|
||||
#
|
||||
failregex = : warning: [-._\w]+\[(?P<host>[.\d]+)\]: SASL (?:LOGIN|PLAIN|(?:CRAM|DIGEST)-MD5) authentication failed$
|
||||
failregex = : warning: [-._\w]+\[<HOST>\]: SASL (?:LOGIN|PLAIN|(?:CRAM|DIGEST)-MD5) authentication failed$
|
||||
|
||||
# Option: ignoreregex
|
||||
# Notes.: regex to ignore. If this regex matches, the line is ignored.
|
||||
# Values: TEXT
|
||||
#
|
||||
ignoreregex =
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
# Fail2Ban configuration file
|
||||
#
|
||||
# Author: Yaroslav Halchenko
|
||||
#
|
||||
# $Revision$
|
||||
#
|
||||
|
||||
[Definition]
|
||||
|
||||
# Option: failregex
|
||||
# Notes.: regex to match the password failures messages in the logfile. The
|
||||
# host must be matched by a group named "host". The tag "<HOST>" can
|
||||
# be used for standard IP/hostname matching and is only an alias for
|
||||
# (?:::f{4,6}:)?(?P<host>\S+)
|
||||
# Values: TEXT
|
||||
#
|
||||
failregex = sshd\[\S*\]: Did not receive identification string from <HOST>
|
||||
|
||||
# Option: ignoreregex
|
||||
# Notes.: regex to ignore. If this regex matches, the line is ignored.
|
||||
# Values: TEXT
|
||||
#
|
||||
ignoreregex =
|
||||
@@ -8,8 +8,19 @@
|
||||
[Definition]
|
||||
|
||||
# Option: failregex
|
||||
# Notes.: regex to match the password failures messages in the logfile.
|
||||
# Notes.: regex to match the password failures messages in the logfile. The
|
||||
# host must be matched by a group named "host". The tag "<HOST>" can
|
||||
# be used for standard IP/hostname matching and is only an alias for
|
||||
# (?:::f{4,6}:)?(?P<host>\S+)
|
||||
# Values: TEXT
|
||||
#
|
||||
failregex = (?:(?:Authentication failure|Failed [-/\w+]+) for(?: [iI](?:llegal|nvalid) user)?|[Ii](?:llegal|nvalid) user|ROOT LOGIN REFUSED) .*(?: from|FROM) (?:::f{4,6}:)?(?P<host>\S*)
|
||||
failregex = Authentication failure for .* from <HOST>
|
||||
Failed [-/\w+]+ for .* from <HOST>
|
||||
ROOT LOGIN REFUSED .* FROM <HOST>
|
||||
[iI](?:llegal|nvalid) user .* from <HOST>
|
||||
|
||||
# Option: ignoreregex
|
||||
# Notes.: regex to ignore. If this regex matches, the line is ignored.
|
||||
# Values: TEXT
|
||||
#
|
||||
ignoreregex =
|
||||
|
||||
@@ -8,7 +8,17 @@
|
||||
[Definition]
|
||||
|
||||
# Option: failregex
|
||||
# Notes.: regex to match the password failures messages in the logfile.
|
||||
# Notes.: regex to match the password failures messages in the logfile. The
|
||||
# host must be matched by a group named "host". The tag "<HOST>" can
|
||||
# be used for standard IP/hostname matching and is only an alias for
|
||||
# (?:::f{4,6}:)?(?P<host>\S+)
|
||||
# Values: TEXT
|
||||
#
|
||||
failregex = vsftpd: \(pam_unix\) authentication failure; .* rhost=(?P<host>\S*)
|
||||
failregex = vsftpd: .* authentication failure; .* rhost=<HOST>$
|
||||
\[.+\] FAIL LOGIN: Client "<HOST>"$
|
||||
|
||||
# Option: ignoreregex
|
||||
# Notes.: regex to ignore. If this regex matches, the line is ignored.
|
||||
# Values: TEXT
|
||||
#
|
||||
ignoreregex =
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
# Fail2Ban configuration file for wuftpd
|
||||
#
|
||||
# Author: Yaroslav Halchenko
|
||||
#
|
||||
# $Revision: $
|
||||
#
|
||||
|
||||
[Definition]
|
||||
|
||||
# Option: failregex
|
||||
# Notes.: regex to match the password failures messages in the logfile.
|
||||
# Values: TEXT
|
||||
#
|
||||
failregex = wu-ftpd\[\d+\]:\s+\(pam_unix\)\s+authentication failure.* rhost=<HOST>
|
||||
+30
-23
@@ -10,13 +10,29 @@
|
||||
|
||||
[DEFAULT]
|
||||
|
||||
# "ignoreip" can be an IP address, a CIDR mask or a DNS host
|
||||
# "ignoreip" can be an IP address, a CIDR mask or a DNS host. Fail2ban will not
|
||||
# ban a host which matches an address in this list. Several addresses can be
|
||||
# defined using space separator.
|
||||
ignoreip = 127.0.0.1
|
||||
|
||||
# "bantime" is the number of seconds that a host is banned.
|
||||
bantime = 600
|
||||
|
||||
# A host is banned if it has generated "maxretry" during the last "findtime"
|
||||
# seconds.
|
||||
findtime = 600
|
||||
|
||||
# "maxretry" is the number of failures before a host get banned.
|
||||
maxretry = 3
|
||||
|
||||
# "backend" specifies the backend used to get files modification. Available
|
||||
# options are "gamin", "polling" and "auto".
|
||||
# options are "gamin", "polling" and "auto". This option can be overridden in
|
||||
# each jail too (use "gamin" for a jail and "polling" for another).
|
||||
#
|
||||
# gamin: requires Gamin (a file alteration monitor) to be installed. If Gamin
|
||||
# is not installed, Fail2ban will use polling.
|
||||
# polling: uses a polling algorithm which does not require external libraries.
|
||||
# auto: will choose Gamin if available and polling otherwise.
|
||||
backend = auto
|
||||
|
||||
|
||||
@@ -53,28 +69,17 @@ action = iptables[name=sasl, port=smtp, protocol=tcp]
|
||||
mail-whois[name=sasl, dest=yourmail@mail.com]
|
||||
logpath = /var/log/mail.log
|
||||
|
||||
# This one behaves like the previous and sends a report when the jail
|
||||
# is stopped.
|
||||
|
||||
[ssh-iptables-report]
|
||||
|
||||
enabled = false
|
||||
filter = sshd
|
||||
action = iptables[name=SSH, port=ssh, protocol=tcp]
|
||||
mail-whois[name=SSH, dest=yourmail@mail.com]
|
||||
mail-report[dest=yourmail@mail.com]
|
||||
logpath = /var/log/sshd.log
|
||||
maxretry = 5
|
||||
|
||||
# Here we use TCP-Wrappers instead of Netfilter/Iptables.
|
||||
# Here we use TCP-Wrappers instead of Netfilter/Iptables. "ignoreregex" is
|
||||
# used to avoid banning the user "myuser".
|
||||
|
||||
[ssh-tcpwrapper]
|
||||
|
||||
enabled = false
|
||||
filter = sshd
|
||||
action = hostsdeny
|
||||
mail-whois[name=SSH, dest=yourmail@mail.com]
|
||||
logpath = /var/log/sshd.log
|
||||
enabled = false
|
||||
filter = sshd
|
||||
action = hostsdeny
|
||||
mail-whois[name=SSH, dest=yourmail@mail.com]
|
||||
ignoreregex = for myuser from
|
||||
logpath = /var/log/sshd.log
|
||||
|
||||
# This jail demonstrates the use of wildcards in "logpath".
|
||||
# Moreover, it is possible to give other files on a new line.
|
||||
@@ -123,13 +128,15 @@ action = shorewall
|
||||
logpath = /var/log/apache2/error_log
|
||||
|
||||
# This jail uses ipfw, the standard firewall on FreeBSD. The "ignoreip"
|
||||
# option is overridden in this jail.
|
||||
# option is overridden in this jail. Moreover, the action "mail-whois" defines
|
||||
# the variable "name" which contains a comma using "". The characters '' are
|
||||
# valid too.
|
||||
|
||||
[ssh-ipfw]
|
||||
|
||||
enabled = false
|
||||
filter = sshd
|
||||
action = ipfw[localhost=192.168.0.1]
|
||||
mail-whois[name=SSH, dest=yourmail@mail.com]
|
||||
mail-whois[name="SSH,IPFW", dest=yourmail@mail.com]
|
||||
logpath = /var/log/auth.log
|
||||
ignoreip = 168.192.0.1
|
||||
|
||||
+76
-41
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/python
|
||||
# This file is part of Fail2Ban.
|
||||
#
|
||||
# Fail2Ban is free software; you can redistribute it and/or modify
|
||||
@@ -25,15 +25,16 @@ __date__ = "$Date$"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
import sys, string, os, pickle, re, logging
|
||||
import sys, string, os, pickle, re, logging, signal
|
||||
import getopt, time, readline, shlex, socket
|
||||
|
||||
# Inserts our own modules path first in the list
|
||||
# fix for bug #343821
|
||||
sys.path.insert(1, "/usr/lib/fail2ban")
|
||||
sys.path.insert(1, "/usr/share/fail2ban")
|
||||
|
||||
# Now we can import our modules
|
||||
from version import version
|
||||
from common.version import version
|
||||
from common.protocol import printFormatted
|
||||
from client.csocket import CSocket
|
||||
from client.configurator import Configurator
|
||||
from client.beautifier import Beautifier
|
||||
@@ -74,7 +75,7 @@ class Fail2banClient:
|
||||
def dispUsage(self):
|
||||
""" Prints Fail2Ban command line options and exits
|
||||
"""
|
||||
print "Usage: "+self.__argv[0]+" [OPTIONS]... <COMMAND>"
|
||||
print "Usage: "+self.__argv[0]+" [OPTIONS] <COMMAND>"
|
||||
print
|
||||
print "Fail2Ban v" + version + " reads log file that contains password failure report"
|
||||
print "and bans the corresponding IP addresses using firewall rules."
|
||||
@@ -86,27 +87,15 @@ class Fail2banClient:
|
||||
print " -i interactive mode"
|
||||
print " -v increase verbosity"
|
||||
print " -q decrease verbosity"
|
||||
print " -x force execution of the server"
|
||||
print " -x force execution of the server (remove socket file)"
|
||||
print " -h, --help display this help message"
|
||||
print " -V, --version print the version"
|
||||
print
|
||||
print "Command:"
|
||||
print " start start the server and the jails"
|
||||
print " reload reload the configuration"
|
||||
print " stop stop all jails and terminate the server"
|
||||
print " status get the current status"
|
||||
print
|
||||
print " set loglevel <LEVEL> set loglevel to <LEVEL>"
|
||||
print " get loglevel get loglevel"
|
||||
print " set logtarget <TARGET> set log target to <TARGET>"
|
||||
print " get logtarget get log target"
|
||||
print
|
||||
print " add <JAIL> [BACKEND] create <JAIL> using [BACKEND]"
|
||||
print " set <JAIL> <CMD> set the <CMD> value for <JAIL>"
|
||||
print " get <JAIL> <CMD> get the <CMD> value for <JAIL>"
|
||||
print " start <JAIL> start <JAIL>"
|
||||
print " stop <JAIL> stop <JAIL>. The jail is removed"
|
||||
print " status <JAIL> get the current status of <JAIL>"
|
||||
|
||||
# Prints the protocol
|
||||
printFormatted()
|
||||
|
||||
print
|
||||
print "Report bugs to <lostcontrol@users.sourceforge.net>"
|
||||
|
||||
@@ -114,7 +103,13 @@ class Fail2banClient:
|
||||
print "Fail2Ban v" + version + " reads log file that contains password failure report"
|
||||
print "and bans the corresponding IP addresses using firewall rules."
|
||||
print
|
||||
|
||||
|
||||
def __sigTERMhandler(self, signum, frame):
|
||||
# Print a new line because we probably come from wait
|
||||
print
|
||||
logSys.warn("Caught signal %d. Exiting" % signum)
|
||||
sys.exit(-1)
|
||||
|
||||
def __getCmdLineOptions(self, optList):
|
||||
""" Gets the command line options
|
||||
"""
|
||||
@@ -180,9 +175,14 @@ class Fail2banClient:
|
||||
logSys.error("Server already running")
|
||||
return False
|
||||
else:
|
||||
self.__startServerAsync(self.__conf["force"])
|
||||
# Read the config while the server is starting
|
||||
self.__readConfig()
|
||||
# Read the config
|
||||
ret = self.__readConfig()
|
||||
# Do not continue if configuration is not 100% valid
|
||||
if not ret:
|
||||
return False
|
||||
# Start the server
|
||||
self.__startServerAsync(self.__conf["socket"],
|
||||
self.__conf["force"])
|
||||
try:
|
||||
# Wait for the server to start
|
||||
self.__waitOnServer()
|
||||
@@ -190,11 +190,18 @@ class Fail2banClient:
|
||||
self.__processCmd(self.__stream, False)
|
||||
return True
|
||||
except ServerExecutionException:
|
||||
logSys.error("Could not start server. Try -x option")
|
||||
logSys.error("Could not start server. Maybe an old " +
|
||||
"socket file is still present. Try to " +
|
||||
"remove " + self.__conf["socket"] + ". If " +
|
||||
"you used fail2ban-client to start the " +
|
||||
"server, adding the -x option will do it")
|
||||
return False
|
||||
elif len(cmd) == 1 and cmd[0] == "reload":
|
||||
if self.__ping():
|
||||
self.__readConfig()
|
||||
ret = self.__readConfig()
|
||||
# Do not continue if configuration is not 100% valid
|
||||
if not ret:
|
||||
return False
|
||||
self.__processCmd([['stop', 'all']], False)
|
||||
# Configure the server
|
||||
return self.__processCmd(self.__stream, False)
|
||||
@@ -210,16 +217,20 @@ class Fail2banClient:
|
||||
#
|
||||
# Start the Fail2ban server in daemon mode.
|
||||
|
||||
def __startServerAsync(self, force = False):
|
||||
args = list()
|
||||
|
||||
args.append("fail2ban-server")
|
||||
args.append("-b")
|
||||
if force:
|
||||
args.append("-x")
|
||||
|
||||
def __startServerAsync(self, socket, force = False):
|
||||
# Forks the current process.
|
||||
pid = os.fork()
|
||||
if pid == 0:
|
||||
args = list()
|
||||
args.append("fail2ban-server")
|
||||
# Start in background mode.
|
||||
args.append("-b")
|
||||
# Set the socket path.
|
||||
args.append("-s")
|
||||
args.append(socket)
|
||||
# Force the execution if needed.
|
||||
if force:
|
||||
args.append("-x")
|
||||
try:
|
||||
# Use the PATH env
|
||||
os.execvp("fail2ban-server", args)
|
||||
@@ -235,17 +246,40 @@ class Fail2banClient:
|
||||
def __waitOnServer(self):
|
||||
# Wait for the server to start
|
||||
cnt = 0
|
||||
if self.__conf["verbose"] > 1:
|
||||
pos = 0
|
||||
delta = 1
|
||||
mask = "[ ]"
|
||||
while not self.__ping():
|
||||
if cnt > 10:
|
||||
# Wonderful visual :)
|
||||
if self.__conf["verbose"] > 1:
|
||||
pos += delta
|
||||
sys.stdout.write("\rINFO " + mask[:pos] + '#' + mask[pos+1:] +
|
||||
" Waiting on the server...")
|
||||
sys.stdout.flush()
|
||||
if pos > len(mask)-3:
|
||||
delta = -1
|
||||
elif pos < 2:
|
||||
delta = 1
|
||||
# The server has 30 secondes to start.
|
||||
if cnt >= 300:
|
||||
if self.__conf["verbose"] > 1:
|
||||
sys.stdout.write('\n')
|
||||
raise ServerExecutionException("Failed to start server")
|
||||
time.sleep(0.1)
|
||||
cnt = cnt + 1
|
||||
cnt += 1
|
||||
if self.__conf["verbose"] > 1:
|
||||
sys.stdout.write('\n')
|
||||
|
||||
|
||||
def start(self, argv):
|
||||
# Command line options
|
||||
self.__argv = argv
|
||||
|
||||
# Install signal handlers
|
||||
signal.signal(signal.SIGTERM, self.__sigTERMhandler)
|
||||
signal.signal(signal.SIGINT, self.__sigTERMhandler)
|
||||
|
||||
# Reads the command line options.
|
||||
try:
|
||||
cmdOpts = 'hc:s:xdviqV'
|
||||
@@ -285,9 +319,9 @@ class Fail2banClient:
|
||||
logSys.info("Using socket file " + self.__conf["socket"])
|
||||
|
||||
if self.__conf["dump"]:
|
||||
self.__readConfig()
|
||||
ret = self.__readConfig()
|
||||
self.dumpConfig(self.__stream)
|
||||
return True
|
||||
return ret
|
||||
|
||||
# Interactive mode
|
||||
if self.__conf["interactive"]:
|
||||
@@ -318,9 +352,10 @@ class Fail2banClient:
|
||||
def __readConfig(self):
|
||||
# Read the configuration
|
||||
self.__configurator.readAll()
|
||||
self.__configurator.getAllOptions()
|
||||
ret = self.__configurator.getAllOptions()
|
||||
self.__configurator.convertToProtocol()
|
||||
self.__stream = self.__configurator.getConfigStream()
|
||||
return ret
|
||||
|
||||
@staticmethod
|
||||
def dumpConfig(cmd):
|
||||
|
||||
+204
-70
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/python
|
||||
# This file is part of Fail2Ban.
|
||||
#
|
||||
# Fail2Ban is free software; you can redistribute it and/or modify
|
||||
@@ -17,33 +17,61 @@
|
||||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 300 $
|
||||
# $Revision$
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 300 $"
|
||||
__date__ = "$Date: 2006-08-23 21:53:09 +0200 (Wed, 23 Aug 2006) $"
|
||||
__version__ = "$Revision$"
|
||||
__date__ = "$Date$"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
import locale, getopt, sys, time, logging, gc
|
||||
import getopt, sys, time, logging, os
|
||||
|
||||
# Inserts our own modules path first in the list
|
||||
# fix for bug #343821
|
||||
sys.path.insert(1, "/usr/lib/fail2ban")
|
||||
sys.path.insert(1, "/usr/share/fail2ban")
|
||||
|
||||
from version import version
|
||||
from ConfigParser import SafeConfigParser
|
||||
from ConfigParser import NoOptionError, NoSectionError, MissingSectionHeaderError
|
||||
from common.version import version
|
||||
from server.filter import Filter
|
||||
from server.regex import RegexException
|
||||
|
||||
# Gets the instance of the logger.
|
||||
logSys = logging.getLogger("fail2ban.regex")
|
||||
|
||||
class RegexStat:
|
||||
|
||||
def __init__(self, failregex):
|
||||
self.__stats = 0
|
||||
self.__failregex = failregex
|
||||
self.__ipList = list()
|
||||
|
||||
def inc(self):
|
||||
self.__stats += 1
|
||||
|
||||
def getStats(self):
|
||||
return self.__stats
|
||||
|
||||
def getFailRegex(self):
|
||||
return self.__failregex
|
||||
|
||||
def appendIP(self, value):
|
||||
self.__ipList.extend(value)
|
||||
|
||||
def getIPList(self):
|
||||
return self.__ipList
|
||||
|
||||
class Fail2banRegex:
|
||||
|
||||
test = None
|
||||
|
||||
def __init__(self):
|
||||
self.__filter = Filter(None)
|
||||
self.__failregex = list()
|
||||
# Setup logging
|
||||
logging.getLogger("fail2ban").handlers = []
|
||||
self.__hdlr = logging.StreamHandler(sys.stdout)
|
||||
self.__hdlr = logging.StreamHandler(Fail2banRegex.test)
|
||||
# set a format which is simpler for console use
|
||||
formatter = logging.Formatter("%(message)s")
|
||||
# tell the handler to use this format
|
||||
@@ -51,7 +79,8 @@ class Fail2banRegex:
|
||||
logging.getLogger("fail2ban").addHandler(self.__hdlr)
|
||||
logging.getLogger("fail2ban").setLevel(logging.ERROR)
|
||||
|
||||
def dispVersion(self):
|
||||
@staticmethod
|
||||
def dispVersion():
|
||||
print "Fail2Ban v" + version
|
||||
print
|
||||
print "Copyright (c) 2004-2006 Cyril Jaquier"
|
||||
@@ -61,14 +90,26 @@ class Fail2banRegex:
|
||||
print "Written by Cyril Jaquier <lostcontrol@users.sourceforge.net>."
|
||||
print "Many contributions by Yaroslav O. Halchenko <debian@onerussian.com>."
|
||||
|
||||
def dispUsage(self):
|
||||
print "Usage: "+sys.argv[0]+" <logline> <failregex>"
|
||||
@staticmethod
|
||||
def dispUsage():
|
||||
print "Usage: "+sys.argv[0]+" [OPTIONS] <LOG> <REGEX>"
|
||||
print
|
||||
print "Fail2Ban v" + version + " reads log file that contains password failure report"
|
||||
print "and bans the corresponding IP addresses using firewall rules."
|
||||
print
|
||||
print "This tools can test and benchmark your regular expressions for the \"failregex\""
|
||||
print "option."
|
||||
print "This tools can test regular expressions for \"fail2ban\"."
|
||||
print
|
||||
print "Options:"
|
||||
print " -h, --help display this help message"
|
||||
print " -V, --version print the version"
|
||||
print
|
||||
print "Log:"
|
||||
print " string a string representing a log line"
|
||||
print " filename path to a log file (/var/log/auth.log)"
|
||||
print
|
||||
print "Regex:"
|
||||
print " string a string representing a 'failregex'"
|
||||
print " filename path to a filter file (filter.d/sshd.conf)"
|
||||
print
|
||||
print "Report bugs to <lostcontrol@users.sourceforge.net>"
|
||||
|
||||
@@ -77,88 +118,181 @@ class Fail2banRegex:
|
||||
"""
|
||||
for opt in optList:
|
||||
if opt[0] in ["-h", "--help"]:
|
||||
self.dispUsage()
|
||||
sys.exit(0)
|
||||
elif opt[0] in ["-V", "--version"]:
|
||||
self.dispVersion()
|
||||
sys.exit(0)
|
||||
|
||||
def setRegex(self, value):
|
||||
print
|
||||
self.__filter.setFailRegex(value)
|
||||
self.dispUsage()
|
||||
sys.exit(0)
|
||||
elif opt[0] in ["-V", "--version"]:
|
||||
self.dispVersion()
|
||||
sys.exit(0)
|
||||
|
||||
@staticmethod
|
||||
def logIsFile(value):
|
||||
return os.path.isfile(value)
|
||||
|
||||
def readRegex(self, value):
|
||||
if os.path.isfile(value):
|
||||
reader = SafeConfigParser()
|
||||
try:
|
||||
reader.read(value)
|
||||
print "Use regex file : " + value
|
||||
self.__failregex = [RegexStat(m)
|
||||
for m in reader.get("Definition", "failregex").split('\n')]
|
||||
except NoSectionError:
|
||||
print "No [Definition] section in " + value
|
||||
print
|
||||
return False
|
||||
except NoOptionError:
|
||||
print "No failregex option in " + value
|
||||
print
|
||||
return False
|
||||
except MissingSectionHeaderError:
|
||||
print "No section headers in " + value
|
||||
print
|
||||
return False
|
||||
else:
|
||||
if len(value) > 53:
|
||||
stripReg = value[0:50] + "..."
|
||||
else:
|
||||
stripReg = value
|
||||
print "Use regex line : " + stripReg
|
||||
self.__failregex = [RegexStat(value)]
|
||||
return True
|
||||
|
||||
def testRegex(self, line):
|
||||
print
|
||||
try:
|
||||
found = False
|
||||
for regex in self.__failregex:
|
||||
logging.getLogger("fail2ban").setLevel(logging.DEBUG)
|
||||
ret = self.__filter.findFailure(line)
|
||||
print
|
||||
logging.getLogger("fail2ban").setLevel(logging.CRITICAL)
|
||||
except IndexError:
|
||||
print "Sorry, but no <host> found in regex"
|
||||
return False
|
||||
if len(ret) == 0:
|
||||
try:
|
||||
self.__filter.addFailRegex(regex.getFailRegex())
|
||||
try:
|
||||
ret = self.__filter.findFailure(line)
|
||||
if not len(ret) == 0:
|
||||
if found == True:
|
||||
ret[0].append(True)
|
||||
else:
|
||||
found = True
|
||||
ret[0].append(False)
|
||||
regex.inc()
|
||||
regex.appendIP(ret)
|
||||
except RegexException, e:
|
||||
print e
|
||||
return False
|
||||
except IndexError:
|
||||
print "Sorry, but no <host> found in regex"
|
||||
return False
|
||||
finally:
|
||||
self.__filter.delFailRegex(0)
|
||||
logging.getLogger("fail2ban").setLevel(logging.CRITICAL)
|
||||
|
||||
def printStats(self):
|
||||
print
|
||||
print "Results"
|
||||
print "======="
|
||||
print
|
||||
|
||||
# Print title
|
||||
cnt = 1
|
||||
print "Failregex:"
|
||||
for failregex in self.__failregex:
|
||||
print "[" + str(cnt) + "] " + failregex.getFailRegex()
|
||||
cnt += 1
|
||||
|
||||
print
|
||||
|
||||
# Print stats
|
||||
cnt = 1
|
||||
total = 0
|
||||
print "Number of matches:"
|
||||
for failregex in self.__failregex:
|
||||
match = failregex.getStats()
|
||||
total += match
|
||||
print "[" + str(cnt) + "] " + str(match) + " match(es)"
|
||||
cnt += 1
|
||||
|
||||
print
|
||||
|
||||
if total == 0:
|
||||
print "Sorry, no match"
|
||||
print
|
||||
print "Look at the above section 'Running tests' which could contain important"
|
||||
print "information."
|
||||
return False
|
||||
else:
|
||||
print "Success, the following data were found:"
|
||||
timeTuple = time.localtime(ret[0][1])
|
||||
print "Date: " + time.strftime("%a %b %d %H:%M:%S %Y", timeTuple)
|
||||
ipList = ""
|
||||
for i in ret:
|
||||
ipList = ipList + " " + i[0]
|
||||
print "IP :" + ipList
|
||||
# Print stats
|
||||
cnt = 1
|
||||
print "Addresses found:"
|
||||
for failregex in self.__failregex:
|
||||
print "[" + str(cnt) + "]"
|
||||
for ip in failregex.getIPList():
|
||||
timeTuple = time.localtime(ip[1])
|
||||
timeString = time.strftime("%a %b %d %H:%M:%S %Y", timeTuple)
|
||||
if ip[2]:
|
||||
dup = " (already matched)"
|
||||
else:
|
||||
dup = ""
|
||||
print " " + ip[0] + " (" + timeString + ")" + dup
|
||||
cnt += 1
|
||||
|
||||
print
|
||||
|
||||
print "Date template hits:"
|
||||
for template in self.__filter.dateDetector.getTemplates():
|
||||
print `template.getHits()` + " hit: " + template.getName()
|
||||
|
||||
print
|
||||
print "Benchmark. Executing 1000..."
|
||||
gc.disable()
|
||||
total = 0
|
||||
maxValue = 0
|
||||
maxPos = 0
|
||||
minValue = 99999999
|
||||
minPos = 0
|
||||
for i in range(1000):
|
||||
start = time.time()
|
||||
ret = self.__filter.findFailure(line)
|
||||
end = time.time()
|
||||
diff = (end - start) * 1000
|
||||
total = total + diff
|
||||
minValue = min(minValue, diff)
|
||||
if minValue == diff:
|
||||
minPos = i
|
||||
maxValue = max(maxValue, diff)
|
||||
if maxValue == diff:
|
||||
maxPos = i
|
||||
gc.enable()
|
||||
print "Performance"
|
||||
print "Avg: " + `total / 1000` + " ms"
|
||||
print "Max: " + `maxValue` + " ms (Run " + `maxPos` + ")"
|
||||
print "Min: " + `minValue` + " ms (Run " + `minPos` + ")"
|
||||
|
||||
print "Success, the total number of match is " + str(total)
|
||||
print
|
||||
print "However, look at the above section 'Running tests' which could contain important"
|
||||
print "information."
|
||||
return True
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
regex = Fail2banRegex()
|
||||
fail2banRegex = Fail2banRegex()
|
||||
# Reads the command line options.
|
||||
try:
|
||||
cmdOpts = 'hV'
|
||||
cmdLongOpts = ['help', 'version']
|
||||
optList, args = getopt.getopt(sys.argv[1:], cmdOpts, cmdLongOpts)
|
||||
except getopt.GetoptError:
|
||||
regex.dispUsage()
|
||||
fail2banRegex.dispUsage()
|
||||
sys.exit(-1)
|
||||
# Process command line
|
||||
regex.getCmdLineOptions(optList)
|
||||
fail2banRegex.getCmdLineOptions(optList)
|
||||
# We need exactly 3 parameters
|
||||
if len(sys.argv) <> 3:
|
||||
regex.dispUsage()
|
||||
if not len(sys.argv) == 3:
|
||||
fail2banRegex.dispUsage()
|
||||
sys.exit(-1)
|
||||
else:
|
||||
regex.setRegex(sys.argv[2])
|
||||
ret = regex.testRegex(sys.argv[1])
|
||||
if ret:
|
||||
print
|
||||
print "Running tests"
|
||||
print "============="
|
||||
print
|
||||
|
||||
if fail2banRegex.readRegex(sys.argv[2]) == False:
|
||||
sys.exit(-1)
|
||||
|
||||
if fail2banRegex.logIsFile(sys.argv[1]):
|
||||
try:
|
||||
hdlr = open(sys.argv[1])
|
||||
print "Use log file : " + sys.argv[1]
|
||||
print
|
||||
for line in hdlr:
|
||||
fail2banRegex.testRegex(line)
|
||||
except IOError, e:
|
||||
print e
|
||||
print
|
||||
sys.exit(-1)
|
||||
else:
|
||||
if len(sys.argv[1]) > 53:
|
||||
stripLog = sys.argv[1][0:50] + "..."
|
||||
else:
|
||||
stripLog = sys.argv[1]
|
||||
print "Use single line: " + stripLog
|
||||
print
|
||||
fail2banRegex.testRegex(sys.argv[1])
|
||||
|
||||
if fail2banRegex.printStats():
|
||||
sys.exit(0)
|
||||
else:
|
||||
sys.exit(-1)
|
||||
|
||||
+12
-10
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/python
|
||||
# This file is part of Fail2Ban.
|
||||
#
|
||||
# Fail2Ban is free software; you can redistribute it and/or modify
|
||||
@@ -29,9 +29,9 @@ import getopt, sys
|
||||
|
||||
# Inserts our own modules path first in the list
|
||||
# fix for bug #343821
|
||||
sys.path.insert(1, "/usr/lib/fail2ban")
|
||||
sys.path.insert(1, "/usr/share/fail2ban")
|
||||
|
||||
from version import version
|
||||
from common.version import version
|
||||
from server.server import Server
|
||||
|
||||
##
|
||||
@@ -71,15 +71,16 @@ class Fail2banServer:
|
||||
print "and bans the corresponding IP addresses using firewall rules."
|
||||
print
|
||||
print "Only use this command for debugging purpose. Start the server with"
|
||||
print "fail2ban-client instead."
|
||||
print "fail2ban-client instead. The default behaviour is to start the server"
|
||||
print "in background."
|
||||
print
|
||||
print "Options:"
|
||||
print " -b start in background"
|
||||
print " -f start in foreground"
|
||||
print " -s <FILE> socket path"
|
||||
print " -x force execution of the server"
|
||||
print " -h, --help display this help message"
|
||||
print " -V, --version print the version"
|
||||
print " -b start in background"
|
||||
print " -f start in foreground"
|
||||
print " -s <FILE> socket path"
|
||||
print " -x force execution of the server (remove socket file)"
|
||||
print " -h, --help display this help message"
|
||||
print " -V, --version print the version"
|
||||
print
|
||||
print "Report bugs to <lostcontrol@users.sourceforge.net>"
|
||||
|
||||
@@ -113,6 +114,7 @@ class Fail2banServer:
|
||||
optList, args = getopt.getopt(self.__argv[1:], cmdOpts, cmdLongOpts)
|
||||
except getopt.GetoptError:
|
||||
self.dispUsage()
|
||||
sys.exit(-1)
|
||||
|
||||
self.__getCmdLineOptions(optList)
|
||||
|
||||
|
||||
+2
-6
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/python
|
||||
# This file is part of Fail2Ban.
|
||||
#
|
||||
# Fail2Ban is free software; you can redistribute it and/or modify
|
||||
@@ -28,11 +28,7 @@ __license__ = "GPL"
|
||||
|
||||
import unittest, logging, sys
|
||||
|
||||
# Inserts our own modules path first in the list
|
||||
# fix for bug #343821
|
||||
sys.path.insert(1, "/usr/lib/fail2ban")
|
||||
|
||||
from version import version
|
||||
from common.version import version
|
||||
from testcases import banmanagertestcase
|
||||
from testcases import clientreadertestcase
|
||||
from testcases import failmanagertestcase
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
__ _ _ ___ _
|
||||
/ _|__ _(_) |_ ) |__ __ _ _ _
|
||||
| _/ _` | | |/ /| '_ \/ _` | ' \
|
||||
|_| \__,_|_|_/___|_.__/\__,_|_||_|
|
||||
|
||||
=============================================================
|
||||
Fail2Ban (version 0.7.7) 2007/??/??
|
||||
=============================================================
|
||||
|
||||
Cacti is a graphing solution using RRDTool. It is possible to
|
||||
use Cacti to display statistics about Fail2ban.
|
||||
|
||||
Installation:
|
||||
-------------
|
||||
|
||||
1/ Install Fail2ban version 0.7 or higher and ensure that it
|
||||
works properly.
|
||||
2/ The user running poller.php must have read and write
|
||||
access to the socket used by Fail2ban.
|
||||
3/ Copy fail2ban_stats.sh to scripts/. You can test it with
|
||||
bash scripts/fail2ban_stats.sh
|
||||
4/ Import the template cacti_host_template_fail2ban.xml
|
||||
5/ TO BE CONTINUED...
|
||||
|
||||
Contact:
|
||||
--------
|
||||
|
||||
You need some new features, you found bugs or you just
|
||||
appreciate this program, you can contact me at:
|
||||
|
||||
Website: http://www.fail2ban.org
|
||||
|
||||
Cyril Jaquier: <lostcontrol@users.sourceforge.net>
|
||||
|
||||
License:
|
||||
--------
|
||||
|
||||
Fail2Ban is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
Fail2Ban is distributed in the hope that it will be
|
||||
useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public
|
||||
License along with Fail2Ban; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
Boston, MA 02111-1307 USA
|
||||
@@ -0,0 +1,297 @@
|
||||
<cacti>
|
||||
<hash_02001346a4e9f7498a8129f0dfc2e1c8c7b35a>
|
||||
<name>Fail2ban</name>
|
||||
<graph_templates>hash_0000132fe631a3ac1f1705e332d0aee925d21b</graph_templates>
|
||||
<data_queries></data_queries>
|
||||
</hash_02001346a4e9f7498a8129f0dfc2e1c8c7b35a>
|
||||
<hash_0000132fe631a3ac1f1705e332d0aee925d21b>
|
||||
<name>Fail2ban - Statistics</name>
|
||||
<graph>
|
||||
<t_title>on</t_title>
|
||||
<title>|host_description| - Statistics</title>
|
||||
<t_image_format_id></t_image_format_id>
|
||||
<image_format_id>1</image_format_id>
|
||||
<t_height></t_height>
|
||||
<height>120</height>
|
||||
<t_width></t_width>
|
||||
<width>500</width>
|
||||
<t_auto_scale></t_auto_scale>
|
||||
<auto_scale>on</auto_scale>
|
||||
<t_auto_scale_opts></t_auto_scale_opts>
|
||||
<auto_scale_opts>2</auto_scale_opts>
|
||||
<t_auto_scale_log></t_auto_scale_log>
|
||||
<auto_scale_log></auto_scale_log>
|
||||
<t_auto_scale_rigid></t_auto_scale_rigid>
|
||||
<auto_scale_rigid></auto_scale_rigid>
|
||||
<t_auto_padding></t_auto_padding>
|
||||
<auto_padding>on</auto_padding>
|
||||
<t_export></t_export>
|
||||
<export>on</export>
|
||||
<t_upper_limit></t_upper_limit>
|
||||
<upper_limit>100</upper_limit>
|
||||
<t_lower_limit></t_lower_limit>
|
||||
<lower_limit>0</lower_limit>
|
||||
<t_base_value></t_base_value>
|
||||
<base_value>1000</base_value>
|
||||
<t_unit_value></t_unit_value>
|
||||
<unit_value></unit_value>
|
||||
<t_unit_exponent_value></t_unit_exponent_value>
|
||||
<unit_exponent_value></unit_exponent_value>
|
||||
<t_vertical_label></t_vertical_label>
|
||||
<vertical_label>hits/5min</vertical_label>
|
||||
</graph>
|
||||
<items>
|
||||
<hash_100013f76575fdcd7f2684843e8f2cbae4ef96>
|
||||
<task_item_id>hash_0800132d7bfb27a7ecb33f23433863e6f90612</task_item_id>
|
||||
<color_id>00CF00</color_id>
|
||||
<graph_type_id>4</graph_type_id>
|
||||
<consolidation_function_id>1</consolidation_function_id>
|
||||
<cdef_id>hash_050013e961cc8ec04fda6ed4981cf5ad501aa5</cdef_id>
|
||||
<value></value>
|
||||
<gprint_id>hash_060013e9c43831e54eca8069317a2ce8c6f751</gprint_id>
|
||||
<text_format>Failed</text_format>
|
||||
<hard_return></hard_return>
|
||||
<sequence>1</sequence>
|
||||
</hash_100013f76575fdcd7f2684843e8f2cbae4ef96>
|
||||
<hash_100013ca0d59c48dde83a1753e21eb1f44a396>
|
||||
<task_item_id>hash_0800132d7bfb27a7ecb33f23433863e6f90612</task_item_id>
|
||||
<color_id>0</color_id>
|
||||
<graph_type_id>9</graph_type_id>
|
||||
<consolidation_function_id>4</consolidation_function_id>
|
||||
<cdef_id>hash_050013e961cc8ec04fda6ed4981cf5ad501aa5</cdef_id>
|
||||
<value></value>
|
||||
<gprint_id>hash_060013e9c43831e54eca8069317a2ce8c6f751</gprint_id>
|
||||
<text_format>Current:</text_format>
|
||||
<hard_return></hard_return>
|
||||
<sequence>2</sequence>
|
||||
</hash_100013ca0d59c48dde83a1753e21eb1f44a396>
|
||||
<hash_1000132f8d371932ebedbb665f80abf427ffb4>
|
||||
<task_item_id>hash_0800132d7bfb27a7ecb33f23433863e6f90612</task_item_id>
|
||||
<color_id>0</color_id>
|
||||
<graph_type_id>9</graph_type_id>
|
||||
<consolidation_function_id>1</consolidation_function_id>
|
||||
<cdef_id>hash_050013e961cc8ec04fda6ed4981cf5ad501aa5</cdef_id>
|
||||
<value></value>
|
||||
<gprint_id>hash_060013e9c43831e54eca8069317a2ce8c6f751</gprint_id>
|
||||
<text_format>Average:</text_format>
|
||||
<hard_return></hard_return>
|
||||
<sequence>3</sequence>
|
||||
</hash_1000132f8d371932ebedbb665f80abf427ffb4>
|
||||
<hash_1000131b8e847f7be22014f1f0b3d098c9e702>
|
||||
<task_item_id>hash_0800132d7bfb27a7ecb33f23433863e6f90612</task_item_id>
|
||||
<color_id>0</color_id>
|
||||
<graph_type_id>9</graph_type_id>
|
||||
<consolidation_function_id>3</consolidation_function_id>
|
||||
<cdef_id>hash_050013e961cc8ec04fda6ed4981cf5ad501aa5</cdef_id>
|
||||
<value></value>
|
||||
<gprint_id>hash_060013e9c43831e54eca8069317a2ce8c6f751</gprint_id>
|
||||
<text_format>Maximum:</text_format>
|
||||
<hard_return>on</hard_return>
|
||||
<sequence>4</sequence>
|
||||
</hash_1000131b8e847f7be22014f1f0b3d098c9e702>
|
||||
<hash_1000130e6084fd4ed86d8c86dea8f84b115eaa>
|
||||
<task_item_id>hash_080013b224f2764ba5a827de959b1ff44cbc1d</task_item_id>
|
||||
<color_id>FF0000</color_id>
|
||||
<graph_type_id>5</graph_type_id>
|
||||
<consolidation_function_id>1</consolidation_function_id>
|
||||
<cdef_id>hash_050013e961cc8ec04fda6ed4981cf5ad501aa5</cdef_id>
|
||||
<value></value>
|
||||
<gprint_id>hash_060013e9c43831e54eca8069317a2ce8c6f751</gprint_id>
|
||||
<text_format>Banned</text_format>
|
||||
<hard_return></hard_return>
|
||||
<sequence>5</sequence>
|
||||
</hash_1000130e6084fd4ed86d8c86dea8f84b115eaa>
|
||||
<hash_1000132812e5f3ee8261819268854c67093b94>
|
||||
<task_item_id>hash_080013b224f2764ba5a827de959b1ff44cbc1d</task_item_id>
|
||||
<color_id>0</color_id>
|
||||
<graph_type_id>9</graph_type_id>
|
||||
<consolidation_function_id>4</consolidation_function_id>
|
||||
<cdef_id>hash_050013e961cc8ec04fda6ed4981cf5ad501aa5</cdef_id>
|
||||
<value></value>
|
||||
<gprint_id>hash_060013e9c43831e54eca8069317a2ce8c6f751</gprint_id>
|
||||
<text_format>Current:</text_format>
|
||||
<hard_return></hard_return>
|
||||
<sequence>6</sequence>
|
||||
</hash_1000132812e5f3ee8261819268854c67093b94>
|
||||
<hash_10001336fcfc1d017e975fa22a3ce0d0492daf>
|
||||
<task_item_id>hash_080013b224f2764ba5a827de959b1ff44cbc1d</task_item_id>
|
||||
<color_id>0</color_id>
|
||||
<graph_type_id>9</graph_type_id>
|
||||
<consolidation_function_id>1</consolidation_function_id>
|
||||
<cdef_id>hash_050013e961cc8ec04fda6ed4981cf5ad501aa5</cdef_id>
|
||||
<value></value>
|
||||
<gprint_id>hash_060013e9c43831e54eca8069317a2ce8c6f751</gprint_id>
|
||||
<text_format>Average:</text_format>
|
||||
<hard_return></hard_return>
|
||||
<sequence>7</sequence>
|
||||
</hash_10001336fcfc1d017e975fa22a3ce0d0492daf>
|
||||
<hash_100013e5fddd5da42b9bf296d7f344b2a00446>
|
||||
<task_item_id>hash_080013b224f2764ba5a827de959b1ff44cbc1d</task_item_id>
|
||||
<color_id>0</color_id>
|
||||
<graph_type_id>9</graph_type_id>
|
||||
<consolidation_function_id>3</consolidation_function_id>
|
||||
<cdef_id>hash_050013e961cc8ec04fda6ed4981cf5ad501aa5</cdef_id>
|
||||
<value></value>
|
||||
<gprint_id>hash_060013e9c43831e54eca8069317a2ce8c6f751</gprint_id>
|
||||
<text_format>Maximum:</text_format>
|
||||
<hard_return>on</hard_return>
|
||||
<sequence>8</sequence>
|
||||
</hash_100013e5fddd5da42b9bf296d7f344b2a00446>
|
||||
</items>
|
||||
<inputs>
|
||||
<hash_090013a5d69bc5ca8b53ef62b61221a69b8055>
|
||||
<name>Data Source [banned]</name>
|
||||
<description></description>
|
||||
<column_name>task_item_id</column_name>
|
||||
<items>hash_0000130e6084fd4ed86d8c86dea8f84b115eaa|hash_0000132812e5f3ee8261819268854c67093b94|hash_00001336fcfc1d017e975fa22a3ce0d0492daf|hash_000013e5fddd5da42b9bf296d7f344b2a00446</items>
|
||||
</hash_090013a5d69bc5ca8b53ef62b61221a69b8055>
|
||||
<hash_0900132cee6f79f051b0dd39cafcbfcfd87960>
|
||||
<name>Data Source [failed]</name>
|
||||
<description></description>
|
||||
<column_name>task_item_id</column_name>
|
||||
<items>hash_000013f76575fdcd7f2684843e8f2cbae4ef96|hash_000013ca0d59c48dde83a1753e21eb1f44a396|hash_0000131b8e847f7be22014f1f0b3d098c9e702|hash_0000132f8d371932ebedbb665f80abf427ffb4</items>
|
||||
</hash_0900132cee6f79f051b0dd39cafcbfcfd87960>
|
||||
</inputs>
|
||||
</hash_0000132fe631a3ac1f1705e332d0aee925d21b>
|
||||
<hash_0100130fce21647570158d210c7832cd50e98a>
|
||||
<name>Fail2ban - Statistics</name>
|
||||
<ds>
|
||||
<t_name></t_name>
|
||||
<name>|host_description| - Statistics</name>
|
||||
<data_input_id>hash_030013a3adf3f2607747859b08262d972eabf0</data_input_id>
|
||||
<t_rra_id></t_rra_id>
|
||||
<t_rrd_step></t_rrd_step>
|
||||
<rrd_step>300</rrd_step>
|
||||
<t_active></t_active>
|
||||
<active>on</active>
|
||||
<rra_items>hash_150013c21df5178e5c955013591239eb0afd46|hash_1500130d9c0af8b8acdc7807943937b3208e29|hash_1500136fc2d038fb42950138b0ce3e9874cc60|hash_150013e36f3adb9f152adfa5dc50fd2b23337e</rra_items>
|
||||
</ds>
|
||||
<items>
|
||||
<hash_0800132d7bfb27a7ecb33f23433863e6f90612>
|
||||
<t_data_source_name></t_data_source_name>
|
||||
<data_source_name>failed</data_source_name>
|
||||
<t_rrd_minimum></t_rrd_minimum>
|
||||
<rrd_minimum>0</rrd_minimum>
|
||||
<t_rrd_maximum></t_rrd_maximum>
|
||||
<rrd_maximum>0</rrd_maximum>
|
||||
<t_data_source_type_id></t_data_source_type_id>
|
||||
<data_source_type_id>2</data_source_type_id>
|
||||
<t_rrd_heartbeat></t_rrd_heartbeat>
|
||||
<rrd_heartbeat>600</rrd_heartbeat>
|
||||
<t_data_input_field_id></t_data_input_field_id>
|
||||
<data_input_field_id>hash_0700134027ae7d3baefb02f510c09de07d159f</data_input_field_id>
|
||||
</hash_0800132d7bfb27a7ecb33f23433863e6f90612>
|
||||
<hash_080013b224f2764ba5a827de959b1ff44cbc1d>
|
||||
<t_data_source_name></t_data_source_name>
|
||||
<data_source_name>banned</data_source_name>
|
||||
<t_rrd_minimum></t_rrd_minimum>
|
||||
<rrd_minimum>0</rrd_minimum>
|
||||
<t_rrd_maximum></t_rrd_maximum>
|
||||
<rrd_maximum>0</rrd_maximum>
|
||||
<t_data_source_type_id></t_data_source_type_id>
|
||||
<data_source_type_id>2</data_source_type_id>
|
||||
<t_rrd_heartbeat></t_rrd_heartbeat>
|
||||
<rrd_heartbeat>600</rrd_heartbeat>
|
||||
<t_data_input_field_id></t_data_input_field_id>
|
||||
<data_input_field_id>hash_07001319c32c9466152aa6cfc2bbc639a246d8</data_input_field_id>
|
||||
</hash_080013b224f2764ba5a827de959b1ff44cbc1d>
|
||||
</items>
|
||||
<data>
|
||||
<item_000>
|
||||
<data_input_field_id>hash_0700131cda0f872b68c87e508a29e8976a6a7a</data_input_field_id>
|
||||
<t_value>on</t_value>
|
||||
<value>ssh-iptables</value>
|
||||
</item_000>
|
||||
</data>
|
||||
</hash_0100130fce21647570158d210c7832cd50e98a>
|
||||
<hash_030013a3adf3f2607747859b08262d972eabf0>
|
||||
<name>Fail2ban - Get statistics</name>
|
||||
<type_id>1</type_id>
|
||||
<input_string>bash <path_cacti>/scripts/fail2ban_stats.sh <jail></input_string>
|
||||
<fields>
|
||||
<hash_0700131cda0f872b68c87e508a29e8976a6a7a>
|
||||
<name>Jail name</name>
|
||||
<update_rra></update_rra>
|
||||
<regexp_match></regexp_match>
|
||||
<allow_nulls></allow_nulls>
|
||||
<type_code></type_code>
|
||||
<input_output>in</input_output>
|
||||
<data_name>jail</data_name>
|
||||
</hash_0700131cda0f872b68c87e508a29e8976a6a7a>
|
||||
<hash_0700134027ae7d3baefb02f510c09de07d159f>
|
||||
<name>Total of failed logins</name>
|
||||
<update_rra>on</update_rra>
|
||||
<regexp_match></regexp_match>
|
||||
<allow_nulls></allow_nulls>
|
||||
<type_code></type_code>
|
||||
<input_output>out</input_output>
|
||||
<data_name>failed</data_name>
|
||||
</hash_0700134027ae7d3baefb02f510c09de07d159f>
|
||||
<hash_07001319c32c9466152aa6cfc2bbc639a246d8>
|
||||
<name>Total of banned hosts</name>
|
||||
<update_rra>on</update_rra>
|
||||
<regexp_match></regexp_match>
|
||||
<allow_nulls></allow_nulls>
|
||||
<type_code></type_code>
|
||||
<input_output>out</input_output>
|
||||
<data_name>banned</data_name>
|
||||
</hash_07001319c32c9466152aa6cfc2bbc639a246d8>
|
||||
</fields>
|
||||
</hash_030013a3adf3f2607747859b08262d972eabf0>
|
||||
<hash_150013c21df5178e5c955013591239eb0afd46>
|
||||
<name>Daily (5 Minute Average)</name>
|
||||
<x_files_factor>0.5</x_files_factor>
|
||||
<steps>1</steps>
|
||||
<rows>600</rows>
|
||||
<timespan>86400</timespan>
|
||||
<cf_items>1|2|3|4</cf_items>
|
||||
</hash_150013c21df5178e5c955013591239eb0afd46>
|
||||
<hash_1500130d9c0af8b8acdc7807943937b3208e29>
|
||||
<name>Weekly (30 Minute Average)</name>
|
||||
<x_files_factor>0.5</x_files_factor>
|
||||
<steps>6</steps>
|
||||
<rows>700</rows>
|
||||
<timespan>604800</timespan>
|
||||
<cf_items>1|2|3|4</cf_items>
|
||||
</hash_1500130d9c0af8b8acdc7807943937b3208e29>
|
||||
<hash_1500136fc2d038fb42950138b0ce3e9874cc60>
|
||||
<name>Monthly (2 Hour Average)</name>
|
||||
<x_files_factor>0.5</x_files_factor>
|
||||
<steps>24</steps>
|
||||
<rows>775</rows>
|
||||
<timespan>2678400</timespan>
|
||||
<cf_items>1|2|3|4</cf_items>
|
||||
</hash_1500136fc2d038fb42950138b0ce3e9874cc60>
|
||||
<hash_150013e36f3adb9f152adfa5dc50fd2b23337e>
|
||||
<name>Yearly (1 Day Average)</name>
|
||||
<x_files_factor>0.5</x_files_factor>
|
||||
<steps>288</steps>
|
||||
<rows>797</rows>
|
||||
<timespan>33053184</timespan>
|
||||
<cf_items>1|2|3|4</cf_items>
|
||||
</hash_150013e36f3adb9f152adfa5dc50fd2b23337e>
|
||||
<hash_050013e961cc8ec04fda6ed4981cf5ad501aa5>
|
||||
<name>Make Per 5 Minutes</name>
|
||||
<items>
|
||||
<hash_14001340bb7a1143b0f2e2efca14eb356236de>
|
||||
<sequence>1</sequence>
|
||||
<type>4</type>
|
||||
<value>CURRENT_DATA_SOURCE</value>
|
||||
</hash_14001340bb7a1143b0f2e2efca14eb356236de>
|
||||
<hash_140013faf1b148b2c0e0527362ed5b8ca1d351>
|
||||
<sequence>2</sequence>
|
||||
<type>6</type>
|
||||
<value>300</value>
|
||||
</hash_140013faf1b148b2c0e0527362ed5b8ca1d351>
|
||||
<hash_14001342686ea0925c0220924b7d333599cd67>
|
||||
<sequence>3</sequence>
|
||||
<type>2</type>
|
||||
<value>3</value>
|
||||
</hash_14001342686ea0925c0220924b7d333599cd67>
|
||||
</items>
|
||||
</hash_050013e961cc8ec04fda6ed4981cf5ad501aa5>
|
||||
<hash_060013e9c43831e54eca8069317a2ce8c6f751>
|
||||
<name>Normal</name>
|
||||
<gprint_text>%8.2lf %s</gprint_text>
|
||||
</hash_060013e9c43831e54eca8069317a2ce8c6f751>
|
||||
</cacti>
|
||||
@@ -0,0 +1,47 @@
|
||||
#!/bin/bash
|
||||
# This file is part of Fail2Ban.
|
||||
#
|
||||
# Fail2Ban is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Fail2Ban is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Fail2Ban; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
# This script can be used to collect data for Cacti. One parameter is needed,
|
||||
# the jail name. It must be a currently running jail. The script returns two
|
||||
# value: the number of failures and the number of banned host.
|
||||
#
|
||||
# If Fail2ban is not available in the path, you can change the value of the
|
||||
# variable FAIL2BAN below.. You can add option to this variable too. Please
|
||||
# look at the man page of fail2ban-client for more information.
|
||||
#
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision$
|
||||
|
||||
FAIL2BAN="fail2ban-client"
|
||||
|
||||
JAIL=$1
|
||||
|
||||
if [ -z $JAIL ]; then
|
||||
echo "Usage:" `basename $0` "<jail>"
|
||||
exit
|
||||
fi
|
||||
|
||||
IFS=""
|
||||
|
||||
STATS=$($FAIL2BAN status $JAIL)
|
||||
|
||||
TOTAL_FAILED=$(echo $STATS | grep "Total failed:" | awk '{ print $5 }')
|
||||
TOTAL_BANNED=$(echo $STATS | grep "Total banned:" | awk '{ print $4 }')
|
||||
|
||||
echo "failed:"$TOTAL_FAILED "banned:"$TOTAL_BANNED
|
||||
|
||||
+27
-1
@@ -17,7 +17,7 @@
|
||||
#
|
||||
# Author: Sireyessire, Cyril Jaquier
|
||||
#
|
||||
# $Revision: 1.2 $
|
||||
# $Revision$
|
||||
|
||||
opts="start stop restart reload showlog"
|
||||
|
||||
@@ -41,6 +41,32 @@ stop() {
|
||||
eend $? "Failed to stop fail2ban"
|
||||
}
|
||||
|
||||
restart() {
|
||||
if ! service_stopped "${SVCNAME}" ; then
|
||||
svc_stop || return "$?"
|
||||
einfon "Waiting for server to shutdown ."
|
||||
cnt=0
|
||||
while [ 1 ]; do
|
||||
# Ping fail2ban-server
|
||||
${FAIL2BAN} ping &> /dev/null
|
||||
if [ ! "$?" == "0" ]; then
|
||||
break
|
||||
fi
|
||||
cnt=`expr $cnt + 1`
|
||||
if [ $cnt -gt 60 ] ; then
|
||||
# We have waited 1 minute. Failed
|
||||
echo
|
||||
eend 1 "Failed"
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
echo -n "."
|
||||
done
|
||||
echo
|
||||
fi
|
||||
svc_start
|
||||
}
|
||||
|
||||
reload() {
|
||||
ebegin "Reloading fail2ban"
|
||||
${FAIL2BAN} reload > /dev/null
|
||||
|
||||
+3
-2
@@ -27,7 +27,7 @@ getpid() {
|
||||
start() {
|
||||
echo -n $"Starting fail2ban: "
|
||||
getpid
|
||||
if [ -z "$pid"]; then
|
||||
if [ -z "$pid" ]; then
|
||||
$FAIL2BAN start > /dev/null
|
||||
RETVAL=$?
|
||||
fi
|
||||
@@ -48,6 +48,7 @@ stop() {
|
||||
if [ -n "$pid" ]; then
|
||||
$FAIL2BAN stop > /dev/null
|
||||
fi
|
||||
sleep 1
|
||||
getpid
|
||||
if [ -z "$pid" ]; then
|
||||
rm -f /var/lock/subsys/fail2ban
|
||||
@@ -77,8 +78,8 @@ case "$1" in
|
||||
fi
|
||||
;;
|
||||
restart)
|
||||
stop
|
||||
start
|
||||
stop
|
||||
;;
|
||||
*)
|
||||
echo $"Usage: $0 {start|stop|status|restart}"
|
||||
|
||||
+208
-34
@@ -1,12 +1,11 @@
|
||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.36.
|
||||
.TH FAIL2BAN-CLIENT "1" "November 2006" "fail2ban-client v0.7.4" "User Commands"
|
||||
.TH FAIL2BAN-CLIENT "1" "February 2007" "fail2ban-client v0.7.7" "User Commands"
|
||||
.SH NAME
|
||||
fail2ban-client \- configure and control the server
|
||||
.SH SYNOPSIS
|
||||
.B fail2ban-client
|
||||
[\fIOPTIONS\fR]... \fI<COMMAND>\fR
|
||||
.SH DESCRIPTION
|
||||
Fail2Ban v0.7.4 reads log file that contains password failure report
|
||||
[?1034hUsage: ../fail2ban\-client [OPTIONS] <COMMAND>
|
||||
.PP
|
||||
Fail2Ban v0.7.7 reads log file that contains password failure report
|
||||
and bans the corresponding IP addresses using firewall rules.
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
@@ -29,7 +28,7 @@ increase verbosity
|
||||
decrease verbosity
|
||||
.TP
|
||||
\fB\-x\fR
|
||||
force execution of the server
|
||||
force execution of the server (remove socket file)
|
||||
.TP
|
||||
\fB\-h\fR, \fB\-\-help\fR
|
||||
display this help message
|
||||
@@ -37,48 +36,223 @@ display this help message
|
||||
\fB\-V\fR, \fB\-\-version\fR
|
||||
print the version
|
||||
.SH COMMAND
|
||||
.IP
|
||||
BASIC
|
||||
.TP
|
||||
start
|
||||
start the server and the jails
|
||||
\fBstart\fR
|
||||
starts the server and the jails
|
||||
.TP
|
||||
reload
|
||||
reload the configuration
|
||||
\fBreload\fR
|
||||
reloads the configuration
|
||||
.TP
|
||||
stop
|
||||
stop all jails and terminate the server
|
||||
\fBstop\fR
|
||||
stops all jails and terminate the
|
||||
server
|
||||
.TP
|
||||
status
|
||||
get the current status
|
||||
\fBstatus\fR
|
||||
gets the current status of the
|
||||
server
|
||||
.TP
|
||||
set loglevel <LEVEL>
|
||||
set loglevel to <LEVEL>
|
||||
\fBping\fR
|
||||
tests if the server is alive
|
||||
.IP
|
||||
LOGGING
|
||||
.TP
|
||||
get loglevel
|
||||
get loglevel
|
||||
\fBset loglevel <LEVEL>\fR
|
||||
sets logging level to <LEVEL>. 0
|
||||
is minimal, 4 is debug
|
||||
.TP
|
||||
set logtarget <TARGET>
|
||||
set log target to <TARGET>
|
||||
\fBget loglevel\fR
|
||||
gets the logging level
|
||||
.TP
|
||||
get logtarget
|
||||
get log target
|
||||
\fBset logtarget <TARGET>\fR
|
||||
sets logging target to <TARGET>.
|
||||
Can be STDOUT, STDERR, SYSLOG or a
|
||||
file
|
||||
.TP
|
||||
add <JAIL> [BACKEND]
|
||||
create <JAIL> using [BACKEND]
|
||||
\fBget logtarget\fR
|
||||
gets logging target
|
||||
.IP
|
||||
JAIL CONTROL
|
||||
.TP
|
||||
set <JAIL> <CMD>
|
||||
set the <CMD> value for <JAIL>
|
||||
\fBadd <JAIL> <BACKEND>\fR
|
||||
creates <JAIL> using <BACKEND>
|
||||
.TP
|
||||
get <JAIL> <CMD>
|
||||
get the <CMD> value for <JAIL>
|
||||
\fBstart <JAIL>\fR
|
||||
starts the jail <JAIL>
|
||||
.TP
|
||||
start <JAIL>
|
||||
start <JAIL>
|
||||
\fBstop <JAIL>\fR
|
||||
stops the jail <JAIL>. The jail is
|
||||
removed
|
||||
.TP
|
||||
stop <JAIL>
|
||||
stop <JAIL>. The jail is removed
|
||||
\fBstatus <JAIL>\fR
|
||||
gets the current status of <JAIL>
|
||||
.IP
|
||||
JAIL CONFIGURATION
|
||||
.TP
|
||||
status <JAIL>
|
||||
get the current status of <JAIL>
|
||||
\fBset <JAIL> idle on|off\fR
|
||||
sets the idle state of <JAIL>
|
||||
.TP
|
||||
\fBset <JAIL> addignoreip <IP>\fR
|
||||
adds <IP> to the ignore list of
|
||||
<JAIL>
|
||||
.TP
|
||||
\fBset <JAIL> delignoreip <IP>\fR
|
||||
removes <IP> from the ignore list
|
||||
of <JAIL>
|
||||
.TP
|
||||
\fBset <JAIL> addlogpath <FILE>\fR
|
||||
adds <FILE> to the monitoring list
|
||||
of <JAIL>
|
||||
.TP
|
||||
\fBset <JAIL> dellogpath <FILE>\fR
|
||||
removes <FILE> to the monitoring
|
||||
list of <JAIL>
|
||||
.TP
|
||||
\fBset <JAIL> timeregex <REGEX>\fR
|
||||
sets the regular expression
|
||||
<REGEX> to match the date format
|
||||
for <JAIL>. This will disable the
|
||||
autodetection feature.
|
||||
.TP
|
||||
\fBset <JAIL> timepattern <PATTERN>\fR
|
||||
sets the pattern <PATTERN> to
|
||||
match the date format for <JAIL>.
|
||||
This will disable the
|
||||
autodetection feature.
|
||||
.TP
|
||||
\fBset <JAIL> addfailregex <REGEX>\fR
|
||||
adds the regular expression
|
||||
<REGEX> which must match failures
|
||||
for <JAIL>
|
||||
.TP
|
||||
\fBset <JAIL> delfailregex <INDEX>\fR
|
||||
removes the regular expression at
|
||||
<INDEX> for failregex
|
||||
.TP
|
||||
\fBset <JAIL> addignoreregex <REGEX>\fR
|
||||
adds the regular expression
|
||||
<REGEX> which should match pattern
|
||||
to exclude for <JAIL>
|
||||
.TP
|
||||
\fBset <JAIL> delignoreregex <INDEX>\fR
|
||||
removes the regular expression at
|
||||
<INDEX> for ignoreregex
|
||||
.TP
|
||||
\fBset <JAIL> findtime <TIME>\fR
|
||||
sets the number of seconds <TIME>
|
||||
for which the filter will look
|
||||
back for <JAIL>
|
||||
.TP
|
||||
\fBset <JAIL> bantime <TIME>\fR
|
||||
sets the number of seconds <TIME>
|
||||
a host will be banned for <JAIL>
|
||||
.TP
|
||||
\fBset <JAIL> maxretry <RETRY>\fR
|
||||
sets the number of failures
|
||||
<RETRY> before banning the host
|
||||
for <JAIL>
|
||||
.TP
|
||||
\fBset <JAIL> addaction <ACT>\fR
|
||||
adds a new action named <NAME> for
|
||||
<JAIL>
|
||||
.TP
|
||||
\fBset <JAIL> delaction <ACT>\fR
|
||||
removes the action <NAME> from
|
||||
<JAIL>
|
||||
.TP
|
||||
\fBset <JAIL> setcinfo <ACT> <KEY> <VALUE>\fR
|
||||
sets <VALUE> for <KEY> of the
|
||||
action <NAME> for <JAIL>
|
||||
.TP
|
||||
\fBset <JAIL> delcinfo <ACT> <KEY>\fR
|
||||
removes <KEY> for the action
|
||||
<NAME> for <JAIL>
|
||||
.TP
|
||||
\fBset <JAIL> actionstart <ACT> <CMD>\fR
|
||||
sets the start command <CMD> of
|
||||
the action <ACT> for <JAIL>
|
||||
.TP
|
||||
\fBset <JAIL> actionstop <ACT> <CMD>\fR
|
||||
sets the stop command <CMD> of the
|
||||
action <ACT> for <JAIL>
|
||||
.TP
|
||||
\fBset <JAIL> actioncheck <ACT> <CMD>\fR
|
||||
sets the check command <CMD> of
|
||||
the action <ACT> for <JAIL>
|
||||
.TP
|
||||
\fBset <JAIL> actionban <ACT> <CMD>\fR
|
||||
sets the ban command <CMD> of the
|
||||
action <ACT> for <JAIL>
|
||||
.TP
|
||||
\fBset <JAIL> actionunban <ACT> <CMD>\fR
|
||||
sets the unban command <CMD> of
|
||||
the action <ACT> for <JAIL>
|
||||
.IP
|
||||
JAIL INFORMATION
|
||||
.TP
|
||||
\fBget <JAIL> logpath\fR
|
||||
gets the list of the monitored
|
||||
files for <JAIL>
|
||||
.TP
|
||||
\fBget <JAIL> ignoreip\fR
|
||||
gets the list of ignored IP
|
||||
addresses for <JAIL>
|
||||
.TP
|
||||
\fBget <JAIL> timeregex\fR
|
||||
gets the regular expression used
|
||||
for the time detection for <JAIL>
|
||||
.TP
|
||||
\fBget <JAIL> timepattern\fR
|
||||
gets the pattern used for the time
|
||||
detection for <JAIL>
|
||||
.TP
|
||||
\fBget <JAIL> failregex\fR
|
||||
gets the list of regular
|
||||
expressions which matches the
|
||||
failures for <JAIL>
|
||||
.TP
|
||||
\fBget <JAIL> ignoreregex\fR
|
||||
gets the list of regular
|
||||
expressions which matches patterns
|
||||
to ignore for <JAIL>
|
||||
.TP
|
||||
\fBget <JAIL> findtime\fR
|
||||
gets the time for which the filter
|
||||
will look back for failures for
|
||||
<JAIL>
|
||||
.TP
|
||||
\fBget <JAIL> bantime\fR
|
||||
gets the time a host is banned for
|
||||
<JAIL>
|
||||
.TP
|
||||
\fBget <JAIL> maxretry\fR
|
||||
gets the number of failures
|
||||
allowed for <JAIL>
|
||||
.TP
|
||||
\fBget <JAIL> addaction\fR
|
||||
gets the last action which has
|
||||
been added for <JAIL>
|
||||
.TP
|
||||
\fBget <JAIL> actionstart <ACT>\fR
|
||||
gets the start command for the
|
||||
action <ACT> for <JAIL>
|
||||
.TP
|
||||
\fBget <JAIL> actionstop <ACT>\fR
|
||||
gets the stop command for the
|
||||
action <ACT> for <JAIL>
|
||||
.TP
|
||||
\fBget <JAIL> actioncheck <ACT>\fR
|
||||
gets the check command for the
|
||||
action <ACT> for <JAIL>
|
||||
.TP
|
||||
\fBget <JAIL> actionban <ACT>\fR
|
||||
gets the ban command for the
|
||||
action <ACT> for <JAIL>
|
||||
.TP
|
||||
\fBget <JAIL> actionunban <ACT>\fR
|
||||
gets the unban command for the
|
||||
action <ACT> for <JAIL>
|
||||
.SH FILES
|
||||
\fI/etc/fail2ban/*\fR
|
||||
.SH AUTHOR
|
||||
|
||||
+25
-5
@@ -1,16 +1,36 @@
|
||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.36.
|
||||
.TH FAIL2BAN-REGEX "1" "November 2006" "fail2ban-regex v0.7.4" "User Commands"
|
||||
.TH FAIL2BAN-REGEX "1" "February 2007" "fail2ban-regex v0.7.7" "User Commands"
|
||||
.SH NAME
|
||||
fail2ban-regex \- test Fail2ban "failregex" option
|
||||
.SH SYNOPSIS
|
||||
.B fail2ban-regex
|
||||
\fI<logline> <failregex>\fR
|
||||
[\fIOPTIONS\fR] \fI<LOG> <REGEX>\fR
|
||||
.SH DESCRIPTION
|
||||
Fail2Ban v0.7.4 reads log file that contains password failure report
|
||||
Fail2Ban v0.7.7 reads log file that contains password failure report
|
||||
and bans the corresponding IP addresses using firewall rules.
|
||||
.PP
|
||||
This tools can test and benchmark your regular expressions for the "failregex"
|
||||
option.
|
||||
This tools can test regular expressions for "fail2ban".
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
\fB\-h\fR, \fB\-\-help\fR
|
||||
display this help message
|
||||
.TP
|
||||
\fB\-V\fR, \fB\-\-version\fR
|
||||
print the version
|
||||
.SH LOG
|
||||
.TP
|
||||
\fBstring\fR
|
||||
a string representing a log line
|
||||
.TP
|
||||
\fBfilename\fR
|
||||
path to a log file (/var/log/auth.log)
|
||||
.SH REGEX
|
||||
.TP
|
||||
\fBstring\fR
|
||||
a string representing a 'failregex'
|
||||
.TP
|
||||
\fBfilename\fR
|
||||
path to a filter file (filter.d/sshd.conf)
|
||||
.SH AUTHOR
|
||||
Written by Cyril Jaquier <lostcontrol@users.sourceforge.net>.
|
||||
Many contributions by Yaroslav O. Halchenko <debian@onerussian.com>.
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.36.
|
||||
.TH FAIL2BAN-SERVER "1" "November 2006" "fail2ban-server v0.7.4" "User Commands"
|
||||
.TH FAIL2BAN-SERVER "1" "February 2007" "fail2ban-server v0.7.7" "User Commands"
|
||||
.SH NAME
|
||||
fail2ban-server \- start the server
|
||||
.SH SYNOPSIS
|
||||
.B fail2ban-server
|
||||
[\fIOPTIONS\fR]
|
||||
.SH DESCRIPTION
|
||||
Fail2Ban v0.7.4 reads log file that contains password failure report
|
||||
Fail2Ban v0.7.7 reads log file that contains password failure report
|
||||
and bans the corresponding IP addresses using firewall rules.
|
||||
.PP
|
||||
Only use this command for debugging purpose. Start the server with
|
||||
fail2ban\-client instead.
|
||||
fail2ban\-client instead. The default behaviour is to start the server
|
||||
in background.
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
\fB\-b\fR
|
||||
@@ -23,7 +24,7 @@ start in foreground
|
||||
socket path
|
||||
.TP
|
||||
\fB\-x\fR
|
||||
force execution of the server
|
||||
force execution of the server (remove socket file)
|
||||
.TP
|
||||
\fB\-h\fR, \fB\-\-help\fR
|
||||
display this help message
|
||||
|
||||
+50
-1
@@ -5,7 +5,30 @@ echo -n "Generating fail2ban-client "
|
||||
help2man --section=1 --no-info --include=fail2ban-client.h2m --output fail2ban-client.1 ../fail2ban-client
|
||||
echo "[done]"
|
||||
echo -n "Patching fail2ban-client "
|
||||
# Changes the title.
|
||||
sed -i -e 's/.SS "Command:"/.SH COMMAND/' fail2ban-client.1
|
||||
# Sets bold font for commands.
|
||||
IFS="
|
||||
"
|
||||
NEXT=0
|
||||
FOUND=0
|
||||
LINES=$( cat fail2ban-client.1 )
|
||||
echo -n "" > fail2ban-client.1
|
||||
for LINE in $LINES; do
|
||||
if [ "$LINE" = ".SH COMMAND" ]; then
|
||||
FOUND=1
|
||||
fi
|
||||
if [ $NEXT -eq 1 ] && [ $FOUND -eq 1 ]; then
|
||||
echo "\fB$LINE\fR" >> fail2ban-client.1
|
||||
else
|
||||
echo "$LINE" >> fail2ban-client.1
|
||||
fi
|
||||
if [ "$LINE" = ".TP" ]; then
|
||||
NEXT=1
|
||||
else
|
||||
NEXT=0
|
||||
fi
|
||||
done
|
||||
echo "[done]"
|
||||
|
||||
# fail2ban-server
|
||||
@@ -17,4 +40,30 @@ echo "[done]"
|
||||
echo -n "Generating fail2ban-regex "
|
||||
help2man --section=1 --no-info --include=fail2ban-regex.h2m --output fail2ban-regex.1 ../fail2ban-regex
|
||||
echo "[done]"
|
||||
|
||||
echo -n "Patching fail2ban-regex "
|
||||
# Changes the title.
|
||||
sed -i -e 's/.SS "Log:"/.SH LOG/' fail2ban-regex.1
|
||||
sed -i -e 's/.SS "Regex:"/.SH REGEX/' fail2ban-regex.1
|
||||
# Sets bold font for commands.
|
||||
IFS="
|
||||
"
|
||||
NEXT=0
|
||||
FOUND=0
|
||||
LINES=$( cat fail2ban-regex.1 )
|
||||
echo -n "" > fail2ban-regex.1
|
||||
for LINE in $LINES; do
|
||||
if [ "$LINE" = ".SH LOG" ]; then
|
||||
FOUND=1
|
||||
fi
|
||||
if [ $NEXT -eq 1 ] && [ $FOUND -eq 1 ]; then
|
||||
echo "\fB$LINE\fR" >> fail2ban-regex.1
|
||||
else
|
||||
echo "$LINE" >> fail2ban-regex.1
|
||||
fi
|
||||
if [ "$LINE" = ".TP" ]; then
|
||||
NEXT=1
|
||||
else
|
||||
NEXT=0
|
||||
fi
|
||||
done
|
||||
echo "[done]"
|
||||
|
||||
+30
-18
@@ -134,11 +134,15 @@ class Actions(JailThread):
|
||||
bTicket = BanManager.createBanTicket(ticket)
|
||||
aInfo["ip"] = bTicket.getIP()
|
||||
aInfo["failures"] = bTicket.getAttempt()
|
||||
logSys.warn("[%s] Ban %s" % (self.jail.getName(), aInfo["ip"]))
|
||||
for action in self.__actions:
|
||||
action.execActionBan(aInfo)
|
||||
self.__banManager.addBanTicket(bTicket)
|
||||
return True
|
||||
aInfo["time"] = bTicket.getTime()
|
||||
if self.__banManager.addBanTicket(bTicket):
|
||||
logSys.warn("[%s] Ban %s" % (self.jail.getName(), aInfo["ip"]))
|
||||
for action in self.__actions:
|
||||
action.execActionBan(aInfo)
|
||||
return True
|
||||
else:
|
||||
logSys.warn("[%s] %s already banned" % (self.jail.getName(),
|
||||
aInfo["ip"]))
|
||||
return False
|
||||
|
||||
##
|
||||
@@ -148,11 +152,7 @@ class Actions(JailThread):
|
||||
|
||||
def __checkUnBan(self):
|
||||
for ticket in self.__banManager.unBanList(MyTime.time()):
|
||||
aInfo = dict()
|
||||
aInfo["ip"] = ticket.getIP()
|
||||
logSys.warn("[%s] Unban %s" % (self.jail.getName(), aInfo["ip"]))
|
||||
for action in self.__actions:
|
||||
action.execActionUnban(aInfo)
|
||||
self.__unBan(ticket)
|
||||
|
||||
##
|
||||
# Flush the ban list.
|
||||
@@ -162,11 +162,23 @@ class Actions(JailThread):
|
||||
def __flushBan(self):
|
||||
logSys.debug("Flush ban list")
|
||||
for ticket in self.__banManager.flushBanList():
|
||||
aInfo = dict()
|
||||
aInfo["ip"] = ticket.getIP()
|
||||
logSys.warn("[%s] Unban %s" % (self.jail.getName(), aInfo["ip"]))
|
||||
for action in self.__actions:
|
||||
action.execActionUnban(aInfo)
|
||||
self.__unBan(ticket)
|
||||
|
||||
##
|
||||
# Unbans host corresponding to the ticket.
|
||||
#
|
||||
# Executes the actions in order to unban the host given in the
|
||||
# ticket.
|
||||
|
||||
def __unBan(self, ticket):
|
||||
aInfo = dict()
|
||||
aInfo["ip"] = ticket.getIP()
|
||||
aInfo["failures"] = ticket.getAttempt()
|
||||
aInfo["time"] = ticket.getTime()
|
||||
logSys.warn("[%s] Unban %s" % (self.jail.getName(), aInfo["ip"]))
|
||||
for action in self.__actions:
|
||||
action.execActionUnban(aInfo)
|
||||
|
||||
|
||||
##
|
||||
# Get the status of the filter.
|
||||
@@ -176,7 +188,7 @@ class Actions(JailThread):
|
||||
# @return a list with tuple
|
||||
|
||||
def status(self):
|
||||
ret = [("Currently banned", self.__banManager.size()),
|
||||
("Total banned", self.__banManager.getBanTotal())]
|
||||
ret = [("Currently banned", self.__banManager.size()),
|
||||
("Total banned", self.__banManager.getBanTotal()),
|
||||
("IP list", self.__banManager.getBanList())]
|
||||
return ret
|
||||
|
||||
+23
-16
@@ -100,7 +100,19 @@ class BanManager:
|
||||
return self.__banTotal
|
||||
finally:
|
||||
self.__lock.release()
|
||||
|
||||
##
|
||||
# Returns a copy of the IP list.
|
||||
#
|
||||
# @return IP list
|
||||
|
||||
def getBanList(self):
|
||||
try:
|
||||
self.__lock.acquire()
|
||||
return [m.getIP() for m in self.__banList]
|
||||
finally:
|
||||
self.__lock.release()
|
||||
|
||||
##
|
||||
# Create a ban ticket.
|
||||
#
|
||||
@@ -136,14 +148,6 @@ class BanManager:
|
||||
finally:
|
||||
self.__lock.release()
|
||||
|
||||
##
|
||||
# Delete a ban ticket.
|
||||
#
|
||||
# Remove a BanTicket from the ban list.
|
||||
# @param ticket the ticket
|
||||
|
||||
def __delBanTicket(self, ticket):
|
||||
self.__banList.remove(ticket)
|
||||
|
||||
##
|
||||
# Get the size of the ban list.
|
||||
@@ -177,20 +181,23 @@ class BanManager:
|
||||
# Return a list of BanTicket which need to be unbanned.
|
||||
# @param time the time
|
||||
# @return the list of ticket to unban
|
||||
# @todo Check the delete operation
|
||||
|
||||
def unBanList(self, time):
|
||||
try:
|
||||
self.__lock.acquire()
|
||||
uBList = list()
|
||||
# Permanent banning
|
||||
if self.__banTime < 0:
|
||||
return uBList
|
||||
for ticket in self.__banList:
|
||||
if ticket.getTime() < time - self.__banTime:
|
||||
uBList.append(ticket)
|
||||
self.__delBanTicket(ticket)
|
||||
return uBList
|
||||
return list()
|
||||
|
||||
# Gets the list of ticket to remove.
|
||||
unBanList = [ticket for ticket in self.__banList
|
||||
if ticket.getTime() < time - self.__banTime]
|
||||
|
||||
# Removes tickets.
|
||||
self.__banList = [ticket for ticket in self.__banList
|
||||
if ticket not in unBanList]
|
||||
|
||||
return unBanList
|
||||
finally:
|
||||
self.__lock.release()
|
||||
|
||||
|
||||
+10
-5
@@ -16,17 +16,16 @@
|
||||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 321 $
|
||||
# $Revision$
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 321 $"
|
||||
__date__ = "$Date: 2006-09-04 21:19:58 +0200 (Mon, 04 Sep 2006) $"
|
||||
__version__ = "$Revision$"
|
||||
__date__ = "$Date$"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
import time, logging
|
||||
|
||||
from datetemplate import DateTemplate
|
||||
from datestrptime import DateStrptime
|
||||
from datetai64n import DateTai64n
|
||||
from dateepoch import DateEpoch
|
||||
@@ -40,7 +39,7 @@ class DateDetector:
|
||||
def __init__(self):
|
||||
self.__lock = Lock()
|
||||
self.__templates = list()
|
||||
self.__defTemplate = DateTemplate()
|
||||
self.__defTemplate = DateStrptime()
|
||||
|
||||
def addDefaultTemplate(self):
|
||||
# standard
|
||||
@@ -67,6 +66,12 @@ class DateDetector:
|
||||
template.setRegex("\d{2}/\S{3}/\d{4}:\d{2}:\d{2}:\d{2}")
|
||||
template.setPattern("%d/%b/%Y:%H:%M:%S")
|
||||
self.__templates.append(template)
|
||||
# Exim 2006-12-21 06:43:20
|
||||
template = DateStrptime()
|
||||
template.setName("Year-Month-Day Hour:Minute:Second")
|
||||
template.setRegex("\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}")
|
||||
template.setPattern("%Y-%m-%d %H:%M:%S")
|
||||
self.__templates.append(template)
|
||||
# TAI64N
|
||||
template = DateTai64n()
|
||||
template.setName("TAI64N")
|
||||
|
||||
+3
-3
@@ -16,11 +16,11 @@
|
||||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 321 $
|
||||
# $Revision$
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 321 $"
|
||||
__date__ = "$Date: 2006-09-04 21:19:58 +0200 (Mon, 04 Sep 2006) $"
|
||||
__version__ = "$Revision$"
|
||||
__date__ = "$Date$"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 321 $
|
||||
# $Revision$
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 321 $"
|
||||
__date__ = "$Date: 2006-09-04 21:19:58 +0200 (Mon, 04 Sep 2006) $"
|
||||
__version__ = "$Revision$"
|
||||
__date__ = "$Date$"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 321 $
|
||||
# $Revision$
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 321 $"
|
||||
__date__ = "$Date: 2006-09-04 21:19:58 +0200 (Mon, 04 Sep 2006) $"
|
||||
__version__ = "$Revision$"
|
||||
__date__ = "$Date$"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 321 $
|
||||
# $Revision$
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 321 $"
|
||||
__date__ = "$Date: 2006-09-04 21:19:58 +0200 (Mon, 04 Sep 2006) $"
|
||||
__version__ = "$Revision$"
|
||||
__date__ = "$Date$"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
@@ -42,14 +42,14 @@ class DateTemplate:
|
||||
return self.__name
|
||||
|
||||
def setRegex(self, regex):
|
||||
self.__regex = regex
|
||||
self.__regex = regex.strip()
|
||||
self.__cRegex = re.compile(regex)
|
||||
|
||||
def getRegex(self):
|
||||
return self.__regex
|
||||
|
||||
def setPattern(self, pattern):
|
||||
self.__pattern = pattern
|
||||
self.__pattern = pattern.strip()
|
||||
|
||||
def getPattern(self):
|
||||
return self.__pattern
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
# This file is part of Fail2Ban.
|
||||
#
|
||||
# Fail2Ban is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Fail2Ban is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Fail2Ban; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision$
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision$"
|
||||
__date__ = "$Date$"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
from regex import Regex, RegexException
|
||||
|
||||
##
|
||||
# Regular expression class.
|
||||
#
|
||||
# This class represents a regular expression with its compiled version.
|
||||
|
||||
class FailRegex(Regex):
|
||||
|
||||
##
|
||||
# Constructor.
|
||||
#
|
||||
# Creates a new object. This method can throw RegexException in order to
|
||||
# avoid construction of invalid object.
|
||||
# @param value the regular expression
|
||||
|
||||
def __init__(self, value):
|
||||
# Replace "<HOST>" with default regular expression for host.
|
||||
regex = value.replace("<HOST>", "(?:::f{4,6}:)?(?P<host>\S+)")
|
||||
# Initializes the parent.
|
||||
Regex.__init__(self, regex)
|
||||
# Check for group "host"
|
||||
if "host" not in self._regexObj.groupindex:
|
||||
raise RegexException("No 'host' group in '%s'" % self._regex)
|
||||
|
||||
##
|
||||
# Returns the matched host.
|
||||
#
|
||||
# This corresponds to the pattern matched by the named group "host".
|
||||
# @return the matched host
|
||||
|
||||
def getHost(self):
|
||||
host = self._matchCache.group("host")
|
||||
if host == None:
|
||||
raise RegexException("Unexpected error. Please check your regex")
|
||||
return host
|
||||
+85
-46
@@ -29,8 +29,10 @@ from failticket import FailTicket
|
||||
from jailthread import JailThread
|
||||
from datedetector import DateDetector
|
||||
from mytime import MyTime
|
||||
from regex import Regex, RegexException
|
||||
from failregex import FailRegex
|
||||
|
||||
import logging, re, sre_constants
|
||||
import logging, re
|
||||
|
||||
# Gets the instance of the logger.
|
||||
logSys = logging.getLogger("fail2ban.filter")
|
||||
@@ -56,15 +58,15 @@ class Filter(JailThread):
|
||||
self.jail = jail
|
||||
## The failures manager.
|
||||
self.failManager = FailManager()
|
||||
self.modified = False
|
||||
## The log file handler.
|
||||
self.__crtHandler = None
|
||||
self.__crtFilename = None
|
||||
## The log file path.
|
||||
self.__logPath = []
|
||||
## The regular expression matching the failure.
|
||||
self.__failRegex = ''
|
||||
self.__failRegexObj = None
|
||||
## The regular expression list matching the failures.
|
||||
self.__failRegex = list()
|
||||
## The regular expression list with expressions to ignore.
|
||||
self.__ignoreRegex = list()
|
||||
## The amount of time to look back.
|
||||
self.__findTime = 6000
|
||||
## The ignore IP list.
|
||||
@@ -156,19 +158,26 @@ class Filter(JailThread):
|
||||
return self.dateDetector.getDefaultPattern()
|
||||
|
||||
##
|
||||
# Set the regular expression which matches the failure.
|
||||
# Add a regular expression which matches the failure.
|
||||
#
|
||||
# The regular expression can also match any other pattern than failures
|
||||
# and thus can be used for many purporse.
|
||||
# @param value the regular expression
|
||||
|
||||
def setFailRegex(self, value):
|
||||
def addFailRegex(self, value):
|
||||
try:
|
||||
self.__failRegexObj = re.compile(value)
|
||||
self.__failRegex = value
|
||||
logSys.info("Set failregex = %s" % value)
|
||||
except sre_constants.error:
|
||||
logSys.error("Unable to compile regular expression " + value)
|
||||
regex = FailRegex(value)
|
||||
self.__failRegex.append(regex)
|
||||
except RegexException, e:
|
||||
logSys.error(e)
|
||||
|
||||
|
||||
def delFailRegex(self, index):
|
||||
try:
|
||||
del self.__failRegex[index]
|
||||
except IndexError:
|
||||
logSys.error("Cannot remove regular expression. Index %d is not "
|
||||
"valid" % index)
|
||||
|
||||
##
|
||||
# Get the regular expression which matches the failure.
|
||||
@@ -176,7 +185,42 @@ class Filter(JailThread):
|
||||
# @return the regular expression
|
||||
|
||||
def getFailRegex(self):
|
||||
return self.__failRegex
|
||||
failRegex = list()
|
||||
for regex in self.__failRegex:
|
||||
failRegex.append(regex.getRegex())
|
||||
return failRegex
|
||||
|
||||
##
|
||||
# Add the regular expression which matches the failure.
|
||||
#
|
||||
# The regular expression can also match any other pattern than failures
|
||||
# and thus can be used for many purporse.
|
||||
# @param value the regular expression
|
||||
|
||||
def addIgnoreRegex(self, value):
|
||||
try:
|
||||
regex = Regex(value)
|
||||
self.__ignoreRegex.append(regex)
|
||||
except RegexException, e:
|
||||
logSys.error(e)
|
||||
|
||||
def delIgnoreRegex(self, index):
|
||||
try:
|
||||
del self.__ignoreRegex[index]
|
||||
except IndexError:
|
||||
logSys.error("Cannot remove regular expression. Index %d is not "
|
||||
"valid" % index)
|
||||
|
||||
##
|
||||
# Get the regular expression which matches the failure.
|
||||
#
|
||||
# @return the regular expression
|
||||
|
||||
def getIgnoreRegex(self):
|
||||
ignoreRegex = list()
|
||||
for regex in self.__ignoreRegex:
|
||||
ignoreRegex.append(regex.getRegex())
|
||||
return ignoreRegex
|
||||
|
||||
##
|
||||
# Set the time needed to find a failure.
|
||||
@@ -187,6 +231,7 @@ class Filter(JailThread):
|
||||
|
||||
def setFindTime(self, value):
|
||||
self.__findTime = value
|
||||
self.failManager.setMaxTime(value)
|
||||
logSys.info("Set findtime = %s" % value)
|
||||
|
||||
##
|
||||
@@ -214,23 +259,6 @@ class Filter(JailThread):
|
||||
def getMaxRetry(self):
|
||||
return self.failManager.getMaxRetry()
|
||||
|
||||
##
|
||||
# Set the maximum time a failure stays in the list.
|
||||
#
|
||||
# @param value the maximum time
|
||||
|
||||
def setMaxTime(self, value):
|
||||
self.failManager.setMaxTime(value)
|
||||
logSys.info("Set maxTime = %s" % value)
|
||||
|
||||
##
|
||||
# Get the maximum time a failure stays in the list.
|
||||
#
|
||||
# @return the time value
|
||||
|
||||
def getMaxTime(self):
|
||||
return self.failManager.getMaxTime()
|
||||
|
||||
##
|
||||
# Main loop.
|
||||
#
|
||||
@@ -350,8 +378,8 @@ class Filter(JailThread):
|
||||
# is created and is added to the FailManager.
|
||||
|
||||
def getFailures(self, filename):
|
||||
ret = self.__openLogFile(filename)
|
||||
if not ret:
|
||||
# Try to open log file.
|
||||
if not self.__openLogFile(filename):
|
||||
logSys.error("Unable to get failures in " + filename)
|
||||
return False
|
||||
self.__setFilePos()
|
||||
@@ -394,26 +422,35 @@ class Filter(JailThread):
|
||||
|
||||
def findFailure(self, line):
|
||||
failList = list()
|
||||
if self.__failRegexObj == None:
|
||||
logSys.error("No failregex is set")
|
||||
else:
|
||||
match = self.__failRegexObj.search(line)
|
||||
if match:
|
||||
date = self.dateDetector.getUnixTime(match.string)
|
||||
# Checks if we must ignore this line.
|
||||
for ignoreRegex in self.__ignoreRegex:
|
||||
ignoreRegex.search(line)
|
||||
if ignoreRegex.hasMatched():
|
||||
# The ignoreregex matched. Return.
|
||||
logSys.debug("Ignoring this line")
|
||||
return failList
|
||||
# Iterates over all the regular expressions.
|
||||
for failRegex in self.__failRegex:
|
||||
failRegex.search(line)
|
||||
if failRegex.hasMatched():
|
||||
# The failregex matched.
|
||||
date = self.dateDetector.getUnixTime(line)
|
||||
if date == None:
|
||||
logSys.debug("Found a match but no valid date/time found "
|
||||
+ "for " + match.string + ". Please contact "
|
||||
+ "the author in order to get support for "
|
||||
+ "this format")
|
||||
+ "for " + line + ". Please contact the "
|
||||
+ "author in order to get support for this "
|
||||
+ "format")
|
||||
else:
|
||||
try:
|
||||
ipMatch = DNSUtils.textToIp(match.group("host"))
|
||||
host = failRegex.getHost()
|
||||
ipMatch = DNSUtils.textToIp(host)
|
||||
if ipMatch:
|
||||
for ip in ipMatch:
|
||||
failList.append([ip, date])
|
||||
except IndexError:
|
||||
logSys.error("There is no 'host' group in the rule. " +
|
||||
"Please correct your configuration.")
|
||||
# We matched a regex, it is enough to stop.
|
||||
break
|
||||
except RegexException, e:
|
||||
logSys.error(e)
|
||||
return failList
|
||||
|
||||
|
||||
@@ -425,7 +462,7 @@ class Filter(JailThread):
|
||||
# @return a list with tuple
|
||||
|
||||
def status(self):
|
||||
ret = [("Currently failed", self.failManager.size()),
|
||||
ret = [("Currently failed", self.failManager.size()),
|
||||
("Total failed", self.failManager.getFailTotal())]
|
||||
return ret
|
||||
|
||||
@@ -451,6 +488,8 @@ class DNSUtils:
|
||||
try:
|
||||
return socket.gethostbyname_ex(dns)[2]
|
||||
except socket.gaierror:
|
||||
logSys.warn("Unable to find a corresponding IP address for %s"
|
||||
% dns)
|
||||
return list()
|
||||
|
||||
@staticmethod
|
||||
|
||||
@@ -50,6 +50,7 @@ class FilterGamin(Filter):
|
||||
|
||||
def __init__(self, jail):
|
||||
Filter.__init__(self, jail)
|
||||
self.__modified = False
|
||||
# Gamin monitor
|
||||
self.monitor = gamin.WatchMonitor()
|
||||
logSys.info("Created FilterGamin")
|
||||
@@ -60,7 +61,7 @@ class FilterGamin(Filter):
|
||||
if event in (gamin.GAMCreated, gamin.GAMChanged, gamin.GAMExists):
|
||||
logSys.debug("File changed: " + path)
|
||||
self.getFailures(path)
|
||||
self.modified = True
|
||||
self.__modified = True
|
||||
|
||||
|
||||
##
|
||||
@@ -105,14 +106,14 @@ class FilterGamin(Filter):
|
||||
if self.monitor.event_pending():
|
||||
self.monitor.handle_events()
|
||||
|
||||
if self.modified:
|
||||
if self.__modified:
|
||||
try:
|
||||
ticket = self.failManager.toBan()
|
||||
self.jail.putFailTicket(ticket)
|
||||
except FailManagerEmpty:
|
||||
self.failManager.cleanup(MyTime.time())
|
||||
self.dateDetector.sortTemplate()
|
||||
self.modified = False
|
||||
self.__modified = False
|
||||
time.sleep(self.getSleepTime())
|
||||
else:
|
||||
time.sleep(self.getSleepTime())
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 354 $
|
||||
# $Revision$
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 354 $"
|
||||
__date__ = "$Date: 2006-09-13 23:31:22 +0200 (Wed, 13 Sep 2006) $"
|
||||
__version__ = "$Revision$"
|
||||
__date__ = "$Date$"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
@@ -50,6 +50,7 @@ class FilterPoll(Filter):
|
||||
|
||||
def __init__(self, jail):
|
||||
Filter.__init__(self, jail)
|
||||
self.__modified = False
|
||||
## The time of the last modification of the file.
|
||||
self.__lastModTime = dict()
|
||||
self.__file404Cnt = dict()
|
||||
@@ -98,16 +99,16 @@ class FilterPoll(Filter):
|
||||
for f in self.getLogPath():
|
||||
if self.isModified(f):
|
||||
self.getFailures(f)
|
||||
self.modified = True
|
||||
self.__modified = True
|
||||
|
||||
if self.modified:
|
||||
if self.__modified:
|
||||
try:
|
||||
ticket = self.failManager.toBan()
|
||||
self.jail.putFailTicket(ticket)
|
||||
except FailManagerEmpty:
|
||||
self.failManager.cleanup(MyTime.time())
|
||||
self.dateDetector.sortTemplate()
|
||||
self.modified = False
|
||||
self.__modified = False
|
||||
time.sleep(self.getSleepTime())
|
||||
else:
|
||||
time.sleep(self.getSleepTime())
|
||||
|
||||
+15
-55
@@ -27,7 +27,6 @@ __license__ = "GPL"
|
||||
import Queue, logging
|
||||
|
||||
from actions import Actions
|
||||
from threading import Lock
|
||||
|
||||
# Gets the instance of the logger.
|
||||
logSys = logging.getLogger("fail2ban.jail")
|
||||
@@ -35,7 +34,6 @@ logSys = logging.getLogger("fail2ban.jail")
|
||||
class Jail:
|
||||
|
||||
def __init__(self, name, backend = "auto"):
|
||||
self.__lock = Lock()
|
||||
self.__name = name
|
||||
self.__queue = Queue.Queue()
|
||||
self.__filter = None
|
||||
@@ -61,89 +59,51 @@ class Jail:
|
||||
self.__filter = FilterGamin(self)
|
||||
|
||||
def setName(self, name):
|
||||
self.__lock.acquire()
|
||||
self.__name = name
|
||||
self.__lock.release()
|
||||
|
||||
def getName(self):
|
||||
try:
|
||||
self.__lock.acquire()
|
||||
return self.__name
|
||||
finally:
|
||||
self.__lock.release()
|
||||
return self.__name
|
||||
|
||||
def getFilter(self):
|
||||
try:
|
||||
self.__lock.acquire()
|
||||
return self.__filter
|
||||
finally:
|
||||
self.__lock.release()
|
||||
return self.__filter
|
||||
|
||||
def getAction(self):
|
||||
try:
|
||||
self.__lock.acquire()
|
||||
return self.__action
|
||||
finally:
|
||||
self.__lock.release()
|
||||
return self.__action
|
||||
|
||||
def putFailTicket(self, ticket):
|
||||
self.__lock.acquire()
|
||||
self.__queue.put(ticket)
|
||||
self.__lock.release()
|
||||
|
||||
def getFailTicket(self):
|
||||
try:
|
||||
self.__lock.acquire()
|
||||
try:
|
||||
return self.__queue.get(False)
|
||||
except Queue.Empty:
|
||||
return False
|
||||
finally:
|
||||
self.__lock.release()
|
||||
return self.__queue.get(False)
|
||||
except Queue.Empty:
|
||||
return False
|
||||
|
||||
def start(self):
|
||||
self.__lock.acquire()
|
||||
self.__filter.start()
|
||||
self.__action.start()
|
||||
self.__lock.release()
|
||||
|
||||
def stop(self):
|
||||
self.__lock.acquire()
|
||||
self.__filter.stop()
|
||||
self.__action.stop()
|
||||
self.__lock.release()
|
||||
self.__filter.join()
|
||||
self.__action.join()
|
||||
|
||||
def isActive(self):
|
||||
try:
|
||||
self.__lock.acquire()
|
||||
isActive0 = self.__filter.isActive()
|
||||
isActive1 = self.__action.isActive()
|
||||
return isActive0 or isActive1
|
||||
finally:
|
||||
self.__lock.release()
|
||||
isActive0 = self.__filter.isActive()
|
||||
isActive1 = self.__action.isActive()
|
||||
return isActive0 or isActive1
|
||||
|
||||
def setIdle(self, value):
|
||||
self.__lock.acquire()
|
||||
self.__filter.setIdle(value)
|
||||
self.__action.setIdle(value)
|
||||
self.__lock.release()
|
||||
|
||||
def getIdle(self):
|
||||
try:
|
||||
self.__lock.acquire()
|
||||
return self.__filter.getIdle() or self.__action.getIdle()
|
||||
finally:
|
||||
self.__lock.release()
|
||||
return self.__filter.getIdle() or self.__action.getIdle()
|
||||
|
||||
def getStatus(self):
|
||||
try:
|
||||
self.__lock.acquire()
|
||||
fStatus = self.__filter.status()
|
||||
aStatus = self.__action.status()
|
||||
ret = [("filter", fStatus),
|
||||
("action", aStatus)]
|
||||
return ret
|
||||
finally:
|
||||
self.__lock.release()
|
||||
fStatus = self.__filter.status()
|
||||
aStatus = self.__action.status()
|
||||
ret = [("filter", fStatus),
|
||||
("action", aStatus)]
|
||||
return ret
|
||||
|
||||
+73
-15
@@ -16,11 +16,11 @@
|
||||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 354 $
|
||||
# $Revision$
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 354 $"
|
||||
__date__ = "$Date: 2006-09-13 23:31:22 +0200 (Wed, 13 Sep 2006) $"
|
||||
__version__ = "$Revision$"
|
||||
__date__ = "$Date$"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
@@ -28,29 +28,63 @@ __license__ = "GPL"
|
||||
from jail import Jail
|
||||
from threading import Lock
|
||||
|
||||
##
|
||||
# Handles the jails.
|
||||
#
|
||||
# This class handles the jails. Creation, deletion or access to a jail must be
|
||||
# done through this class. This class is thread-safe which is not the case of
|
||||
# the jail itself, including filter and actions.
|
||||
|
||||
class Jails:
|
||||
|
||||
##
|
||||
# Constructor.
|
||||
|
||||
def __init__(self):
|
||||
self.__lock = Lock()
|
||||
self.__jails = dict()
|
||||
|
||||
##
|
||||
# Adds a jail.
|
||||
#
|
||||
# Adds a new jail which should use the given backend. Raises a
|
||||
# <code>DuplicateJailException</code> if the jail is already defined.
|
||||
# @param name The name of the jail
|
||||
# @param backend The backend to use
|
||||
|
||||
def add(self, name, backend):
|
||||
self.__lock.acquire()
|
||||
if self.__jails.has_key(name):
|
||||
self.__lock.release()
|
||||
raise DuplicateJailException(name)
|
||||
else:
|
||||
self.__jails[name] = Jail(name, backend)
|
||||
try:
|
||||
self.__lock.acquire()
|
||||
if self.__jails.has_key(name):
|
||||
raise DuplicateJailException(name)
|
||||
else:
|
||||
self.__jails[name] = Jail(name, backend)
|
||||
finally:
|
||||
self.__lock.release()
|
||||
|
||||
##
|
||||
# Removes a jail.
|
||||
#
|
||||
# Removes the jail <code>name</code>. Raise an <code>UnknownJailException</code>
|
||||
# if the jail does not exist.
|
||||
# @param name The name of the jail
|
||||
|
||||
def remove(self, name):
|
||||
self.__lock.acquire()
|
||||
if self.__jails.has_key(name):
|
||||
del self.__jails[name]
|
||||
try:
|
||||
self.__lock.acquire()
|
||||
if self.__jails.has_key(name):
|
||||
del self.__jails[name]
|
||||
else:
|
||||
raise UnknownJailException(name)
|
||||
finally:
|
||||
self.__lock.release()
|
||||
else:
|
||||
self.__lock.release()
|
||||
raise UnknownJailException(name)
|
||||
|
||||
##
|
||||
# Returns a jail.
|
||||
#
|
||||
# Returns the jail <code>name</code>. Raise an <code>UnknownJailException</code>
|
||||
# if the jail does not exist.
|
||||
# @param name The name of the jail
|
||||
|
||||
def get(self, name):
|
||||
try:
|
||||
@@ -63,6 +97,13 @@ class Jails:
|
||||
finally:
|
||||
self.__lock.release()
|
||||
|
||||
##
|
||||
# Returns an action class instance.
|
||||
#
|
||||
# Returns the action object of the jail <code>name</code>. Raise an
|
||||
# <code>UnknownJailException</code> if the jail does not exist.
|
||||
# @param name The name of the jail
|
||||
|
||||
def getAction(self, name):
|
||||
try:
|
||||
self.__lock.acquire()
|
||||
@@ -74,6 +115,13 @@ class Jails:
|
||||
finally:
|
||||
self.__lock.release()
|
||||
|
||||
##
|
||||
# Returns a filter class instance.
|
||||
#
|
||||
# Returns the filter object of the jail <code>name</code>. Raise an
|
||||
# <code>UnknownJailException</code> if the jail does not exist.
|
||||
# @param name The name of the jail
|
||||
|
||||
def getFilter(self, name):
|
||||
try:
|
||||
self.__lock.acquire()
|
||||
@@ -85,6 +133,11 @@ class Jails:
|
||||
finally:
|
||||
self.__lock.release()
|
||||
|
||||
##
|
||||
# Returns the jails.
|
||||
#
|
||||
# Returns a copy of the jails list.
|
||||
|
||||
def getAll(self):
|
||||
try:
|
||||
self.__lock.acquire()
|
||||
@@ -92,6 +145,11 @@ class Jails:
|
||||
finally:
|
||||
self.__lock.release()
|
||||
|
||||
##
|
||||
# Returns the size of the jails.
|
||||
#
|
||||
# Returns the number of jails.
|
||||
|
||||
def size(self):
|
||||
try:
|
||||
self.__lock.acquire()
|
||||
|
||||
+3
-3
@@ -16,11 +16,11 @@
|
||||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 321 $
|
||||
# $Revision$
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 321 $"
|
||||
__date__ = "$Date: 2006-09-04 21:19:58 +0200 (Mon, 04 Sep 2006) $"
|
||||
__version__ = "$Revision$"
|
||||
__date__ = "$Date$"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
# This file is part of Fail2Ban.
|
||||
#
|
||||
# Fail2Ban is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Fail2Ban is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Fail2Ban; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision$
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision$"
|
||||
__date__ = "$Date$"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
import re, sre_constants
|
||||
|
||||
##
|
||||
# Regular expression class.
|
||||
#
|
||||
# This class represents a regular expression with its compiled version.
|
||||
|
||||
class Regex:
|
||||
|
||||
##
|
||||
# Constructor.
|
||||
#
|
||||
# Creates a new object. This method can throw RegexException in order to
|
||||
# avoid construction of invalid object.
|
||||
# @param value the regular expression
|
||||
|
||||
def __init__(self, regex):
|
||||
self._matchCache = None
|
||||
if regex.lstrip() == '':
|
||||
raise RegexException("Cannot add empty regex")
|
||||
try:
|
||||
self._regexObj = re.compile(regex)
|
||||
self._regex = regex
|
||||
except sre_constants.error:
|
||||
raise RegexException("Unable to compile regular expression '%s'" %
|
||||
regex)
|
||||
|
||||
##
|
||||
# Gets the regular expression.
|
||||
#
|
||||
# The effective regular expression used is returned.
|
||||
# @return the regular expression
|
||||
|
||||
def getRegex(self):
|
||||
return self._regex
|
||||
|
||||
##
|
||||
# Searches the regular expression.
|
||||
#
|
||||
# Sets an internal cache (match object) in order to avoid searching for
|
||||
# the pattern again. This method must be called before calling any other
|
||||
# method of this object.
|
||||
# @param value the line
|
||||
|
||||
def search(self, value):
|
||||
self._matchCache = self._regexObj.search(value)
|
||||
|
||||
##
|
||||
# Checks if the previous call to search() matched.
|
||||
#
|
||||
# @return True if a match was found, False otherwise
|
||||
|
||||
def hasMatched(self):
|
||||
if self._matchCache:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
##
|
||||
# Exception dedicated to the class Regex.
|
||||
|
||||
class RegexException(Exception):
|
||||
pass
|
||||
+110
-60
@@ -24,6 +24,7 @@ __date__ = "$Date$"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
from threading import Lock, RLock
|
||||
from jails import Jails
|
||||
from transmitter import Transmitter
|
||||
from ssocket import SSocket
|
||||
@@ -36,6 +37,8 @@ logSys = logging.getLogger("fail2ban.server")
|
||||
class Server:
|
||||
|
||||
def __init__(self, daemon = False):
|
||||
self.__loggingLock = Lock()
|
||||
self.__lock = RLock()
|
||||
self.__jails = Jails()
|
||||
self.__daemon = daemon
|
||||
self.__transm = Transmitter(self)
|
||||
@@ -91,17 +94,29 @@ class Server:
|
||||
self.__jails.remove(name)
|
||||
|
||||
def startJail(self, name):
|
||||
if not self.isActive(name):
|
||||
self.__jails.get(name).start()
|
||||
try:
|
||||
self.__lock.acquire()
|
||||
if not self.isActive(name):
|
||||
self.__jails.get(name).start()
|
||||
finally:
|
||||
self.__lock.release()
|
||||
|
||||
def stopJail(self, name):
|
||||
if self.isActive(name):
|
||||
self.__jails.get(name).stop()
|
||||
self.delJail(name)
|
||||
try:
|
||||
self.__lock.acquire()
|
||||
if self.isActive(name):
|
||||
self.__jails.get(name).stop()
|
||||
self.delJail(name)
|
||||
finally:
|
||||
self.__lock.release()
|
||||
|
||||
def stopAllJail(self):
|
||||
for jail in self.__jails.getAll():
|
||||
self.stopJail(jail)
|
||||
try:
|
||||
self.__lock.acquire()
|
||||
for jail in self.__jails.getAll():
|
||||
self.stopJail(jail)
|
||||
finally:
|
||||
self.__lock.release()
|
||||
|
||||
def isActive(self, name):
|
||||
return self.__jails.get(name).isActive()
|
||||
@@ -150,24 +165,30 @@ class Server:
|
||||
def getFindTime(self, name):
|
||||
return self.__jails.getFilter(name).getFindTime()
|
||||
|
||||
def setFailRegex(self, name, value):
|
||||
self.__jails.getFilter(name).setFailRegex(value)
|
||||
def addFailRegex(self, name, value):
|
||||
self.__jails.getFilter(name).addFailRegex(value)
|
||||
|
||||
def delFailRegex(self, name, index):
|
||||
self.__jails.getFilter(name).delFailRegex(index)
|
||||
|
||||
def getFailRegex(self, name):
|
||||
return self.__jails.getFilter(name).getFailRegex()
|
||||
|
||||
def addIgnoreRegex(self, name, value):
|
||||
self.__jails.getFilter(name).addIgnoreRegex(value)
|
||||
|
||||
def delIgnoreRegex(self, name, index):
|
||||
self.__jails.getFilter(name).delIgnoreRegex(index)
|
||||
|
||||
def getIgnoreRegex(self, name):
|
||||
return self.__jails.getFilter(name).getIgnoreRegex()
|
||||
|
||||
def setMaxRetry(self, name, value):
|
||||
self.__jails.getFilter(name).setMaxRetry(value)
|
||||
|
||||
def getMaxRetry(self, name):
|
||||
return self.__jails.getFilter(name).getMaxRetry()
|
||||
|
||||
def setMaxTime(self, name, value):
|
||||
self.__jails.getFilter(name).setMaxTime(value)
|
||||
|
||||
def getMaxTime(self, name):
|
||||
return self.__jails.getFilter(name).getMaxTime()
|
||||
|
||||
# Action
|
||||
def addAction(self, name, value):
|
||||
self.__jails.getAction(name).addAction(value)
|
||||
@@ -225,15 +246,19 @@ class Server:
|
||||
|
||||
# Status
|
||||
def status(self):
|
||||
jailList = ''
|
||||
for jail in self.__jails.getAll():
|
||||
jailList += jail + ', '
|
||||
length = len(jailList)
|
||||
if not length == 0:
|
||||
jailList = jailList[:length-2]
|
||||
ret = [("Number of jail", self.__jails.size()),
|
||||
("Jail list", jailList)]
|
||||
return ret
|
||||
try:
|
||||
self.__lock.acquire()
|
||||
jailList = ''
|
||||
for jail in self.__jails.getAll():
|
||||
jailList += jail + ', '
|
||||
length = len(jailList)
|
||||
if not length == 0:
|
||||
jailList = jailList[:length-2]
|
||||
ret = [("Number of jail", self.__jails.size()),
|
||||
("Jail list", jailList)]
|
||||
return ret
|
||||
finally:
|
||||
self.__lock.release()
|
||||
|
||||
def statusJail(self, name):
|
||||
return self.__jails.get(name).getStatus()
|
||||
@@ -252,17 +277,21 @@ class Server:
|
||||
# @param value the level
|
||||
|
||||
def setLogLevel(self, value):
|
||||
self.__logLevel = value
|
||||
logLevel = logging.DEBUG
|
||||
if value == 0:
|
||||
logLevel = logging.FATAL
|
||||
elif value == 1:
|
||||
logLevel = logging.ERROR
|
||||
elif value == 2:
|
||||
logLevel = logging.WARNING
|
||||
elif value == 3:
|
||||
logLevel = logging.INFO
|
||||
logging.getLogger("fail2ban").setLevel(logLevel)
|
||||
try:
|
||||
self.__loggingLock.acquire()
|
||||
self.__logLevel = value
|
||||
logLevel = logging.DEBUG
|
||||
if value == 0:
|
||||
logLevel = logging.FATAL
|
||||
elif value == 1:
|
||||
logLevel = logging.ERROR
|
||||
elif value == 2:
|
||||
logLevel = logging.WARNING
|
||||
elif value == 3:
|
||||
logLevel = logging.INFO
|
||||
logging.getLogger("fail2ban").setLevel(logLevel)
|
||||
finally:
|
||||
self.__loggingLock.release()
|
||||
|
||||
##
|
||||
# Get the logging level.
|
||||
@@ -271,35 +300,56 @@ class Server:
|
||||
# @return the log level
|
||||
|
||||
def getLogLevel(self):
|
||||
return self.__logLevel
|
||||
try:
|
||||
self.__loggingLock.acquire()
|
||||
return self.__logLevel
|
||||
finally:
|
||||
self.__loggingLock.release()
|
||||
|
||||
##
|
||||
# Sets the logging target.
|
||||
#
|
||||
# target can be a file, SYSLOG, STDOUT or STDERR.
|
||||
# @param target the logging target
|
||||
|
||||
def setLogTarget(self, target):
|
||||
# Remove previous handler
|
||||
logging.getLogger("fail2ban").handlers = []
|
||||
self.__logTarget = target
|
||||
if target == "SYSLOG":
|
||||
hdlr = logging.handlers.SysLogHandler()
|
||||
elif target == "STDOUT":
|
||||
hdlr = logging.StreamHandler(sys.stdout)
|
||||
elif target == "STDERR":
|
||||
hdlr = logging.StreamHandler(sys.stderr)
|
||||
else:
|
||||
# Target should be a file
|
||||
try:
|
||||
open(target, "a")
|
||||
hdlr = logging.FileHandler(target)
|
||||
except IOError:
|
||||
logSys.error("Unable to log to " + target)
|
||||
return False
|
||||
# set a format which is simpler for console use
|
||||
formatter = logging.Formatter("%(asctime)s %(name)-16s: %(levelname)-6s %(message)s")
|
||||
# tell the handler to use this format
|
||||
hdlr.setFormatter(formatter)
|
||||
logging.getLogger("fail2ban").addHandler(hdlr)
|
||||
return True
|
||||
try:
|
||||
self.__loggingLock.acquire()
|
||||
if target == "SYSLOG":
|
||||
facility = logging.handlers.SysLogHandler.LOG_DAEMON
|
||||
hdlr = logging.handlers.SysLogHandler("/dev/log",
|
||||
facility = facility)
|
||||
elif target == "STDOUT":
|
||||
hdlr = logging.StreamHandler(sys.stdout)
|
||||
elif target == "STDERR":
|
||||
hdlr = logging.StreamHandler(sys.stderr)
|
||||
else:
|
||||
# Target should be a file
|
||||
try:
|
||||
open(target, "a")
|
||||
hdlr = logging.FileHandler(target)
|
||||
except IOError:
|
||||
logSys.error("Unable to log to " + target)
|
||||
logSys.info("Logging to previous target " + self.__logTarget)
|
||||
return False
|
||||
self.__logTarget = target
|
||||
# Remove previous handler
|
||||
logging.getLogger("fail2ban").handlers = []
|
||||
# set a format which is simpler for console use
|
||||
formatter = logging.Formatter("%(asctime)s %(name)-16s: %(levelname)-6s %(message)s")
|
||||
# tell the handler to use this format
|
||||
hdlr.setFormatter(formatter)
|
||||
logging.getLogger("fail2ban").addHandler(hdlr)
|
||||
return True
|
||||
finally:
|
||||
self.__loggingLock.release()
|
||||
|
||||
def getLogTarget(self):
|
||||
return self.__logTarget
|
||||
try:
|
||||
self.__loggingLock.acquire()
|
||||
return self.__logTarget
|
||||
finally:
|
||||
self.__loggingLock.release()
|
||||
|
||||
def __createDaemon(self):
|
||||
""" Detach a process from the controlling terminal and run it in the
|
||||
|
||||
+131
-118
@@ -24,7 +24,6 @@ __date__ = "$Date$"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
from threading import Lock
|
||||
import logging, time
|
||||
|
||||
# Gets the instance of the logger.
|
||||
@@ -32,229 +31,243 @@ logSys = logging.getLogger("fail2ban.comm")
|
||||
|
||||
class Transmitter:
|
||||
|
||||
##
|
||||
# Constructor.
|
||||
#
|
||||
# @param The server reference
|
||||
|
||||
def __init__(self, server):
|
||||
self.__lock = Lock()
|
||||
self.__server = server
|
||||
|
||||
def proceed(self, action):
|
||||
##
|
||||
# Proceeds a command.
|
||||
#
|
||||
# Proceeds an incoming command.
|
||||
# @param command The incoming command
|
||||
|
||||
def proceed(self, command):
|
||||
# Deserialize object
|
||||
logSys.debug("Command: " + `command`)
|
||||
try:
|
||||
self.__lock.acquire()
|
||||
logSys.debug("Action: " + `action`)
|
||||
try:
|
||||
ret = self.__actionHandler(action)
|
||||
ack = 0, ret
|
||||
except Exception, e:
|
||||
logSys.warn("Invalid command: " + `action`)
|
||||
ack = 1, e
|
||||
return ack
|
||||
finally:
|
||||
self.__lock.release()
|
||||
ret = self.__commandHandler(command)
|
||||
ack = 0, ret
|
||||
except Exception, e:
|
||||
logSys.warn("Invalid command: " + `command`)
|
||||
ack = 1, e
|
||||
return ack
|
||||
|
||||
##
|
||||
# Handle an action.
|
||||
# Handle an command.
|
||||
#
|
||||
#
|
||||
|
||||
def __actionHandler(self, action):
|
||||
if action[0] == "ping":
|
||||
def __commandHandler(self, command):
|
||||
if command[0] == "ping":
|
||||
return "pong"
|
||||
elif action[0] == "add":
|
||||
name = action[1]
|
||||
elif command[0] == "add":
|
||||
name = command[1]
|
||||
if name == "all":
|
||||
raise Exception("Reserved name")
|
||||
try:
|
||||
backend = action[2]
|
||||
backend = command[2]
|
||||
except IndexError:
|
||||
backend = "auto"
|
||||
self.__server.addJail(name, backend)
|
||||
return name
|
||||
elif action[0] == "start":
|
||||
name = action[1]
|
||||
elif command[0] == "start":
|
||||
name = command[1]
|
||||
self.__server.startJail(name)
|
||||
return None
|
||||
elif action[0] == "stop":
|
||||
if len(action) == 1:
|
||||
elif command[0] == "stop":
|
||||
if len(command) == 1:
|
||||
self.__server.quit()
|
||||
elif action[1] == "all":
|
||||
elif command[1] == "all":
|
||||
self.__server.stopAllJail()
|
||||
else:
|
||||
name = action[1]
|
||||
name = command[1]
|
||||
self.__server.stopJail(name)
|
||||
return None
|
||||
elif action[0] == "sleep":
|
||||
value = action[1]
|
||||
elif command[0] == "sleep":
|
||||
value = command[1]
|
||||
time.sleep(int(value))
|
||||
return None
|
||||
elif action[0] == "set":
|
||||
return self.__actionSet(action[1:])
|
||||
elif action[0] == "get":
|
||||
return self.__actionGet(action[1:])
|
||||
elif action[0] == "status":
|
||||
return self.status(action[1:])
|
||||
elif command[0] == "set":
|
||||
return self.__commandSet(command[1:])
|
||||
elif command[0] == "get":
|
||||
return self.__commandGet(command[1:])
|
||||
elif command[0] == "status":
|
||||
return self.status(command[1:])
|
||||
raise Exception("Invalid command")
|
||||
|
||||
def __actionSet(self, action):
|
||||
name = action[0]
|
||||
def __commandSet(self, command):
|
||||
name = command[0]
|
||||
# Logging
|
||||
if name == "loglevel":
|
||||
value = int(action[1])
|
||||
value = int(command[1])
|
||||
self.__server.setLogLevel(value)
|
||||
return self.__server.getLogLevel()
|
||||
elif name == "logtarget":
|
||||
value = action[1]
|
||||
value = command[1]
|
||||
self.__server.setLogTarget(value)
|
||||
return self.__server.getLogTarget()
|
||||
# Jail
|
||||
elif action[1] == "idle":
|
||||
if action[2] == "on":
|
||||
elif command[1] == "idle":
|
||||
if command[2] == "on":
|
||||
self.__server.setIdleJail(name, True)
|
||||
elif action[2] == "off":
|
||||
elif command[2] == "off":
|
||||
self.__server.setIdleJail(name, False)
|
||||
return self.__server.getIdleJail(name)
|
||||
# Filter
|
||||
elif action[1] == "addignoreip":
|
||||
value = action[2]
|
||||
elif command[1] == "addignoreip":
|
||||
value = command[2]
|
||||
self.__server.addIgnoreIP(name, value)
|
||||
return self.__server.getIgnoreIP(name)
|
||||
elif action[1] == "delignoreip":
|
||||
value = action[2]
|
||||
elif command[1] == "delignoreip":
|
||||
value = command[2]
|
||||
self.__server.delIgnoreIP(name, value)
|
||||
return self.__server.getIgnoreIP(name)
|
||||
elif action[1] == "addlogpath":
|
||||
value = action[2:]
|
||||
elif command[1] == "addlogpath":
|
||||
value = command[2:]
|
||||
for path in value:
|
||||
self.__server.addLogPath(name, path)
|
||||
return self.__server.getLogPath(name)
|
||||
elif action[1] == "dellogpath":
|
||||
value = action[2]
|
||||
elif command[1] == "dellogpath":
|
||||
value = command[2]
|
||||
self.__server.delLogPath(name, value)
|
||||
return self.__server.getLogPath(name)
|
||||
elif action[1] == "timeregex":
|
||||
value = action[2]
|
||||
elif command[1] == "timeregex":
|
||||
value = command[2]
|
||||
self.__server.setTimeRegex(name, value)
|
||||
return self.__server.getTimeRegex(name)
|
||||
elif action[1] == "timepattern":
|
||||
value = action[2]
|
||||
elif command[1] == "timepattern":
|
||||
value = command[2]
|
||||
self.__server.setTimePattern(name, value)
|
||||
return self.__server.getTimePattern(name)
|
||||
elif action[1] == "failregex":
|
||||
value = action[2]
|
||||
self.__server.setFailRegex(name, value)
|
||||
elif command[1] == "addfailregex":
|
||||
value = command[2]
|
||||
self.__server.addFailRegex(name, value)
|
||||
return self.__server.getFailRegex(name)
|
||||
elif action[1] == "maxtime":
|
||||
value = action[2]
|
||||
self.__server.setMaxTime(name, int(value))
|
||||
return self.__server.getMaxTime(name)
|
||||
elif action[1] == "findtime":
|
||||
value = action[2]
|
||||
elif command[1] == "delfailregex":
|
||||
value = int(command[2])
|
||||
self.__server.delFailRegex(name, value)
|
||||
return self.__server.getFailRegex(name)
|
||||
elif command[1] == "addignoreregex":
|
||||
value = command[2]
|
||||
self.__server.addIgnoreRegex(name, value)
|
||||
return self.__server.getIgnoreRegex(name)
|
||||
elif command[1] == "delignoreregex":
|
||||
value = int(command[2])
|
||||
self.__server.delIgnoreRegex(name, value)
|
||||
return self.__server.getIgnoreRegex(name)
|
||||
elif command[1] == "findtime":
|
||||
value = command[2]
|
||||
self.__server.setFindTime(name, int(value))
|
||||
return self.__server.getFindTime(name)
|
||||
elif action[1] == "maxretry":
|
||||
value = action[2]
|
||||
elif command[1] == "maxretry":
|
||||
value = command[2]
|
||||
self.__server.setMaxRetry(name, int(value))
|
||||
return self.__server.getMaxRetry(name)
|
||||
# Action
|
||||
elif action[1] == "bantime":
|
||||
value = action[2]
|
||||
# command
|
||||
elif command[1] == "bantime":
|
||||
value = command[2]
|
||||
self.__server.setBanTime(name, int(value))
|
||||
return self.__server.getBanTime(name)
|
||||
elif action[1] == "addaction":
|
||||
value = action[2]
|
||||
elif command[1] == "addaction":
|
||||
value = command[2]
|
||||
self.__server.addAction(name, value)
|
||||
return self.__server.getLastAction(name).getName()
|
||||
elif action[1] == "delaction":
|
||||
elif command[1] == "delaction":
|
||||
self.__server.delAction(name, value)
|
||||
return None
|
||||
elif action[1] == "setcinfo":
|
||||
act = action[2]
|
||||
key = action[3]
|
||||
value = action[4]
|
||||
elif command[1] == "setcinfo":
|
||||
act = command[2]
|
||||
key = command[3]
|
||||
value = command[4]
|
||||
self.__server.setCInfo(name, act, key, value)
|
||||
return self.__server.getCInfo(name, act, key)
|
||||
elif action[1] == "delcinfo":
|
||||
act = action[2]
|
||||
key = action[3]
|
||||
elif command[1] == "delcinfo":
|
||||
act = command[2]
|
||||
key = command[3]
|
||||
self.__server.delCInfo(name, act, key)
|
||||
return None
|
||||
elif action[1] == "actionstart":
|
||||
act = action[2]
|
||||
value = action[3]
|
||||
elif command[1] == "actionstart":
|
||||
act = command[2]
|
||||
value = command[3]
|
||||
self.__server.setActionStart(name, act, value)
|
||||
return self.__server.getActionStart(name, act)
|
||||
elif action[1] == "actionstop":
|
||||
act = action[2]
|
||||
value = action[3]
|
||||
elif command[1] == "actionstop":
|
||||
act = command[2]
|
||||
value = command[3]
|
||||
self.__server.setActionStop(name, act, value)
|
||||
return self.__server.getActionStop(name, act)
|
||||
elif action[1] == "actioncheck":
|
||||
act = action[2]
|
||||
value = action[3]
|
||||
elif command[1] == "actioncheck":
|
||||
act = command[2]
|
||||
value = command[3]
|
||||
self.__server.setActionCheck(name, act, value)
|
||||
return self.__server.getActionCheck(name, act)
|
||||
elif action[1] == "actionban":
|
||||
act = action[2]
|
||||
value = action[3]
|
||||
elif command[1] == "actionban":
|
||||
act = command[2]
|
||||
value = command[3]
|
||||
self.__server.setActionBan(name, act, value)
|
||||
return self.__server.getActionBan(name, act)
|
||||
elif action[1] == "actionunban":
|
||||
act = action[2]
|
||||
value = action[3]
|
||||
elif command[1] == "actionunban":
|
||||
act = command[2]
|
||||
value = command[3]
|
||||
self.__server.setActionUnban(name, act, value)
|
||||
return self.__server.getActionUnban(name, act)
|
||||
raise Exception("Invalid command (no set action or not yet implemented)")
|
||||
|
||||
def __actionGet(self, action):
|
||||
name = action[0]
|
||||
def __commandGet(self, command):
|
||||
name = command[0]
|
||||
# Logging
|
||||
if name == "loglevel":
|
||||
return self.__server.getLogLevel()
|
||||
elif name == "logtarget":
|
||||
return self.__server.getLogTarget()
|
||||
# Filter
|
||||
elif action[1] == "logpath":
|
||||
elif command[1] == "logpath":
|
||||
return self.__server.getLogPath(name)
|
||||
elif action[1] == "ignoreip":
|
||||
elif command[1] == "ignoreip":
|
||||
return self.__server.getIgnoreIP(name)
|
||||
elif action[1] == "timeregex":
|
||||
elif command[1] == "timeregex":
|
||||
return self.__server.getTimeRegex(name)
|
||||
elif action[1] == "timepattern":
|
||||
elif command[1] == "timepattern":
|
||||
return self.__server.getTimePattern(name)
|
||||
elif action[1] == "failregex":
|
||||
elif command[1] == "failregex":
|
||||
return self.__server.getFailRegex(name)
|
||||
elif action[1] == "maxtime":
|
||||
return self.__server.getMaxTime(name)
|
||||
elif action[1] == "findtime":
|
||||
elif command[1] == "ignoreregex":
|
||||
return self.__server.getIgnoreRegex(name)
|
||||
elif command[1] == "findtime":
|
||||
return self.__server.getFindTime(name)
|
||||
elif action[1] == "maxretry":
|
||||
elif command[1] == "maxretry":
|
||||
return self.__server.getMaxRetry(name)
|
||||
# Action
|
||||
elif action[1] == "bantime":
|
||||
elif command[1] == "bantime":
|
||||
return self.__server.getBanTime(name)
|
||||
elif action[1] == "addaction":
|
||||
elif command[1] == "addaction":
|
||||
return self.__server.getLastAction(name).getName()
|
||||
elif action[1] == "actionstart":
|
||||
act = action[2]
|
||||
elif command[1] == "actionstart":
|
||||
act = command[2]
|
||||
return self.__server.getActionStart(name, act)
|
||||
elif action[1] == "actionstop":
|
||||
act = action[2]
|
||||
elif command[1] == "actionstop":
|
||||
act = command[2]
|
||||
return self.__server.getActionStop(name, act)
|
||||
elif action[1] == "actioncheck":
|
||||
act = action[2]
|
||||
elif command[1] == "actioncheck":
|
||||
act = command[2]
|
||||
return self.__server.getActionCheck(name, act)
|
||||
elif action[1] == "actionban":
|
||||
act = action[2]
|
||||
elif command[1] == "actionban":
|
||||
act = command[2]
|
||||
return self.__server.getActionBan(name, act)
|
||||
elif action[1] == "actionunban":
|
||||
act = action[2]
|
||||
elif command[1] == "actionunban":
|
||||
act = command[2]
|
||||
return self.__server.getActionUnban(name, act)
|
||||
raise Exception("Invalid command (no get action or not yet implemented)")
|
||||
|
||||
def status(self, action):
|
||||
if len(action) == 0:
|
||||
def status(self, command):
|
||||
if len(command) == 0:
|
||||
return self.__server.status()
|
||||
else:
|
||||
name = action[0]
|
||||
name = command[0]
|
||||
return self.__server.statusJail(name)
|
||||
raise Exception("Invalid command (no status)")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[install]
|
||||
install-purelib=/usr/lib/fail2ban
|
||||
install-purelib=/usr/share/fail2ban
|
||||
|
||||
[sdist]
|
||||
formats=bztar
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/python
|
||||
|
||||
# This file is part of Fail2Ban.
|
||||
#
|
||||
@@ -27,9 +27,9 @@ __copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
from distutils.core import setup
|
||||
from version import version
|
||||
from os.path import isfile, join
|
||||
from sys import exit, argv
|
||||
from common.version import version
|
||||
from os.path import isfile, join, isdir
|
||||
from sys import argv
|
||||
from glob import glob
|
||||
|
||||
longdesc = '''
|
||||
@@ -40,33 +40,33 @@ to reject the IP address or executes user defined
|
||||
commands.'''
|
||||
|
||||
setup(
|
||||
name = "fail2ban",
|
||||
version = version,
|
||||
description = "Ban IPs that make too many password failure",
|
||||
long_description = longdesc,
|
||||
author = "Cyril Jaquier",
|
||||
author_email = "lostcontrol@users.sourceforge.net",
|
||||
url = "http://fail2ban.sourceforge.net",
|
||||
license = "GPL",
|
||||
platforms = "Posix",
|
||||
name = "fail2ban",
|
||||
version = version,
|
||||
description = "Ban IPs that make too many password failure",
|
||||
long_description = longdesc,
|
||||
author = "Cyril Jaquier",
|
||||
author_email = "lostcontrol@users.sourceforge.net",
|
||||
url = "http://fail2ban.sourceforge.net",
|
||||
license = "GPL",
|
||||
platforms = "Posix",
|
||||
scripts = [
|
||||
'fail2ban-client',
|
||||
'fail2ban-server',
|
||||
'fail2ban-client',
|
||||
'fail2ban-server',
|
||||
'fail2ban-regex'
|
||||
],
|
||||
py_modules = ['version'],
|
||||
],
|
||||
packages = [
|
||||
'client',
|
||||
'common',
|
||||
'client',
|
||||
'server'
|
||||
],
|
||||
],
|
||||
data_files = [
|
||||
('/etc/fail2ban',
|
||||
('/etc/fail2ban',
|
||||
glob("config/*.conf")
|
||||
),
|
||||
('/etc/fail2ban/filter.d',
|
||||
),
|
||||
('/etc/fail2ban/filter.d',
|
||||
glob("config/filter.d/*.conf")
|
||||
),
|
||||
('/etc/fail2ban/action.d',
|
||||
),
|
||||
('/etc/fail2ban/action.d',
|
||||
glob("config/action.d/*.conf")
|
||||
)
|
||||
]
|
||||
@@ -79,24 +79,30 @@ elements = {
|
||||
"/etc/":
|
||||
[
|
||||
"fail2ban.conf"
|
||||
],
|
||||
],
|
||||
"/usr/bin/":
|
||||
[
|
||||
"fail2ban.py"
|
||||
],
|
||||
],
|
||||
"/usr/lib/fail2ban/firewall/":
|
||||
[
|
||||
"iptables.py",
|
||||
"ipfwadm.py",
|
||||
"iptables.py",
|
||||
"ipfwadm.py",
|
||||
"ipfw.py"
|
||||
],
|
||||
"/usr/lib/fail2ban/":
|
||||
[
|
||||
"version.py",
|
||||
"protocol.py"
|
||||
]
|
||||
}
|
||||
|
||||
for dir in elements:
|
||||
for f in elements[dir]:
|
||||
path = join(dir, f)
|
||||
for directory in elements:
|
||||
for f in elements[directory]:
|
||||
path = join(directory, f)
|
||||
if isfile(path):
|
||||
obsoleteFiles.append(path)
|
||||
|
||||
if obsoleteFiles:
|
||||
print
|
||||
print "Obsolete files from previous Fail2Ban versions were found on " \
|
||||
@@ -107,6 +113,13 @@ if obsoleteFiles:
|
||||
print "\t" + f
|
||||
print
|
||||
|
||||
if isdir("/usr/lib/fail2ban"):
|
||||
print
|
||||
print "Fail2ban is not installed under /usr/lib anymore. The new " \
|
||||
"location is under /usr/share. Please remove the directory " \
|
||||
"/usr/lib/fail2ban and everything under this directory."
|
||||
print
|
||||
|
||||
# Update config file
|
||||
if argv[1] == "install":
|
||||
print
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 382 $
|
||||
# $Revision$
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 382 $"
|
||||
__date__ = "$Date: 2006-09-25 19:03:48 +0200 (Mon, 25 Sep 2006) $"
|
||||
__version__ = "$Revision$"
|
||||
__date__ = "$Date$"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 253 $
|
||||
# $Revision$
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 253 $"
|
||||
__date__ = "$Date: 2006-07-17 00:21:58 +0200 (Mon, 17 Jul 2006) $"
|
||||
__version__ = "$Revision$"
|
||||
__date__ = "$Date$"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
|
||||
@@ -16,15 +16,15 @@
|
||||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision: 253 $
|
||||
# $Revision$
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 253 $"
|
||||
__date__ = "$Date: 2006-07-17 00:21:58 +0200 (Mon, 17 Jul 2006) $"
|
||||
__version__ = "$Revision$"
|
||||
__date__ = "$Date$"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
import unittest, time
|
||||
import unittest
|
||||
from server.datedetector import DateDetector
|
||||
from server.datetemplate import DateTemplate
|
||||
|
||||
@@ -53,4 +53,15 @@ class DateDetectorTest(unittest.TestCase):
|
||||
|
||||
self.assertEqual(self.__datedetector.getTime(log), date)
|
||||
self.assertEqual(self.__datedetector.getUnixTime(log), dateUnix)
|
||||
|
||||
|
||||
def testDefaultTempate(self):
|
||||
self.__datedetector.setDefaultRegex("^\S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2}")
|
||||
self.__datedetector.setDefaultPattern("%b %d %H:%M:%S")
|
||||
|
||||
log = "Jan 23 21:59:59 [sshd] error: PAM: Authentication failure"
|
||||
date = [2005, 1, 23, 21, 59, 59, 1, 23, -1]
|
||||
dateUnix = 1106513999.0
|
||||
|
||||
self.assertEqual(self.__datedetector.getTime(log), date)
|
||||
self.assertEqual(self.__datedetector.getUnixTime(log), dateUnix)
|
||||
|
||||
@@ -99,7 +99,7 @@ class GetFailures(unittest.TestCase):
|
||||
output = ('193.168.0.128', 3, 1124013599.0)
|
||||
|
||||
self.__filter.addLogPath(GetFailures.FILENAME_01)
|
||||
self.__filter.setFailRegex("(?:(?:Authentication failure|Failed [-/\w+]+) for(?: [iI](?:llegal|nvalid) user)?|[Ii](?:llegal|nvalid) user|ROOT LOGIN REFUSED) .*(?: from|FROM) (?:::f{4,6}:)?(?P<host>\S*)")
|
||||
self.__filter.addFailRegex("(?:(?:Authentication failure|Failed [-/\w+]+) for(?: [iI](?:llegal|nvalid) user)?|[Ii](?:llegal|nvalid) user|ROOT LOGIN REFUSED) .*(?: from|FROM) (?:::f{4,6}:)?(?P<host>\S*)")
|
||||
|
||||
self.__filter.getFailures(GetFailures.FILENAME_01)
|
||||
|
||||
@@ -116,7 +116,7 @@ class GetFailures(unittest.TestCase):
|
||||
output = ('141.3.81.106', 4, 1124013539.0)
|
||||
|
||||
self.__filter.addLogPath(GetFailures.FILENAME_02)
|
||||
self.__filter.setFailRegex("Failed .* (?:::f{4,6}:)(?P<host>\S*)")
|
||||
self.__filter.addFailRegex("Failed .* (?:::f{4,6}:)(?P<host>\S*)")
|
||||
|
||||
self.__filter.getFailures(GetFailures.FILENAME_02)
|
||||
|
||||
@@ -127,13 +127,13 @@ class GetFailures(unittest.TestCase):
|
||||
ip = ticket.getIP()
|
||||
found = (ip, attempts, date)
|
||||
|
||||
self.assertEqual(found, output)
|
||||
self.assertEqual(found, output)
|
||||
|
||||
def testGetFailures03(self):
|
||||
output = ('203.162.223.135', 6, 1124013544.0)
|
||||
|
||||
self.__filter.addLogPath(GetFailures.FILENAME_03)
|
||||
self.__filter.setFailRegex("error,relay=(?:::f{4,6}:)?(?P<host>\S*),.*550 User unknown")
|
||||
self.__filter.addFailRegex("error,relay=(?:::f{4,6}:)?(?P<host>\S*),.*550 User unknown")
|
||||
|
||||
self.__filter.getFailures(GetFailures.FILENAME_03)
|
||||
|
||||
@@ -151,7 +151,7 @@ class GetFailures(unittest.TestCase):
|
||||
('212.41.96.185', 4, 1124013598.0)]
|
||||
|
||||
self.__filter.addLogPath(GetFailures.FILENAME_04)
|
||||
self.__filter.setFailRegex("Invalid user .* (?P<host>\S*)")
|
||||
self.__filter.addFailRegex("Invalid user .* (?P<host>\S*)")
|
||||
|
||||
self.__filter.getFailures(GetFailures.FILENAME_04)
|
||||
|
||||
@@ -165,4 +165,33 @@ class GetFailures(unittest.TestCase):
|
||||
self.assertEqual(found, output[i])
|
||||
except FailManagerEmpty:
|
||||
pass
|
||||
|
||||
|
||||
def testGetFailuresMultiRegex(self):
|
||||
output = ('141.3.81.106', 8, 1124013541.0)
|
||||
|
||||
self.__filter.addLogPath(GetFailures.FILENAME_02)
|
||||
self.__filter.addFailRegex("Failed .* from <HOST>")
|
||||
self.__filter.addFailRegex("Accepted .* from <HOST>")
|
||||
|
||||
self.__filter.getFailures(GetFailures.FILENAME_02)
|
||||
|
||||
ticket = self.__filter.failManager.toBan()
|
||||
|
||||
attempts = ticket.getAttempt()
|
||||
date = ticket.getTime()
|
||||
ip = ticket.getIP()
|
||||
found = (ip, attempts, date)
|
||||
|
||||
self.assertEqual(found, output)
|
||||
|
||||
def testGetFailuresIgnoreRegex(self):
|
||||
output = ('141.3.81.106', 8, 1124013541.0)
|
||||
|
||||
self.__filter.addLogPath(GetFailures.FILENAME_02)
|
||||
self.__filter.addFailRegex("Failed .* from <HOST>")
|
||||
self.__filter.addFailRegex("Accepted .* from <HOST>")
|
||||
self.__filter.addIgnoreRegex("for roehl")
|
||||
|
||||
self.__filter.getFailures(GetFailures.FILENAME_02)
|
||||
|
||||
self.assertRaises(FailManagerEmpty, self.__filter.failManager.toBan)
|
||||
|
||||
Reference in New Issue
Block a user