mirror of
https://github.com/fail2ban/fail2ban.git
synced 2026-03-11 08:55:31 +00:00
Compare commits
499 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8be17b0981 | ||
|
|
c03a6204c1 | ||
|
|
eb7ed973ef | ||
|
|
3b8033b337 | ||
|
|
243876e60a | ||
|
|
3bead7c011 | ||
|
|
05f6ad4fcc | ||
|
|
81b906303c | ||
|
|
025adbf485 | ||
|
|
f457cf8131 | ||
|
|
1a802bee93 | ||
|
|
36e28359ed | ||
|
|
8a8afefd70 | ||
|
|
8afd0c8956 | ||
|
|
6cdb5738ec | ||
|
|
9887ee4412 | ||
|
|
8506e4a41d | ||
|
|
948e923589 | ||
|
|
247667c9c2 | ||
|
|
7528fce11b | ||
|
|
edaf8ef19f | ||
|
|
74981e4c13 | ||
|
|
45453826a3 | ||
|
|
2f0e05a0d7 | ||
|
|
ef65652671 | ||
|
|
bfafd12c59 | ||
|
|
7c2bda4977 | ||
|
|
3f78f1520b | ||
|
|
7bac839603 | ||
|
|
d0b94c147e | ||
|
|
070d49e09c | ||
|
|
dda4aa7d2d | ||
|
|
ad9aba5871 | ||
|
|
13563fd09b | ||
|
|
a9401233dd | ||
|
|
1379a262f6 | ||
|
|
abdd0d4b25 | ||
|
|
897b21a4c5 | ||
|
|
65668b8ed8 | ||
|
|
2856092709 | ||
|
|
2ac7e1284f | ||
|
|
0fee8dbe92 | ||
|
|
6c47bf6461 | ||
|
|
9534bdac37 | ||
|
|
a8875c36b8 | ||
|
|
9f26da3cf8 | ||
|
|
5beee494a3 | ||
|
|
3fd3454146 | ||
|
|
ce8cc5d261 | ||
|
|
4539e6719c | ||
|
|
85cfb81782 | ||
|
|
3d23a44bb1 | ||
|
|
77efe3b40c | ||
|
|
26b91862fc | ||
|
|
10b12e8c57 | ||
|
|
13876e93ad | ||
|
|
70d7fd0fdd | ||
|
|
9e72e78f34 | ||
|
|
912e3c81a2 | ||
|
|
c54d505dea | ||
|
|
6ac181f559 | ||
|
|
52399e6ef1 | ||
|
|
c9e1a1b087 | ||
|
|
a055568500 | ||
|
|
0265df854e | ||
|
|
a3d181c973 | ||
|
|
002719dca4 | ||
|
|
c26fda9dbb | ||
|
|
bdb5d99906 | ||
|
|
4e22c20559 | ||
|
|
3ce6f344e3 | ||
|
|
bf4903538d | ||
|
|
77ba28bae1 | ||
|
|
dc3268ce5d | ||
|
|
eb80b895d1 | ||
|
|
6120a731d9 | ||
|
|
e16e982a45 | ||
|
|
dd58d440bc | ||
|
|
e6516fd2b3 | ||
|
|
0a91bf69a5 | ||
|
|
d86a7aecca | ||
|
|
ff3eca1d61 | ||
|
|
0b255a8723 | ||
|
|
793d0c6555 | ||
|
|
7bb86822d0 | ||
|
|
6d3bfa8781 | ||
|
|
b309cf6b3c | ||
|
|
e97df4672a | ||
|
|
1c2ace2958 | ||
|
|
b710d5b6c7 | ||
|
|
dc899e438f | ||
|
|
86b9adb2f5 | ||
|
|
85faeab644 | ||
|
|
9ef134c17d | ||
|
|
8a4f373617 | ||
|
|
646832d5bd | ||
|
|
04ff4c060c | ||
|
|
cfa3356e0f | ||
|
|
4254d6bcd3 | ||
|
|
afe9bc08ec | ||
|
|
a5d7127109 | ||
|
|
cca2de984f | ||
|
|
f7aaaf50b8 | ||
|
|
f0a083449a | ||
|
|
9ecf6150c8 | ||
|
|
cbc3cb431c | ||
|
|
d731b385f9 | ||
|
|
52d239483d | ||
|
|
0d4a926029 | ||
|
|
cbe14c70c5 | ||
|
|
37f72f88ef | ||
|
|
139151ec81 | ||
|
|
c76e90fbb1 | ||
|
|
6538d43a8e | ||
|
|
bfd80ce522 | ||
|
|
70ce1cef08 | ||
|
|
426eeca62a | ||
|
|
6104444bb4 | ||
|
|
cf9135983c | ||
|
|
c7f7bc55bb | ||
|
|
6b57e46070 | ||
|
|
fc3e8a5d37 | ||
|
|
1d6ff06856 | ||
|
|
767c89f863 | ||
|
|
a0093b557e | ||
|
|
d5718503ad | ||
|
|
6b56259f9a | ||
|
|
b2352f113e | ||
|
|
5a2fd9b31c | ||
|
|
4eef68b3d3 | ||
|
|
7a4985178f | ||
|
|
786d5b7e9e | ||
|
|
191d1e9533 | ||
|
|
9f0b6382bf | ||
|
|
f49d50b8fd | ||
|
|
994a0b69da | ||
|
|
16ae53e888 | ||
|
|
ee421dfbd6 | ||
|
|
b0d4eb07e5 | ||
|
|
d02a613e89 | ||
|
|
8ae6eaf39a | ||
|
|
505d51fd5d | ||
|
|
4bb1fd519d | ||
|
|
cf9c8f1e9b | ||
|
|
c035428535 | ||
|
|
79346e4f2c | ||
|
|
94fe9cf4a8 | ||
|
|
1e06ab68b4 | ||
|
|
e9a42847bc | ||
|
|
3e9a4b4a48 | ||
|
|
95cdf553f5 | ||
|
|
13a74feaad | ||
|
|
6e3bfd800c | ||
|
|
9d7646e6c0 | ||
|
|
f5ba525cd2 | ||
|
|
fd1d0d25a8 | ||
|
|
bd4cb606e5 | ||
|
|
65d473fc8e | ||
|
|
e3ab969047 | ||
|
|
9145db8de3 | ||
|
|
7233edd0bf | ||
|
|
c54f1a4603 | ||
|
|
5bea1c87f1 | ||
|
|
6efa3a3144 | ||
|
|
fe37047061 | ||
|
|
81a5b1596b | ||
|
|
d684339edd | ||
|
|
bdae15b522 | ||
|
|
c9b5e845ba | ||
|
|
e5199aee92 | ||
|
|
1c61836169 | ||
|
|
fdac34a3ee | ||
|
|
c340fb0ef4 | ||
|
|
6d4b487eb9 | ||
|
|
c88967df2d | ||
|
|
882e6d5e00 | ||
|
|
2d736ad755 | ||
|
|
a44c8dc3ec | ||
|
|
6fb3532c45 | ||
|
|
a1268f37c3 | ||
|
|
b55c20594e | ||
|
|
6d3308ecb4 | ||
|
|
b8ab346257 | ||
|
|
d2c60a168f | ||
|
|
e1fc569291 | ||
|
|
95710e9dac | ||
|
|
88385eb6c1 | ||
|
|
7a5e2c8419 | ||
|
|
8c6d7dc12f | ||
|
|
5b6c13f0aa | ||
|
|
155a0855f2 | ||
|
|
eb1fc5b261 | ||
|
|
325613a8f8 | ||
|
|
9dde3d019e | ||
|
|
a796cc9b91 | ||
|
|
4b6f69a14a | ||
|
|
eb8b44370a | ||
|
|
b7b1fff53c | ||
|
|
62aeb55b63 | ||
|
|
dd9f359f5c | ||
|
|
89b5f3bb1e | ||
|
|
51358e1587 | ||
|
|
d89ded39b0 | ||
|
|
b6aebc333c | ||
|
|
d38f233e91 | ||
|
|
a6ca6e2a26 | ||
|
|
a57a768cb8 | ||
|
|
4151eeccfe | ||
|
|
91c27d0600 | ||
|
|
12ff98027f | ||
|
|
eb4731d8b1 | ||
|
|
0bf1106d72 | ||
|
|
89970d2e3e | ||
|
|
363c0d5fd0 | ||
|
|
1ea8a6de58 | ||
|
|
44bd87951e | ||
|
|
3361fb0805 | ||
|
|
9e31cfc1f1 | ||
|
|
be734991eb | ||
|
|
fda37fac81 | ||
|
|
47e995cb57 | ||
|
|
2950e41186 | ||
|
|
78af48862f | ||
|
|
54c0effceb | ||
|
|
c769046a1f | ||
|
|
a43f7ad63f | ||
|
|
2749109f10 | ||
|
|
8e0a2366f0 | ||
|
|
af119e0ae1 | ||
|
|
35afe20ea0 | ||
|
|
d4663e8941 | ||
|
|
216f0abb5e | ||
|
|
4a87802c59 | ||
|
|
9a558589d7 | ||
|
|
db8c943a7b | ||
|
|
83f2d59eee | ||
|
|
07a7da8d8e | ||
|
|
4fb04842a2 | ||
|
|
ca45671db2 | ||
|
|
7fd097d73f | ||
|
|
93810fff75 | ||
|
|
a4f1b0ce9f | ||
|
|
766d2b8d74 | ||
|
|
8170e9fe75 | ||
|
|
599ec5e01e | ||
|
|
7004d175b7 | ||
|
|
216622adb2 | ||
|
|
50ff131a0f | ||
|
|
8360776ce1 | ||
|
|
7b335f47ea | ||
|
|
2fed408c05 | ||
|
|
59c5e78ce9 | ||
|
|
a7f3a04b0e | ||
|
|
ab9d41e530 | ||
|
|
6fce23e7ba | ||
|
|
8ae5e7e3e4 | ||
|
|
cd95c3a1fc | ||
|
|
2533526827 | ||
|
|
17daf0ec78 | ||
|
|
304c3cd566 | ||
|
|
7d2fffbe19 | ||
|
|
8bbdb7b5a7 | ||
|
|
246a617cd6 | ||
|
|
21bf636056 | ||
|
|
65e9c411ef | ||
|
|
ecb9771123 | ||
|
|
4da56cf4bc | ||
|
|
ac62658c10 | ||
|
|
0185e1c7d5 | ||
|
|
ed20a9a5b9 | ||
|
|
c04e12dd8d | ||
|
|
1434e3089c | ||
|
|
a763fbbdfd | ||
|
|
d0d0728523 | ||
|
|
c14327565d | ||
|
|
61799e15e1 | ||
|
|
22ffe12abb | ||
|
|
7b528a6da6 | ||
|
|
3ca3646472 | ||
|
|
bdba42edd9 | ||
|
|
921d9a5a40 | ||
|
|
3b97182f62 | ||
|
|
b59fd2e7b5 | ||
|
|
44f32d6132 | ||
|
|
2c13cba73d | ||
|
|
fd7657f9a9 | ||
|
|
4550e3ad27 | ||
|
|
a4ca2e83bd | ||
|
|
1ec9237e53 | ||
|
|
c80908837f | ||
|
|
e0f1a1e02a | ||
|
|
8da0a99cde | ||
|
|
806a27cb4f | ||
|
|
5ecc26d3ba | ||
|
|
e605415f61 | ||
|
|
c22a83933b | ||
|
|
df94ec4c52 | ||
|
|
0c125ec9c9 | ||
|
|
77b052fdea | ||
|
|
5a59b0bae2 | ||
|
|
f63868b3e8 | ||
|
|
9ca137b42b | ||
|
|
529eb79ddb | ||
|
|
d260ed31d2 | ||
|
|
8be16f1c1c | ||
|
|
f12917c491 | ||
|
|
dd3c78ecab | ||
|
|
0b63fc312d | ||
|
|
93082ead79 | ||
|
|
383adec83c | ||
|
|
45d7f3cb97 | ||
|
|
ff701e94c3 | ||
|
|
3047572701 | ||
|
|
dce2c608c1 | ||
|
|
4f679a56e0 | ||
|
|
9bedc3c383 | ||
|
|
302252b25c | ||
|
|
cab6f93364 | ||
|
|
b3178851fe | ||
|
|
781321d609 | ||
|
|
7de1057f94 | ||
|
|
dd4431cd63 | ||
|
|
e1b7720d43 | ||
|
|
0c2edfacb0 | ||
|
|
b161e55ca7 | ||
|
|
6fb3198a41 | ||
|
|
6a1da5e164 | ||
|
|
419e380870 | ||
|
|
6fb89d1709 | ||
|
|
3190febb27 | ||
|
|
c6244a8509 | ||
|
|
7523a777f0 | ||
|
|
093cd763ce | ||
|
|
ff4a2a12fc | ||
|
|
cabcc9b3f4 | ||
|
|
f2d7f16d2f | ||
|
|
1024452fe1 | ||
|
|
86cacca9e4 | ||
|
|
1371c91512 | ||
|
|
054e1d89ca | ||
|
|
8d6bfd89bf | ||
|
|
7e88c9be8d | ||
|
|
337a519cb2 | ||
|
|
e3b36756c0 | ||
|
|
36c890f15b | ||
|
|
4e326cb5cb | ||
|
|
340d45ca88 | ||
|
|
26597f625d | ||
|
|
f1efea6a4f | ||
|
|
f966d88ce5 | ||
|
|
ef208e9149 | ||
|
|
70aef2c3c6 | ||
|
|
572582137c | ||
|
|
7076af637f | ||
|
|
5277e91013 | ||
|
|
c03afd3ad4 | ||
|
|
e03df4805f | ||
|
|
7c83669700 | ||
|
|
b71ed9e472 | ||
|
|
9554279129 | ||
|
|
0abba5dc6e | ||
|
|
b245225b13 | ||
|
|
199759f0ba | ||
|
|
70e964c062 | ||
|
|
44fa2959e7 | ||
|
|
5d9817728d | ||
|
|
4d603f9726 | ||
|
|
cdb6607261 | ||
|
|
6bfc23b868 | ||
|
|
44bd1f09fa | ||
|
|
1427625528 | ||
|
|
22ce0c0536 | ||
|
|
9fc754ceea | ||
|
|
0e27811818 | ||
|
|
8ef0d3c7a9 | ||
|
|
81b2eb32d6 | ||
|
|
5e9060a613 | ||
|
|
b3bcd0a0f2 | ||
|
|
e2ede1a43e | ||
|
|
dcb0177d96 | ||
|
|
e96ecf78c1 | ||
|
|
3b3fcde2e6 | ||
|
|
698cba5708 | ||
|
|
4b4c728558 | ||
|
|
e20bd9402b | ||
|
|
eed319e896 | ||
|
|
132c719386 | ||
|
|
183f805ae3 | ||
|
|
7931b67325 | ||
|
|
162f0c4b6c | ||
|
|
c55e9949dc | ||
|
|
8eac5f597a | ||
|
|
cd2ba0a3ba | ||
|
|
f8f8c046a2 | ||
|
|
35af8b6d5d | ||
|
|
f8622c6f92 | ||
|
|
db3b410a60 | ||
|
|
f7ee023661 | ||
|
|
77f80e8c3f | ||
|
|
bbca81f34c | ||
|
|
bcaf1e714e | ||
|
|
6afaf35263 | ||
|
|
3e6a60f940 | ||
|
|
76f6bc81bc | ||
|
|
c38f6654f7 | ||
|
|
48c91dfb6b | ||
|
|
7bfa133208 | ||
|
|
3546071aa5 | ||
|
|
226a59445a | ||
|
|
9c5f6eea76 | ||
|
|
99ff701678 | ||
|
|
03d7c92ae8 | ||
|
|
e2c4982417 | ||
|
|
101d6923e3 | ||
|
|
eebef0089c | ||
|
|
7d6b1a4c3b | ||
|
|
66e195b0f3 | ||
|
|
8e97474586 | ||
|
|
5cd4c5a29f | ||
|
|
217f404b22 | ||
|
|
fb8a93b40f | ||
|
|
50cbc7e8dd | ||
|
|
5d9603c104 | ||
|
|
baf8330214 | ||
|
|
ca4af85cd7 | ||
|
|
de0ed85fb8 | ||
|
|
871101c3c1 | ||
|
|
3c8d5fd4ef | ||
|
|
809b904106 | ||
|
|
7544e969d5 | ||
|
|
2b98f461bb | ||
|
|
e73748c442 | ||
|
|
27294c4b9e | ||
|
|
56485c8548 | ||
|
|
a9b30eb86e | ||
|
|
9cbf59c827 | ||
|
|
212a4c236a | ||
|
|
2c0360d178 | ||
|
|
d1d1730de0 | ||
|
|
3d4bed50c2 | ||
|
|
c7f8b75e7e | ||
|
|
7dc32971f8 | ||
|
|
9b1417a169 | ||
|
|
b892133d51 | ||
|
|
d46ec3a555 | ||
|
|
5781675a7d | ||
|
|
ac2076ef4f | ||
|
|
0e3e9b1d7f | ||
|
|
9997807fb3 | ||
|
|
a2c77429b9 | ||
|
|
234660e94d | ||
|
|
17f060526e | ||
|
|
92fae68071 | ||
|
|
06e3dea062 | ||
|
|
5dcbc0dd55 | ||
|
|
f93a538693 | ||
|
|
a3a3fffa54 | ||
|
|
ed135b6a93 | ||
|
|
582436aadf | ||
|
|
cb8674e68a | ||
|
|
09c23fd5b8 | ||
|
|
d8a9812adc | ||
|
|
58834b6734 | ||
|
|
432e7e1e93 | ||
|
|
bd6e7aeff0 | ||
|
|
efbbcb41ea | ||
|
|
996553f330 | ||
|
|
df91b047d2 | ||
|
|
05c162ef10 | ||
|
|
ae5fe2e003 | ||
|
|
36af3f2502 | ||
|
|
a58fcb8786 | ||
|
|
cbb097a2b3 | ||
|
|
82506f0586 | ||
|
|
eba33d6205 | ||
|
|
e1d3006b03 | ||
|
|
fd3805b40a | ||
|
|
cd17906afe | ||
|
|
d8e2b03a24 | ||
|
|
6d19d2e800 | ||
|
|
04c252c34b | ||
|
|
ca2b94c522 | ||
|
|
fc7dbcc6a7 | ||
|
|
f8fcaf943b | ||
|
|
05575de1f1 | ||
|
|
5a0224ff0e | ||
|
|
64983ecc29 | ||
|
|
6a2d2aa97a | ||
|
|
11768a97e9 | ||
|
|
2224b3db4a | ||
|
|
f376da4bec | ||
|
|
60b136333e | ||
|
|
3359845242 | ||
|
|
846b3316db | ||
|
|
4ae00485b0 | ||
|
|
9327218843 | ||
|
|
7e88ae0ee6 | ||
|
|
1fb7ffe759 | ||
|
|
38d3f01a51 |
203 changed files with 5219 additions and 2019 deletions
12
.codespellrc
Normal file
12
.codespellrc
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
[codespell]
|
||||
# THANKS - names
|
||||
skip = .git,*.pdf,*.svg,venv,.codespellrc,.typos.toml,THANKS,*test*.log,logs
|
||||
check-hidden = true
|
||||
# Ignore all acronyms etc as plenty e.g. in fail2ban/server/strptime.py
|
||||
# Try to identify incomplete words which are part of a regex, hence having [] at the beginning
|
||||
# Ignore all urls as something with :// in it
|
||||
# Ignore all lines with codespell-ignore in them for pragma annotation
|
||||
ignore-regex = (\b([A-Z][A-Z][A-Z]+|gir\.st)\b)|\[[a-zA-Z]+\][a-z]+\b|[a-z]+://\S+|.*codespell-ignore.*
|
||||
# some oddly named variables, some names, etc
|
||||
# wee -- comes in regex etc for weeks
|
||||
ignore-words-list = assertIn,theis,timere,alls,wee,wight,ans,re-use,pre-emptive
|
||||
3
.github/FUNDING.yml
vendored
3
.github/FUNDING.yml
vendored
|
|
@ -1,4 +1,5 @@
|
|||
# These are supported funding model platforms
|
||||
|
||||
github: [sebres]
|
||||
custom: [paypal.me/sebres]
|
||||
custom: [https://paypal.me/sebres]
|
||||
liberapay: sebres
|
||||
|
|
|
|||
10
.github/PULL_REQUEST_TEMPLATE.md
vendored
10
.github/PULL_REQUEST_TEMPLATE.md
vendored
|
|
@ -1,12 +1,10 @@
|
|||
Before submitting your PR, please review the following checklist:
|
||||
|
||||
- [ ] **CHOOSE CORRECT BRANCH**: if filing a bugfix/enhancement
|
||||
against certain release version, choose `0.9`, `0.10` or `0.11` branch,
|
||||
for dev-edition use `master` branch
|
||||
- [ ] **CONSIDER adding a unit test** if your PR resolves an issue
|
||||
- [ ] **LIST ISSUES** this PR resolves
|
||||
- [ ] **LIST ISSUES** this PR resolves or describe the approach in detail
|
||||
- [ ] **MAKE SURE** this PR doesn't break existing tests
|
||||
- [ ] **KEEP PR small** so it could be easily reviewed.
|
||||
- [ ] **KEEP PR small** so it could be easily reviewed
|
||||
- [ ] **AVOID** making unnecessary stylistic changes in unrelated code
|
||||
- [ ] **ACCOMPANY** each new `failregex` for filter `X` with sample log lines
|
||||
within `fail2ban/tests/files/logs/X` file
|
||||
(and `# failJSON`) within `fail2ban/tests/files/logs/X` file
|
||||
- [ ] **PROVIDE ChangeLog** entry describing the pull request
|
||||
|
|
|
|||
22
.github/workflows/codespell.yml
vendored
Normal file
22
.github/workflows/codespell.yml
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
---
|
||||
name: Codespell
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
branches: [master]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
codespell:
|
||||
name: Check for spelling errors
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Codespell
|
||||
uses: codespell-project/actions-codespell@v2
|
||||
44
.github/workflows/main.yml
vendored
44
.github/workflows/main.yml
vendored
|
|
@ -19,18 +19,18 @@ jobs:
|
|||
# This workflow contains a single job called "build"
|
||||
build:
|
||||
# The type of runner that the job will run on
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: [2.7, 3.5, 3.6, 3.7, 3.8, 3.9, '3.10', '3.11.0-beta.3', pypy2, pypy3]
|
||||
python-version: [3.8, 3.9, '3.10', '3.11', '3.12', '3.13', '3.14', '3.15.0-alpha.5', pypy3.11]
|
||||
fail-fast: false
|
||||
# Steps represent a sequence of tasks that will be executed as part of the job
|
||||
steps:
|
||||
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v2
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
|
||||
|
|
@ -51,27 +51,35 @@ jobs:
|
|||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
if [[ "$F2B_PY" = 3 ]]; then python -m pip install --upgrade pip || echo "can't upgrade pip"; fi
|
||||
if [[ "$F2B_PY" = 3 ]] && ! command -v 2to3x -v 2to3 > /dev/null; then
|
||||
#pip install 2to3
|
||||
sudo apt-get -y install 2to3
|
||||
fi
|
||||
#if [[ "$F2B_PY" = 3 ]]; then python -m pip install --upgrade pip || echo "can't upgrade pip"; fi
|
||||
#sudo apt-get -y install python${F2B_PY/2/}-pyinotify || echo 'inotify not available'
|
||||
python -m pip install pyinotify || echo 'inotify not available'
|
||||
sudo apt-get -y install sqlite3 || echo 'sqlite3 not available'
|
||||
#sudo apt-get -y install python${F2B_PY/2/}-systemd || echo 'systemd not available'
|
||||
sudo apt-get -y install libsystemd-dev || echo 'systemd dependencies seems to be unavailable'
|
||||
python -m pip install systemd-python || echo 'systemd not available'
|
||||
#readline if available as module:
|
||||
# readline if available as module:
|
||||
python -c 'import readline' 2> /dev/null || python -m pip install readline || echo 'readline not available'
|
||||
# asyncore/asynchat:
|
||||
if dpkg --compare-versions "$F2B_PYV" ge 3.12; then
|
||||
#sudo apt-get -y install python${F2B_PY/2/}-setuptools || echo 'setuptools not unavailable'
|
||||
python -m pip install setuptools || echo "can't install setuptools"
|
||||
# don't install async* modules, we need to cover bundled-in libraries:
|
||||
#python -m pip install pyasynchat || echo "can't install pyasynchat";
|
||||
#python -m pip install pyasyncore || echo "can't install pyasyncore";
|
||||
fi
|
||||
# aiosmtpd in test_smtp (for 3.10+, no need to test it everywhere):
|
||||
if dpkg --compare-versions "$F2B_PYV" ge 3.10; then
|
||||
#sudo apt-get -y install python${F2B_PY/2/}-aiosmtpd || echo 'aiosmtpd not available'
|
||||
python -m pip install aiosmtpd || echo 'aiosmtpd not available'
|
||||
fi
|
||||
|
||||
- name: Before scripts
|
||||
run: |
|
||||
cd "$GITHUB_WORKSPACE"
|
||||
# Manually execute 2to3 for now
|
||||
if [[ "$F2B_PY" = 3 ]]; then echo "2to3 ..." && ./fail2ban-2to3; fi
|
||||
_debug() { echo -n "$1 "; err=$("${@:2}" 2>&1) && echo 'OK' || echo -e "FAIL\n$err"; }
|
||||
# (debug) output current preferred encoding:
|
||||
_debug 'Encodings:' python -c 'import locale, sys; from fail2ban.helpers import PREFER_ENC; print(PREFER_ENC, locale.getpreferredencoding(), (sys.stdout and sys.stdout.encoding))'
|
||||
echo 'Encodings:' $(python -c 'import locale, sys; from fail2ban.helpers import PREFER_ENC; print(PREFER_ENC, locale.getpreferredencoding(), (sys.stdout and sys.stdout.encoding))')
|
||||
# (debug) backend availabilities:
|
||||
echo 'Backends:'
|
||||
_debug '- systemd:' python -c 'from fail2ban.server.filtersystemd import FilterSystemd'
|
||||
|
|
@ -80,14 +88,8 @@ jobs:
|
|||
|
||||
- name: Test suite
|
||||
run: |
|
||||
if [[ "$F2B_PY" = 2 ]]; then
|
||||
python setup.py test
|
||||
elif dpkg --compare-versions "$F2B_PYV" lt 3.10; then
|
||||
python bin/fail2ban-testcases --verbosity=2
|
||||
else
|
||||
echo "Skip systemd backend since systemd-python module must be fixed for python >= v.3.10 in GHA ..."
|
||||
python bin/fail2ban-testcases --verbosity=2 -i "[sS]ystemd|[jJ]ournal"
|
||||
fi
|
||||
#python setup.py test
|
||||
python bin/fail2ban-testcases --verbosity=2
|
||||
|
||||
#- name: Test suite (debug some systemd tests only)
|
||||
#run: python bin/fail2ban-testcases --verbosity=2 "[sS]ystemd|[jJ]ournal"
|
||||
|
|
|
|||
32
.github/workflows/publish.yml
vendored
Normal file
32
.github/workflows/publish.yml
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
name: Upload Package to PyPI
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
release:
|
||||
types: [created]
|
||||
|
||||
jobs:
|
||||
pypi-publish:
|
||||
name: Publish release to PyPI
|
||||
runs-on: ubuntu-latest
|
||||
environment:
|
||||
name: pypi
|
||||
url: https://pypi.org/p/fail2ban
|
||||
permissions:
|
||||
id-token: write
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.x"
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip || echo "can't upgrade pip"
|
||||
pip install setuptools wheel || echo "can't install/update setuptools or wheel"
|
||||
- name: Build package
|
||||
run: |
|
||||
# python -m build ...
|
||||
python setup.py sdist bdist_wheel
|
||||
- name: Publish package distributions to PyPI
|
||||
uses: pypa/gh-action-pypi-publish@release/v1
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -10,3 +10,4 @@ htmlcov
|
|||
__pycache__
|
||||
.vagrant/
|
||||
.idea/
|
||||
.venv/
|
||||
|
|
|
|||
17
.project
17
.project
|
|
@ -1,17 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>fail2ban-unstable</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.python.pydev.PyDevBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.python.pydev.pythonNature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
82
.travis.yml
82
.travis.yml
|
|
@ -1,82 +0,0 @@
|
|||
# vim ft=yaml
|
||||
# travis-ci.org definition for Fail2Ban build
|
||||
# https://travis-ci.org/fail2ban/fail2ban/
|
||||
|
||||
#os: linux
|
||||
|
||||
language: python
|
||||
dist: xenial
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
include:
|
||||
- python: 2.7
|
||||
#- python: pypy
|
||||
- python: 3.4
|
||||
- python: 3.5
|
||||
- python: 3.6
|
||||
- python: 3.7
|
||||
- python: 3.8
|
||||
- python: 3.9-dev
|
||||
- python: pypy3.5
|
||||
before_install:
|
||||
- echo "running under $TRAVIS_PYTHON_VERSION"
|
||||
- if [[ $TRAVIS_PYTHON_VERSION == 2* || $TRAVIS_PYTHON_VERSION == pypy* && $TRAVIS_PYTHON_VERSION != pypy3* ]]; then export F2B_PY=2; fi
|
||||
- if [[ $TRAVIS_PYTHON_VERSION == 3* || $TRAVIS_PYTHON_VERSION == pypy3* ]]; then export F2B_PY=3; fi
|
||||
- echo "Set F2B_PY=$F2B_PY"
|
||||
- travis_retry sudo apt-get update -qq
|
||||
# Set this so sudo executes the correct python binary
|
||||
# Anything not using sudo will already have the correct environment
|
||||
- export VENV_BIN="$VIRTUAL_ENV/bin" && echo "VENV_BIN set to $VENV_BIN"
|
||||
install:
|
||||
# Install Python packages / dependencies
|
||||
# coverage
|
||||
- travis_retry pip install coverage
|
||||
# coveralls (note coveralls doesn't support 2.6 now):
|
||||
#- if [[ $TRAVIS_PYTHON_VERSION != 2.6* ]]; then F2B_COV=1; else F2B_COV=0; fi
|
||||
- F2B_COV=1
|
||||
- if [[ "$F2B_COV" = 1 ]]; then travis_retry pip install coveralls; fi
|
||||
# codecov:
|
||||
- travis_retry pip install codecov
|
||||
# dnspython or dnspython3
|
||||
- if [[ "$F2B_PY" = 2 ]]; then travis_retry pip install dnspython || echo 'not installed'; fi
|
||||
- if [[ "$F2B_PY" = 3 ]]; then travis_retry pip install dnspython3 || echo 'not installed'; fi
|
||||
# python systemd bindings:
|
||||
- if [[ "$F2B_PY" = 2 ]]; then travis_retry sudo apt-get install -qq python-systemd || echo 'not installed'; fi
|
||||
- if [[ "$F2B_PY" = 3 ]]; then travis_retry sudo apt-get install -qq python3-systemd || echo 'not installed'; fi
|
||||
# gamin - install manually (not in PyPI) - travis-ci system Python is 2.7
|
||||
- if [[ $TRAVIS_PYTHON_VERSION == 2.7 ]]; then (travis_retry sudo apt-get install -qq python-gamin && cp /usr/share/pyshared/gamin.py /usr/lib/pyshared/python2.7/_gamin.so $VIRTUAL_ENV/lib/python2.7/site-packages/) || echo 'not installed'; fi
|
||||
# pyinotify
|
||||
- travis_retry pip install pyinotify || echo 'not installed'
|
||||
# Install helper tools
|
||||
- sudo apt-get install shellcheck
|
||||
before_script:
|
||||
# Manually execute 2to3 for now
|
||||
- if [[ "$F2B_PY" = 3 ]]; then ./fail2ban-2to3; fi
|
||||
# (debug) output current preferred encoding:
|
||||
- python -c 'import locale, sys; from fail2ban.helpers import PREFER_ENC; print(PREFER_ENC, locale.getpreferredencoding(), (sys.stdout and sys.stdout.encoding))'
|
||||
script:
|
||||
# Keep the legacy setup.py test approach of checking coverage for python2
|
||||
- if [[ "$F2B_PY" = 2 ]]; then coverage run setup.py test; fi
|
||||
# Coverage doesn't pick up setup.py test with python3, so run it directly (with same verbosity as from setup)
|
||||
- if [[ "$F2B_PY" = 3 ]]; then coverage run bin/fail2ban-testcases --verbosity=2; fi
|
||||
# Use $VENV_BIN (not python) or else sudo will always run the system's python (2.7)
|
||||
- sudo $VENV_BIN/pip install .
|
||||
# Doc files should get installed on Travis under Linux (some builds/python's seem to use another path segment)
|
||||
- test -e /usr/share/doc/fail2ban/FILTERS && echo 'found' || echo 'not found'
|
||||
# Test initd script
|
||||
- shellcheck -s bash -e SC1090,SC1091 files/debian-initd
|
||||
after_success:
|
||||
- if [[ "$F2B_COV" = 1 ]]; then coveralls; fi
|
||||
- codecov
|
||||
|
||||
# Might be worth looking into
|
||||
#notifications:
|
||||
# email: true
|
||||
# irc:
|
||||
# channels: "irc.freenode.org#fail2ban"
|
||||
# template:
|
||||
# - "%{repository}@%{branch}: %{message} (%{build_url})"
|
||||
# on_success: change
|
||||
# on_failure: change
|
||||
# skip_join: true
|
||||
35
.typos.toml
Normal file
35
.typos.toml
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
[files]
|
||||
extend-exclude = [
|
||||
".git/",
|
||||
".codespellrc",
|
||||
"fail2ban/tests/files/logs/",
|
||||
]
|
||||
ignore-hidden = false
|
||||
|
||||
[default]
|
||||
extend-ignore-re = [
|
||||
"Christoph Theis",
|
||||
"\\[[0-9a-f]{7,8}\\]",
|
||||
"hash_[0-9a-f]{38}",
|
||||
"\t[0-9.-]+[ A-Z]+",
|
||||
"Erreur d'authentification",
|
||||
"WebEMailExtrac",
|
||||
"ssh2: RSA 14:ba:xx",
|
||||
"\\[Cc\\]lient",
|
||||
"\\[Gg\\]ot",
|
||||
"\\[nN\\]ot",
|
||||
"\\[Uu\\]nknown",
|
||||
"\\[uU\\]ser",
|
||||
"\\[Uu\\]\\(\\?:ser",
|
||||
]
|
||||
|
||||
[default.extend-words]
|
||||
"alls" = "alls"
|
||||
"helo" = "helo"
|
||||
|
||||
[default.extend-identifiers]
|
||||
"failManager2nd" = "failManager2nd"
|
||||
"log2nd" = "log2nd"
|
||||
"routeros" = "routeros"
|
||||
"REFERERS" = "REFERERS"
|
||||
"tre_search" = "tre_search"
|
||||
228
ChangeLog
228
ChangeLog
|
|
@ -7,6 +7,208 @@
|
|||
Fail2Ban: Changelog
|
||||
===================
|
||||
|
||||
ver. 1.1.1-dev-1 (20??/??/??) - development nightly edition
|
||||
-----------
|
||||
|
||||
### Compatibility
|
||||
* `action.d/iptables.conf` rewritten due to support of multiple chains (gh-3909), therefore user-level derivations
|
||||
(action including iptables-based action) may become incompatible, e. g. some tags if used need to be replaced,
|
||||
e. g. `<chain>` with `$chain` or `<_ipt_for_proto-iter>` with `<_ipt-iter>`;
|
||||
* `filter.d/exim.conf` - several rules of mode `normal` moved to new mode `more`, because of too risky handling (see [gh-3940](https://github.com/fail2ban/fail2ban/pull/3940)),
|
||||
to use it as before set `mode = more` for exim jail, but be aware of the consequences.
|
||||
|
||||
### Fixes
|
||||
* fixes `systemd` bug with missing journal descriptor after rotation by reopening of journal if it is recognized as not alive (gh-3929)
|
||||
* improve threaded clean-up of all filters, new thread functions `afterStop` (to force clean-up after stop) and `done`, invoking `afterStop` once
|
||||
* ensure journal-reader is always closed (additional prevention against leaks and "too many open files"), thereby avoid sporadic segfault
|
||||
in systemd module (see https://github.com/systemd/python-systemd/issues/143)
|
||||
* fixes `systemd` causing "too many open files" error for a lot of journal files and large amount of systemd jails
|
||||
(see new parameter `rotated` below, gh-3391);
|
||||
* passing of arguments from jails to action or filter will affect conditional section too (gh-4069),
|
||||
e. g. setting `blocktype="DROP"` via jail for action would now apply for IPv4 and IPv6 chains,
|
||||
to submit different `blocktype` for IPv4 and IPv6 from jail, one can pass them like in this example:
|
||||
`banaction = iptables-ipset[blocktype="...", blocktype?family=inet6="..."]`
|
||||
* `jail.conf`:
|
||||
- default banactions need to be specified in `paths-*.conf` (maintainer level) now
|
||||
- since stock fail2ban includes `paths-debian.conf` by default, banactions are `nftables`
|
||||
(can be overwritten in `jail.local` by user)
|
||||
* `paths-common.conf`:
|
||||
- changed default `mysql_log` path (default `logpath` of `mysqld-auth` jail without maintainer overrides, gh-3932)
|
||||
* `paths-debian.conf`:
|
||||
- default banactions are `nftables`
|
||||
- sshd backend switched to `systemd` (gh-3292)
|
||||
- postfix backend switched to `systemd` (gh-3527)
|
||||
* `action.d/firewallcmd-ipset.conf`:
|
||||
- rename `ipsettype` to `ipsetbackend` (gh-2620), parameter `ipsettype` will be used now to the real set type (gh-3760)
|
||||
* `action.d/nftables.conf`:
|
||||
- action fixed for SELinux without execmem permission, rewrite capturing with `grep -P` using `grep -E` or `sed`
|
||||
(PCRE-JIT by `grep -P` may cause SELinux denial for execmem, see gh-4137)
|
||||
* `action.d/xarf-login-attack.conf` - ignore errors or warnings in output of `dig` provided as comment (gh-4068)
|
||||
* `filter.d/apache-badbots.conf`, `filter.d/apache-fakegooglebot.conf`:
|
||||
- regexs rewritten more strict (removed catch-alls, etc);
|
||||
- regexs fixed to match lines with vhost in accesslog (gh-1594)
|
||||
* `filter.d/apache-noscript.conf` - consider new log-format with "AH02811: stderr from /..." (gh-3900)
|
||||
* `filter.d/apache-overflows.conf` - consider AH10244: invalid URI path (gh-3778, gh-3900)
|
||||
* `filter.d/asterisk.conf` - fixed RE for "no matching endpoint" with retry info (like `after X tries in Y ms`) at end,
|
||||
loosening of end anchor (ignore any simple text tokens at end if no single quote found), gh-4037
|
||||
* `filter.d/exim.conf`:
|
||||
- several rules of mode `normal` moved to new mode `more`, because of too risky handling (gh-3940),
|
||||
thereby mode `aggressive` is not affected, because it fully includes mode `more` now;
|
||||
- mode `aggressive` extended to catch dropped by ACL failures, e.g. "ACL: Country is banned"
|
||||
* `filter.d/freeswitch.conf` - bypass some new info in prefix before [WARNING] (changed default `_pref_line`),
|
||||
FreeSWITCH log line prefix has changed in newer versions (gh-3143)
|
||||
* `filter.d/lighttpd-auth.conf` - fixed regex (if failures generated by systemd-journal), bypass several prefixes now (gh-3955)
|
||||
* `filter.d/postfix.conf`:
|
||||
- consider CONNECT and other rejected commands as a valid `_pref` (gh-3800)
|
||||
- default `_daemon` in prefix-line is loosened - can match everything starting with word postfix, like `postfix-example.com/smtpd` (gh-3297)
|
||||
- add optional `NOQUEUE:` prefix to ddos regex (gh-4072)
|
||||
- internal parameter `_pref` is renamed to `_cmd`, `_pref` matches now optional prefix like `NOQUEUE: ` etc
|
||||
- modes `ddos` and `aggressive` extended to match `rate limit exceeded` for connection or message delivery request rates (gh-3265, gh-4073)
|
||||
* `filter.d/dropbear.conf`:
|
||||
- recognizes extra pid/timestamp if logged into stdout/journal, added `journalmatch` (gh-3597)
|
||||
- failregex extended to match different format of "Exit before auth" message (gh-3791)
|
||||
* `filter.d/recidive.conf` - restore possibility to set jail name in the filter, _jailname is positive now (gh-3769)
|
||||
* `filter.d/roundcube-auth.conf` - improved RE better matching log format of roundcube version 1.4+ (gh-3816)
|
||||
* `filter.d/sendmail-reject.conf`: (gh-4020)
|
||||
- support `<F-MLFID>` for BSD-style logfiles
|
||||
- add match for `User unknown` to default
|
||||
- the relay field may not always have a hostname before the ip address
|
||||
- mode `aggressive` enables match for `lost input channel` and `Cannot resolve PTR record`
|
||||
* `filter.d/sshd.conf`:
|
||||
- adapted to conform possible new daemon name sshd-session, since OpenSSH 9.8
|
||||
several log messages will be tagged with as originating from a process named "sshd-session" rather than "sshd" (gh-3782)
|
||||
- `ddos` and `aggressive` modes: regex extended for timeout before authentication (optional connection from part, gh-3907)
|
||||
* `filter.d/vsftpd.conf` - fixed regex (if failures generated by systemd-journal, gh-3954)
|
||||
* `filter.d/froxlor-auth.conf` - updated the regex to the new logging situation for froxlor and changed logpath in jail.conf (gh-4075).
|
||||
|
||||
### New Features and Enhancements
|
||||
* backend `systemd` extended with new parameter `rotated` (default `false`, as prevention against "too many open files"),
|
||||
that allows to monitor only actual journals and ignore now a lot of rotated files by default; so can drastically reduce
|
||||
amount of used file descriptors, normally to 1 or 2 descriptors per jail (gh-3391)
|
||||
* new jail option `skip_if_nologs` to ignore jail if no `logpath` matches found, fail2ban continue to start with warnings/errors,
|
||||
thus other jails become running (gh-2756)
|
||||
* implements automatic switch `backend = auto` to backend `systemd`, when the following is true (RFE gh-3768):
|
||||
- no files matching `logpath` found for this jail;
|
||||
- no `systemd_if_nologs = false` is specified for the jail (`true` by default);
|
||||
- option `journalmatch` is set for the jail or its filter (otherwise it'd be too heavy to allow all auto-jails,
|
||||
even if they have never been foreseen for journal monitoring);
|
||||
(option `skip_if_nologs` will be ignored if we could switch backend to `systemd`)
|
||||
* configuration `ignoreip` and fail2ban-client commands `addignoreip`/`delignoreip` extended with `file:...` syntax
|
||||
to ignore IPs from file-ip-set (containing IP, subnet, dns/fqdn or raw strings); the file would be read lazy on demand,
|
||||
by first ban (and automatically reloaded by update after small latency to avoid expensive stats check on every compare);
|
||||
the entries inside the file can be separated by comma, space or new line with optional comments (text following chars
|
||||
`#` or `;` after space or newline would be ignored up to next newline)
|
||||
* `action.d/apprise.conf` - updated to support tagging and other command line args (gh-4141)
|
||||
* `action.d/*-ipset.conf`:
|
||||
- parameter `ipsettype` to set type of ipset, e. g. hash:ip, hash:net, etc (gh-3760)
|
||||
* `action.d/iptables.conf` - action and few derivatives of it extended to handle multiple chains,
|
||||
e. g. would also accept `chain = INPUT,FORWARD` (gh-3909)
|
||||
* `action.d/nftables.conf` (gh-3291):
|
||||
- new parameter `addr_options` for addr-set (default `flags interval\;`, allows to store CIDR or address ranges);
|
||||
can be set to empty value to create simple addresses set (restore previous behavior).
|
||||
* `action.d/firewallcmd-rich-*.conf` - fixed incorrect quoting, disabling port variable expansion
|
||||
by substitution of rich rule (gh-3815)
|
||||
* `filter.d/dovecot.conf`:
|
||||
- add support for latest Dovecot 2.4 release (gh-4016)
|
||||
- mode `aggressive` covered new variant for `no auth attempts in X secs` with `Login aborted` and `(no_auth_attempts)`
|
||||
- mode `aggressive` extended to match `disconnected during TLS handshake` with `no application protocol` and `no shared cipher`
|
||||
* `filter.d/nginx-http-auth.conf`:
|
||||
- extended with `prefregex` to capture content of error only (bypass common prefix and suffix, like server, request, host, referrer);
|
||||
- extended to match PAM authentication failures (gh-4071)
|
||||
- modes `fallback` and `aggressive` extended to match more SSL failures by SSL_do_handshake or SSL_read (gh-4142, gh-2881)
|
||||
* `filter.d/nginx-limit-req.conf` - extended to ban hosts failed by limit connection in ngx_http_limit_conn_module (gh-3674, gh-4047)
|
||||
* `filter.d/proxmox.conf` - add support to Proxmox Web GUI (gh-2966)
|
||||
* `filter.d/openvpn.conf` - new filter and jail for openvpn recognizing failed TLS handshakes (gh-2702)
|
||||
* `filter.d/sendmail-reject.conf` - also recognize "Domain of sender address ... does not resolve" (gh-4035)
|
||||
* `filter.d/vaultwarden.conf` - new filter and jail for Vaultwarden (gh-3979)
|
||||
* `filter.d/xrdp.conf` - new filter for XRDP, an open source RDP server (gh-3254)
|
||||
* `fail2ban-regex` extended with new option `-i` or `--invert` to output not-matched lines by `-o` or `--out` (gh-4001)
|
||||
|
||||
|
||||
ver. 1.1.0 (2024/04/25) - object-found--norad-59479-cospar-2024-069a--altitude-36267km
|
||||
-----------
|
||||
|
||||
### Compatibility
|
||||
* the minimum supported python version is now 3.5, if you have previous python version
|
||||
you can use the 0.11 or 1.0 version of fail2ban or upgrade python (or even build it from source).
|
||||
|
||||
### Fixes
|
||||
* circumvent SEGFAULT in a python's socket module by getaddrinfo with disabled IPv6 (gh-3438)
|
||||
* avoid sporadic error in pyinotify backend if pending file deleted in other thread, e. g. by flushing logs (gh-3635)
|
||||
* `action.d/cloudflare-token.conf` - fixes gh-3479, url-encode args by unban
|
||||
* `action.d/*ipset*`: make `maxelem` ipset option configurable through banaction arguments (gh-3564)
|
||||
* `filter.d/apache-common.conf` - accepts remote besides client (gh-3622)
|
||||
* `filter.d/mysqld-auth.conf` - matches also if no suffix in message (mariadb 10.3 log format, gh-3603)
|
||||
* `filter.d/nginx-*.conf` - nginx error-log filters extended with support of journal format (gh-3646)
|
||||
* `filter.d/postfix.conf`:
|
||||
- "rejected" rule extended to match "Access denied" too (gh-3474)
|
||||
- avoid double counting ('lost connection after AUTH' together with message 'disconnect ...', gh-3505)
|
||||
- add Sender address rejected: Malformed DNS server reply (gh-3590)
|
||||
- add to postfix syslog daemon format (gh-3690)
|
||||
- change journalmatch postfix, allow sub-units with postfix@-.service (gh-3692)
|
||||
* `filter.d/recidive.conf`: support for systemd-journal, conditional RE depending on logtype (for file or journal, gh-3693)
|
||||
* `filter.d/slapd.conf` - filter rewritten for single-line processing, matches errored result without `text=...` (gh-3604)
|
||||
|
||||
### New Features and Enhancements
|
||||
* supports python 3.12 and 3.13 (gh-3487)
|
||||
* bundling async modules removed in python 3.12+ (fallback to local libraries pyasyncore/pyasynchat if import would miss them, gh-3487)
|
||||
* `fail2ban-client` extended (gh-2975):
|
||||
- `fail2ban-client status --all [flavor]` - returns status of fail2ban and all jails in usual form
|
||||
- `fail2ban-client stats` - returns statistic in form of table (jail, backend, found and banned counts)
|
||||
- `fail2ban-client statistic` or `fail2ban-client statistics` - same as `fail2ban-client stats` (aliases for stats)
|
||||
- `fail2ban-client status --all stats` - (undocumented, flavor "stats") returns statistic of all jails in form of python dict
|
||||
* `fail2ban-regex` extended to load settings from jail (by simple name it'd prefer jail to the filter now, gh-2655);
|
||||
to load the settings from filter one could use:
|
||||
```diff
|
||||
- fail2ban-regex ... sshd ; # jail
|
||||
+ fail2ban-regex ... sshd.conf ; # filter
|
||||
# or:
|
||||
+ fail2ban-regex ... filter.d/sshd ; # filter
|
||||
```
|
||||
* better auto-detection for IPv6 support (`allowipv6 = auto` by default), trying to check sysctl net.ipv6.conf.all.disable_ipv6
|
||||
(value read from `/proc/sys/net/ipv6/conf/all/disable_ipv6`) if available, otherwise seeks over local IPv6 from network interfaces
|
||||
if available for platform and uses DNS to find local IPv6 as a fallback only
|
||||
* improve `ignoreself` by considering all local addresses from network interfaces additionally to IPs from hostnames (gh-3132)
|
||||
* `action.d/mikrotik.conf` - new action for mikrotik routerOS, adds and removes entries from address lists on the router (gh-2860)
|
||||
* `action.d/pf.conf` - pf action extended with support of `protocol=all` (gh-3503)
|
||||
* `action.d/smtp.py` - added optional support for TLS connections via the `ssl` arg.
|
||||
* `filter.d/dante.conf` - new filter for Dante SOCKS server (gh-2112)
|
||||
* `filter.d/exim.conf`, `filter.d/exim-spam.conf`:
|
||||
- messages are prefiltered by `prefregex` now
|
||||
- filter can bypass additional timestamp or pid that may be logged via systemd-journal or syslog-ng (gh-3060)
|
||||
- rewrite host line regex for all varied exim's log_selector states (gh-3263, gh-3701, gh-3702)
|
||||
- fixed "dropped: too many ..." regex, also matching unrecognized commands now (gh-3502)
|
||||
* `filter.d/named-refused.conf` - denied allows any reason in parenthesis as suffix (gh-3697)
|
||||
* `filter.d/nginx-forbidden.conf` - new filter to ban forbidden locations, e. g. using `deny` directive (gh-2226)
|
||||
* `filter.d/routeros-auth.conf` - new filter detecting failed login attempts in the log produced by MikroTik RouterOS
|
||||
* `filter.d/sshd.conf`:
|
||||
- avoid double counting for "maximum authentication attempts exceeded" (gh-3502)
|
||||
- message "Disconnecting ... Too many authentication failures" is not a failure anymore
|
||||
- mode `ddos`/`aggressive` extended to match new messages caused by port scanner, wrong payload on ssh port (gh-3486):
|
||||
* message authentication code incorrect [preauth]
|
||||
* connection corrupted [preauth]
|
||||
* timeout before authentication
|
||||
|
||||
|
||||
ver. 1.0.2 (2022/11/09) - finally-war-game-test-tape-not-a-nuclear-alarm
|
||||
-----------
|
||||
|
||||
### Fixes
|
||||
* backend `systemd`: code review and several fixes:
|
||||
- wait only if it is necessary, e. g. in operational mode and if no more entries retrieved (end of journal);
|
||||
- ensure we give enough time after possible rotation, vacuuming or adding/removing journal files,
|
||||
and move cursor back and forth to avoid entering dead space
|
||||
* `filter.d/named-refused.conf`:
|
||||
- support BIND named log categories, gh-3388
|
||||
- allow `info:` as possible error prefix too ("query (cache) denied" may occur as info)
|
||||
* `filter.d/dovecot.conf`:
|
||||
- fixes regression introduced in gh-3210: resolve extremely long search by repeated apply of non-greedy RE-part
|
||||
with following branches (it may be extremely slow up to infinite search depending on message), gh-3370
|
||||
- fixes regression and matches new format in aggressive mode too (amend to gh-3210)
|
||||
|
||||
### New Features and Enhancements
|
||||
|
||||
|
||||
ver. 1.0.1 (2022/09/27) - energy-equals-mass-times-the-speed-of-light-squared
|
||||
-----------
|
||||
|
||||
|
|
@ -34,7 +236,7 @@ ver. 1.0.1 (2022/09/27) - energy-equals-mass-times-the-speed-of-light-squared
|
|||
* [stability] solves race condition with uncontrolled growth of failure list (jail with too many matches,
|
||||
that did not cause ban), behavior changed to ban ASAP, gh-2945
|
||||
* fixes search for the best datepattern - e. g. if line is too short, boundaries check for previously known
|
||||
unprecise pattern may fail on incomplete lines (logging break-off, no flush, etc), gh-3020
|
||||
imprecise pattern may fail on incomplete lines (logging break-off, no flush, etc), gh-3020
|
||||
* [stability, performance] backend `systemd`:
|
||||
- fixes error "local variable 'line' referenced before assignment", introduced in 55d7d9e2, gh-3097
|
||||
- don't update database too often (every 10 ticks or ~ 10 seconds in production)
|
||||
|
|
@ -372,7 +574,7 @@ filter = flt[logtype=short]
|
|||
* `filter.d/znc-adminlog.conf`: new filter for ZNC (IRC bouncer); requires the adminlog module to be loaded
|
||||
|
||||
### Enhancements
|
||||
* introduced new options: `dbmaxmatches` (fail2ban.conf) and `maxmatches` (jail.conf) to contol
|
||||
* introduced new options: `dbmaxmatches` (fail2ban.conf) and `maxmatches` (jail.conf) to control
|
||||
how many matches per ticket fail2ban can hold in memory and store in database (gh-2402, gh-2118);
|
||||
* fail2ban.conf: introduced new section `[Thread]` and option `stacksize` to configure default size
|
||||
of the stack for threads running in fail2ban (gh-2356), it could be set in `fail2ban.local` to
|
||||
|
|
@ -482,7 +684,7 @@ ver. 0.10.3 (2018/04/04) - the-time-is-always-right-to-do-what-is-right
|
|||
- fixed root login refused regex (optional port before preauth, gh-2080);
|
||||
- avoid banning of legitimate users when pam_unix used in combination with other password method, so
|
||||
bypass pam_unix failures if accepted available for this user gh-2070;
|
||||
- amend to gh-1263 with better handling of multiple attempts (failures for different user-names recognized immediatelly);
|
||||
- amend to gh-1263 with better handling of multiple attempts (failures for different user-names recognized immediately);
|
||||
- mode `ddos` (and `aggressive`) extended to catch `Connection closed by ... [preauth]`, so in DDOS mode
|
||||
it counts failure on closing connection within preauth-stage (gh-2085);
|
||||
* `action.d/abuseipdb.conf`: fixed curl cypher errors and comment quote-issue (gh-2044, gh-2101);
|
||||
|
|
@ -812,7 +1014,7 @@ ver. 0.10.0-alpha-1 (2016/07/14) - ipv6-support-etc
|
|||
sane environment in error case of `actioncheck`.
|
||||
* Reporting via abuseipdb.com:
|
||||
- Bans can now be reported to abuseipdb
|
||||
- Catagories must be set in the config
|
||||
- Categories must be set in the config
|
||||
- Relevant log lines included in report
|
||||
|
||||
### Enhancements
|
||||
|
|
@ -949,7 +1151,7 @@ releases.
|
|||
- Rewritten without end-anchor ($), because of potential vulnerability on very long URLs.
|
||||
* filter.d/apache-badbots.conf - extended to recognize Jorgee Vulnerability Scanner (gh-1882)
|
||||
* filter.d/asterisk.conf
|
||||
- fixed failregex AMI Asterisk authentification failed (see gh-1302)
|
||||
- fixed failregex AMI Asterisk authentication failed (see gh-1302)
|
||||
- removed invalid (vulnerable) regex blocking IPs using forign data (from header "from")
|
||||
thus not the IP-address that really originates the request (see gh-1927)
|
||||
- fixed failregex for the SQL-injection attempts with single-quotes in connect-string (see gh-2011)
|
||||
|
|
@ -1249,7 +1451,7 @@ ver. 0.9.3 (2015/08/01) - lets-all-stay-friends
|
|||
* `filter.d/roundcube-auth.conf`
|
||||
- Updated regex to work with 'errors' log (1.0.5 and 1.1.1)
|
||||
- Added regex to work with 'userlogins' log
|
||||
* `action.d/sendmail*.conf` - use LC_ALL (superseeding LC_TIME) to override
|
||||
* `action.d/sendmail*.conf` - use LC_ALL (superseding LC_TIME) to override
|
||||
locale on systems with customized LC_ALL
|
||||
* performance fix: minimizes connection overhead, close socket only at
|
||||
communication end (gh-1099)
|
||||
|
|
@ -1419,7 +1621,7 @@ ver. 0.9.1 (2014/10/29) - better, faster, stronger
|
|||
* Ignored IPs are no longer banned when being restored from persistent
|
||||
database
|
||||
* Manually unbanned IPs are now removed from persistent database, such they
|
||||
wont be banned again when Fail2Ban is restarted
|
||||
won't be banned again when Fail2Ban is restarted
|
||||
* Pass "bantime" parameter to the actions in default jail's action
|
||||
definition(s)
|
||||
* `filters.d/sieve.conf` - fixed typo in _daemon. Thanks Jisoo Park
|
||||
|
|
@ -1710,7 +1912,7 @@ those filters were used.
|
|||
all platforms to ensure permissions are the same before and after a ban.
|
||||
Closes gh-266. hostsdeny supports daemon_list now too.
|
||||
* `action.d/bsd-ipfw` - action option unused. Change blocktype to port unreach
|
||||
instead of deny for consistancy.
|
||||
instead of deny for consistency.
|
||||
* `filter.d/dovecot` - added to support different dovecot failure
|
||||
"..disallowed plaintext auth". Closes Debian bug #709324
|
||||
* `filter.d/roundcube-auth` - timezone offset can be positive or negative
|
||||
|
|
@ -1900,7 +2102,7 @@ fail2ban-users mailing list and IRC.
|
|||
### New Features
|
||||
- Yaroslav Halchenko
|
||||
* [9ba27353] Add support for `jail.d/{confilefile}` and `fail2ban.d/{configfile}`
|
||||
to provide additional flexibility to system adminstrators. Thanks to
|
||||
to provide additional flexibility to system administrators. Thanks to
|
||||
beilber for the idea. Closes gh-114.
|
||||
* [3ce53e87] Add exim filter.
|
||||
- Erwan Ben Souiden
|
||||
|
|
@ -2051,7 +2253,7 @@ ver. 0.8.7 (2012/07/31) - stable
|
|||
* [47c03a2] files/nagios - spelling/grammar fixes
|
||||
* [b083038] updated Free Software Foundation's address
|
||||
* [9092a63] changed TLDs to invalid domains, in accordance with RFC 2606
|
||||
* [642d9af,3282f86] reformated printing of jail's name to be consistent
|
||||
* [642d9af,3282f86] reformatted printing of jail's name to be consistent
|
||||
with init's info messages
|
||||
* [3282f86] uniform use of capitalized Jail in the messages
|
||||
- Leonardo Chiquitto
|
||||
|
|
@ -2396,7 +2598,7 @@ ver. 0.6.1 (2006/03/16) - stable
|
|||
- Fixed crash when time format does not match data
|
||||
- Propagated patch from Debian to fix fail2ban search path addition to the path
|
||||
search list: now it is added first. Thanks to Nick Craig-Wood
|
||||
- Added SMTP authentification for mail notification. Thanks to Markus Hoffmann
|
||||
- Added SMTP authentication for mail notification. Thanks to Markus Hoffmann
|
||||
- Removed debug mode as it is confusing for people
|
||||
- Added parsing of timestamp in TAI64N format (#1275325). Thanks to Mark
|
||||
Edgington
|
||||
|
|
@ -2429,7 +2631,7 @@ ver. 0.5.5 (2005/10/26) - beta
|
|||
further adjusted by upstream author).
|
||||
* Added -f command line parameter for [findtime].
|
||||
* Added a cleanup of firewall rules on emergency shutdown when unknown
|
||||
exception is catched.
|
||||
exception is caught.
|
||||
* Fail2ban should not crash now if a wrong file name is specified in config.
|
||||
* reordered code a bit so that log targets are setup right after background
|
||||
and then only loglevel (verbose, debug) is processed, so the warning could
|
||||
|
|
@ -2518,7 +2720,7 @@ ver. 0.3.1 (2005/03/31) - beta
|
|||
|
||||
ver. 0.3.0 (2005/02/24) - beta
|
||||
----------
|
||||
- Re-writting of parts of the code in order to handle several log files with
|
||||
- Re-writing of parts of the code in order to handle several log files with
|
||||
different rules
|
||||
- Removed `sshd.py` because it is no more needed
|
||||
- Fixed a bug when exiting with IP in the ban list
|
||||
|
|
|
|||
30
FILTERS
30
FILTERS
|
|
@ -129,7 +129,7 @@ Date/Time
|
|||
---------
|
||||
|
||||
At the moment, Fail2Ban depends on log lines to have time stamps. That is why
|
||||
before starting to develop failregex, check if your log line format known to
|
||||
before starting to develop failregex, check if your log line format is known to
|
||||
Fail2Ban. Copy the time component from the log line and append an IP address to
|
||||
test with following command::
|
||||
|
||||
|
|
@ -232,16 +232,24 @@ the <> at the start so regex should be similar to '^<> error <HOST> is evil$' us
|
|||
|
||||
The following general rules apply to regular expressions:
|
||||
|
||||
* ensure regexes start with a ^ and are as restrictive as possible. E.g. do not
|
||||
use .* if \d+ is sufficient;
|
||||
* ensure regexes are anchored (e. g. start with a ^) and are as restrictive
|
||||
as possible. E.g. do not use catch-alls .+ or .* if \d+ or [^"]* is sufficient.
|
||||
Basically avoid the catch-alls where it is possible, especially non-greedy
|
||||
catch-alls on RE with many branches or ambiguous matches;
|
||||
* use functionality of Python regexes defined in the standard Python re library
|
||||
http://docs.python.org/2/library/re.html;
|
||||
* make regular expressions readable (as much as possible). E.g.
|
||||
(?:...) represents a non-capturing regex but (...) is more readable, thus
|
||||
preferred.
|
||||
https://docs.python.org/library/re.html;
|
||||
* try to write regular expressions as efficient as possible. E.g. do not write
|
||||
several REs for almost the same messages, just with A or B or C, if they can
|
||||
be matched by single RE using | operator like ...(?:A|B|C)... and order them
|
||||
by their frequency, so A before B and C, if A is more frequent or will match
|
||||
faster;
|
||||
* make regular expressions readable (as much as possible), but only if it is
|
||||
justified. E.g. (?:...) represents a non-capturing regex and (...) is more
|
||||
readable, but capturing groups make the RE a bit slower, thus (?:...) may be
|
||||
more preferable.
|
||||
|
||||
If you have only a basic knowledge of regular repressions we advise to read
|
||||
http://docs.python.org/2/library/re.html first. It doesn't take long and would
|
||||
https://docs.python.org/library/re.html first. It doesn't take long and would
|
||||
remind you e.g. which characters you need to escape and which you don't.
|
||||
|
||||
Developing/testing a regex
|
||||
|
|
@ -265,10 +273,6 @@ Take note of -l heavydebug / -l debug and -v as they might be very useful.
|
|||
parts are constrained and different formats depending on configuration or
|
||||
less common usages.
|
||||
|
||||
.. TIP::
|
||||
For looking through source code - http://sourcecodebrowser.com/ . It has
|
||||
call graphs and can browse different versions.
|
||||
|
||||
.. TIP::
|
||||
Some applications log spaces at the end. If you are not sure add \s*$ as
|
||||
the end part of the regex.
|
||||
|
|
@ -309,6 +313,8 @@ So more specifically in the [filter] section in jail.conf:
|
|||
Submit github pull request (See "Pull Requests" above) for
|
||||
github.com/fail2ban/fail2ban containing your great work.
|
||||
|
||||
You may also consider https://github.com/fail2ban/fail2ban/wiki/Best-practice
|
||||
|
||||
Filter Security
|
||||
===============
|
||||
|
||||
|
|
|
|||
14
MANIFEST
14
MANIFEST
|
|
@ -40,6 +40,7 @@ config/action.d/mail.conf
|
|||
config/action.d/mail-whois-common.conf
|
||||
config/action.d/mail-whois.conf
|
||||
config/action.d/mail-whois-lines.conf
|
||||
config/action.d/mikrotik.conf
|
||||
config/action.d/mynetwatchman.conf
|
||||
config/action.d/netscaler.conf
|
||||
config/action.d/nftables-allports.conf
|
||||
|
|
@ -90,6 +91,7 @@ config/filter.d/counter-strike.conf
|
|||
config/filter.d/courier-auth.conf
|
||||
config/filter.d/courier-smtp.conf
|
||||
config/filter.d/cyrus-imap.conf
|
||||
config/filter.d/dante.conf
|
||||
config/filter.d/directadmin.conf
|
||||
config/filter.d/domino-smtp.conf
|
||||
config/filter.d/dovecot.conf
|
||||
|
|
@ -121,6 +123,8 @@ config/filter.d/nagios.conf
|
|||
config/filter.d/named-refused.conf
|
||||
config/filter.d/nginx-bad-request.conf
|
||||
config/filter.d/nginx-botsearch.conf
|
||||
config/filter.d/nginx-error-common.conf
|
||||
config/filter.d/nginx-forbidden.conf
|
||||
config/filter.d/nginx-http-auth.conf
|
||||
config/filter.d/nginx-limit-req.conf
|
||||
config/filter.d/nsd.conf
|
||||
|
|
@ -138,6 +142,7 @@ config/filter.d/pure-ftpd.conf
|
|||
config/filter.d/qmail.conf
|
||||
config/filter.d/recidive.conf
|
||||
config/filter.d/roundcube-auth.conf
|
||||
config/filter.d/routeros-auth.conf
|
||||
config/filter.d/scanlogd.conf
|
||||
config/filter.d/screensharingd.conf
|
||||
config/filter.d/selinux-common.conf
|
||||
|
|
@ -175,7 +180,6 @@ CONTRIBUTING.md
|
|||
COPYING
|
||||
.coveragerc
|
||||
DEVELOP
|
||||
fail2ban-2to3
|
||||
fail2ban/client/actionreader.py
|
||||
fail2ban/client/beautifier.py
|
||||
fail2ban/client/configparserinc.py
|
||||
|
|
@ -191,6 +195,8 @@ fail2ban/client/filterreader.py
|
|||
fail2ban/client/__init__.py
|
||||
fail2ban/client/jailreader.py
|
||||
fail2ban/client/jailsreader.py
|
||||
fail2ban/compat/asynchat.py
|
||||
fail2ban/compat/asyncore.py
|
||||
fail2ban/exceptions.py
|
||||
fail2ban/helpers.py
|
||||
fail2ban/__init__.py
|
||||
|
|
@ -204,7 +210,6 @@ fail2ban/server/datedetector.py
|
|||
fail2ban/server/datetemplate.py
|
||||
fail2ban/server/failmanager.py
|
||||
fail2ban/server/failregex.py
|
||||
fail2ban/server/filtergamin.py
|
||||
fail2ban/server/filterpoll.py
|
||||
fail2ban/server/filter.py
|
||||
fail2ban/server/filterpyinotify.py
|
||||
|
|
@ -272,7 +277,7 @@ fail2ban/tests/files/config/apache-auth/noentry/.htaccess
|
|||
fail2ban/tests/files/config/apache-auth/README
|
||||
fail2ban/tests/files/database_v1.db
|
||||
fail2ban/tests/files/database_v2.db
|
||||
fail2ban/tests/files/filter.d/substition.conf
|
||||
fail2ban/tests/files/filter.d/substitution.conf
|
||||
fail2ban/tests/files/filter.d/testcase01.conf
|
||||
fail2ban/tests/files/filter.d/testcase02.conf
|
||||
fail2ban/tests/files/filter.d/testcase02.local
|
||||
|
|
@ -300,6 +305,7 @@ fail2ban/tests/files/logs/counter-strike
|
|||
fail2ban/tests/files/logs/courier-auth
|
||||
fail2ban/tests/files/logs/courier-smtp
|
||||
fail2ban/tests/files/logs/cyrus-imap
|
||||
fail2ban/tests/files/logs/dante
|
||||
fail2ban/tests/files/logs/directadmin
|
||||
fail2ban/tests/files/logs/domino-smtp
|
||||
fail2ban/tests/files/logs/dovecot
|
||||
|
|
@ -329,6 +335,7 @@ fail2ban/tests/files/logs/nagios
|
|||
fail2ban/tests/files/logs/named-refused
|
||||
fail2ban/tests/files/logs/nginx-bad-request
|
||||
fail2ban/tests/files/logs/nginx-botsearch
|
||||
fail2ban/tests/files/logs/nginx-forbidden
|
||||
fail2ban/tests/files/logs/nginx-http-auth
|
||||
fail2ban/tests/files/logs/nginx-limit-req
|
||||
fail2ban/tests/files/logs/nsd
|
||||
|
|
@ -346,6 +353,7 @@ fail2ban/tests/files/logs/pure-ftpd
|
|||
fail2ban/tests/files/logs/qmail
|
||||
fail2ban/tests/files/logs/recidive
|
||||
fail2ban/tests/files/logs/roundcube-auth
|
||||
fail2ban/tests/files/logs/routeros-auth
|
||||
fail2ban/tests/files/logs/scanlogd
|
||||
fail2ban/tests/files/logs/screensharingd
|
||||
fail2ban/tests/files/logs/selinux-ssh
|
||||
|
|
|
|||
27
README.md
27
README.md
|
|
@ -2,7 +2,7 @@
|
|||
/ _|__ _(_) |_ ) |__ __ _ _ _
|
||||
| _/ _` | | |/ /| '_ \/ _` | ' \
|
||||
|_| \__,_|_|_/___|_.__/\__,_|_||_|
|
||||
v1.0.1.dev1 20??/??/??
|
||||
v1.1.0.dev1 20??/??/??
|
||||
|
||||
## Fail2Ban: ban hosts that cause multiple authentication errors
|
||||
|
||||
|
|
@ -18,7 +18,7 @@ attempts, it cannot eliminate the risk presented by weak authentication.
|
|||
Set up services to use only two factor, or public/private authentication
|
||||
mechanisms if you really want to protect services.
|
||||
|
||||
<img src="http://www.worldipv6launch.org/wp-content/themes/ipv6/downloads/World_IPv6_launch_logo.svg" height="52pt"/> | Since v0.10 fail2ban supports the matching of IPv6 addresses.
|
||||
<img src="http://www.worldipv6launch.org/wp-content/themes/ipv6/downloads/World_IPv6_launch_logo.svg" style="height:52pt;"/> | Since v0.10 fail2ban supports the matching of IPv6 addresses.
|
||||
------|------
|
||||
|
||||
This README is a quick introduction to Fail2Ban. More documentation, FAQ, and HOWTOs
|
||||
|
|
@ -29,29 +29,30 @@ and the website: https://www.fail2ban.org
|
|||
Installation:
|
||||
-------------
|
||||
|
||||
**It is possible that Fail2Ban is already packaged for your distribution. In
|
||||
this case, you should use that instead.**
|
||||
Fail2Ban is likely already packaged for your Linux distribution and [can be installed with a simple command](https://github.com/fail2ban/fail2ban/wiki/How-to-install-fail2ban-packages).
|
||||
|
||||
If your distribution is not listed, you can install from GitHub:
|
||||
|
||||
Required:
|
||||
- [Python2 >= 2.7 or Python >= 3.2](https://www.python.org) or [PyPy](https://pypy.org)
|
||||
- python-setuptools, python-distutils or python3-setuptools for installation from source
|
||||
- [Python >= 3.5](https://www.python.org) or [PyPy3](https://pypy.org)
|
||||
- python-setuptools (or python3-setuptools) for installation from source
|
||||
|
||||
Optional:
|
||||
- [pyinotify >= 0.8.3](https://github.com/seb-m/pyinotify), may require:
|
||||
* Linux >= 2.6.13
|
||||
- [gamin >= 0.0.21](http://www.gnome.org/~veillard/gamin)
|
||||
- [systemd >= 204](http://www.freedesktop.org/wiki/Software/systemd) and python bindings:
|
||||
* [python-systemd package](https://www.freedesktop.org/software/systemd/python-systemd/index.html)
|
||||
- [dnspython](http://www.dnspython.org/)
|
||||
- [pyasyncore](https://pypi.org/project/pyasyncore/) and [pyasynchat](https://pypi.org/project/pyasynchat/) (normally bundled-in within fail2ban, for python 3.12+ only)
|
||||
|
||||
|
||||
To install:
|
||||
|
||||
tar xvfj fail2ban-1.0.1.tar.bz2
|
||||
cd fail2ban-1.0.1
|
||||
tar xvfj fail2ban-master.tar.bz2
|
||||
cd fail2ban-master
|
||||
sudo python setup.py install
|
||||
|
||||
Alternatively, you can clone the source from GitHub to a directory of Your choice, and do the install from there. Pick the correct branch, for example, master or 0.11
|
||||
Alternatively, you can clone the source from GitHub to a directory of your choice, and do the install from there. Pick the correct branch, for example, master or 0.11
|
||||
|
||||
git clone https://github.com/fail2ban/fail2ban.git
|
||||
cd fail2ban
|
||||
|
|
@ -90,11 +91,7 @@ fail2ban(1) and jail.conf(5) manpages for further references.
|
|||
Code status:
|
||||
------------
|
||||
|
||||
* travis-ci.org: [](https://travis-ci.org/fail2ban/fail2ban?branch=master) / [](https://travis-ci.org/fail2ban/fail2ban?branch=0.11) (0.11 branch) / [](https://travis-ci.org/fail2ban/fail2ban?branch=0.10) (0.10 branch)
|
||||
|
||||
* coveralls.io: [](https://coveralls.io/github/fail2ban/fail2ban?branch=master) / [](https://coveralls.io/github/fail2ban/fail2ban?branch=0.11) (0.11 branch) / [](https://coveralls.io/github/fail2ban/fail2ban?branch=0.10) / (0.10 branch)
|
||||
|
||||
* codecov.io: [](https://codecov.io/gh/fail2ban/fail2ban/branch/master) / [](https://codecov.io/gh/fail2ban/fail2ban/branch/0.11) (0.11 branch) / [](https://codecov.io/gh/fail2ban/fail2ban/branch/0.10) (0.10 branch)
|
||||
* [](https://github.com/fail2ban/fail2ban/actions/workflows/main.yml)
|
||||
|
||||
Contact:
|
||||
--------
|
||||
|
|
|
|||
8
RELEASE
8
RELEASE
|
|
@ -13,7 +13,7 @@ Preparation
|
|||
* Check distribution patches and see if they can be included
|
||||
|
||||
* https://apps.fedoraproject.org/packages/fail2ban/sources
|
||||
* http://sources.gentoo.org/cgi-bin/viewvc.cgi/gentoo-x86/net-analyzer/fail2ban/
|
||||
* https://gitweb.gentoo.org/repo/gentoo.git/tree/net-analyzer/fail2ban
|
||||
* http://svnweb.freebsd.org/ports/head/security/py-fail2ban/
|
||||
* https://build.opensuse.org/package/show?package=fail2ban&project=openSUSE%3AFactory
|
||||
* http://sophie.zarb.org/sources/fail2ban (Mageia)
|
||||
|
|
@ -49,7 +49,7 @@ Preparation
|
|||
|
||||
ad-hoc bash script to run in a clean clone:
|
||||
|
||||
find -type f | grep -v -e '\.git' -e '/doc/' -e '\.travis' -e MANIFEST | sed -e 's,^\./,,g' | while read f; do grep -ne "^$f\$" MANIFEST >/dev/null || echo "$f" ; done
|
||||
find -type f | grep -v -e '\.git' -e '/doc/' -e MANIFEST | sed -e 's,^\./,,g' | while read f; do grep -ne "^$f\$" MANIFEST >/dev/null || echo "$f" ; done
|
||||
|
||||
or an alternative for comparison with previous release
|
||||
|
||||
|
|
@ -115,7 +115,7 @@ Pre Release
|
|||
|
||||
* Arch Linux:
|
||||
|
||||
* https://www.archlinux.org/packages/community/any/fail2ban/
|
||||
* https://www.archlinux.org/packages/extra/any/fail2ban/
|
||||
|
||||
* Debian: Yaroslav Halchenko <debian@onerussian.com>
|
||||
|
||||
|
|
@ -134,7 +134,7 @@ Pre Release
|
|||
|
||||
* Gentoo: netmon@gentoo.org
|
||||
|
||||
* http://sources.gentoo.org/cgi-bin/viewvc.cgi/gentoo-x86/net-analyzer/fail2ban/metadata.xml?view=markup
|
||||
* https://gitweb.gentoo.org/repo/gentoo.git/tree/net-analyzer/fail2ban/metadata.xml
|
||||
* https://bugs.gentoo.org/buglist.cgi?quicksearch=fail2ban
|
||||
|
||||
* openSUSE: Stephan Kulow <coolo@suse.com>
|
||||
|
|
|
|||
1
THANKS
1
THANKS
|
|
@ -22,6 +22,7 @@ Andrey G. Grozin
|
|||
Andy Fragen
|
||||
Arturo 'Buanzo' Busleiman
|
||||
Axel Thimm
|
||||
Balazs Mateffy
|
||||
Bas van den Dikkenberg
|
||||
Beau Raines
|
||||
Bill Heaton
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: t -*-
|
||||
# vi: set ft=python sts=4 ts=4 sw=4 noet :
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: t -*-
|
||||
# vi: set ft=python sts=4 ts=4 sw=4 noet :
|
||||
#
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: t -*-
|
||||
# vi: set ft=python sts=4 ts=4 sw=4 noet :
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: t -*-
|
||||
# vi: set ft=python sts=4 ts=4 sw=4 noet :
|
||||
"""Script to run Fail2Ban tests battery
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ actioncheck =
|
|||
# use my (Shaun's) helper PHP script by commenting out the first #actionban
|
||||
# line below, uncommenting the second one, and pointing the URL at
|
||||
# wherever you install the helper script. For the PHP helper script, see
|
||||
# <https://wiki.shaunc.com/wikka.php?wakka=ReportingToAbuseIPDBWithFail2Ban>
|
||||
# <https://github.com/parseword/fail2ban-abuseipdb/>
|
||||
#
|
||||
# Tags: See jail.conf(5) man page
|
||||
# Values: CMD
|
||||
|
|
|
|||
|
|
@ -2,7 +2,61 @@
|
|||
#
|
||||
# Author: Chris Caron <lead2gold@gmail.com>
|
||||
#
|
||||
# ban & send a notification to one or more of the 120+ services supported by
|
||||
# Apprise.
|
||||
# - See https://appriseit.com/services/ for details on what is supported.
|
||||
# - See https://appriseit.com/getting-started/configuration/ for information
|
||||
# on how to prepare an Apprise configuration file.
|
||||
#
|
||||
# This plugin requires that Apprise is installed on your system:
|
||||
#
|
||||
# pip install apprise
|
||||
#
|
||||
# Breakdown:
|
||||
# config provide a path to an Apprise Config file
|
||||
# The default is /etc/fail2ban/apprise.conf if not provided.
|
||||
# Both YAML and TEXT formats are supported.
|
||||
# You can even point your configuration to an Apprise API
|
||||
# endpoint.
|
||||
#
|
||||
# args Provide additional arguments to support the Apprise CLI.
|
||||
# See https://appriseit.com/cli/usage/ for additional options.
|
||||
# the --tag (-g) is incredibly useful for integrating with
|
||||
# fail2ban as you can exclusively have it target specific
|
||||
# notifications this way.
|
||||
#
|
||||
# Config Example #1: Simple
|
||||
# 1. Create a /etc/fail2ban/apprise.conf
|
||||
# ```
|
||||
# # /etc/fail2ban/apprise.conf
|
||||
# fail2ban=mailto://user:pass@example.com
|
||||
# ```
|
||||
# 2 In jail:
|
||||
# ```
|
||||
# action = %(action_)s
|
||||
# apprise[args='--tag fail2ban']
|
||||
# ```
|
||||
#
|
||||
# Config Example #2: YAML an Custom path
|
||||
# 1. Create a /etc/fail2ban/apprise.conf
|
||||
# ```
|
||||
# # /etc/fail2ban/apprise.yaml
|
||||
# urls:
|
||||
# - mailto://user:pass@example.com:
|
||||
# tags: f2b
|
||||
# ```
|
||||
# 2. In jail:
|
||||
# ```
|
||||
# action = %(action_)s
|
||||
# apprise[config='/etc/fail2ban/apprise.yaml',args='--tag f2b']
|
||||
# ```
|
||||
#
|
||||
# Config Example #3: Apprise API
|
||||
# 1. In jail:
|
||||
# ```
|
||||
# action = %(action_)s
|
||||
# apprise[config='http://apprise.example.ca/get/mykey',args='-g f2b']
|
||||
# ```
|
||||
|
||||
[Definition]
|
||||
|
||||
|
|
@ -10,7 +64,7 @@
|
|||
# Notes.: command executed once at the start of Fail2Ban.
|
||||
# Values: CMD
|
||||
#
|
||||
actionstart = printf %%b "The jail <name> as been started successfully." | <apprise> -t "[Fail2Ban] <name>: started on `uname -n`"
|
||||
actionstart = printf %%b "The jail <name> has been started successfully." | <apprise> -t "[Fail2Ban] <name>: started on `uname -n`"
|
||||
|
||||
# Option: actionstop
|
||||
# Notes.: command executed once at the end of Fail2Ban
|
||||
|
|
@ -45,5 +99,9 @@ actionunban =
|
|||
# Define location of the default apprise configuration file to use
|
||||
#
|
||||
config = /etc/fail2ban/apprise.conf
|
||||
|
||||
# Support passing in arguments for example: "-g fail2ban"
|
||||
#
|
||||
apprise = apprise -c "<config>"
|
||||
args =
|
||||
#
|
||||
apprise = apprise -c "<config>" <args>
|
||||
|
|
|
|||
|
|
@ -30,6 +30,9 @@
|
|||
|
||||
[Definition]
|
||||
|
||||
# bypass reporting of restored (already reported) tickets:
|
||||
norestored = 1
|
||||
|
||||
# Option: actionstart
|
||||
# Notes.: command executed on demand at the first ban (or at the start of Fail2Ban if actionstart_on_demand is set to false).
|
||||
# Values: CMD
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ block = ip
|
|||
# Option: blocktype
|
||||
# Notes.: How to block the traffic. Use a action from man 5 ipfw
|
||||
# Common values: deny, unreach port, reset
|
||||
# ACTION defination at the top of man ipfw for allowed values.
|
||||
# ACTION definition at the top of man ipfw for allowed values.
|
||||
# Values: STRING
|
||||
#
|
||||
blocktype = unreach port
|
||||
|
|
|
|||
|
|
@ -50,11 +50,12 @@ actionban = curl -s -X POST "<_cf_api_url>" \
|
|||
# <time> unix timestamp of the ban time
|
||||
# Values: CMD
|
||||
#
|
||||
actionunban = id=$(curl -s -X GET "<_cf_api_url>?mode=<cfmode>¬es=<notes>&configuration.target=<cftarget>&configuration.value=<ip>" \
|
||||
<_cf_api_prms> \
|
||||
| awk -F"[,:}]" '{for(i=1;i<=NF;i++){if($i~/'id'\042/){print $(i+1)}}}' \
|
||||
| tr -d ' "' \
|
||||
| head -n 1)
|
||||
actionunban = id=$(curl -s -G -X GET "<_cf_api_url>" \
|
||||
--data-urlencode "mode=<cfmode>" --data-urlencode "notes=<notes>" --data-urlencode "configuration.target=<cftarget>" --data-urlencode "configuration.value=<ip>" \
|
||||
<_cf_api_prms> \
|
||||
| awk -F"[,:}]" '{for(i=1;i<=NF;i++){if($i~/'id'\042/){print $(i+1)}}}' \
|
||||
| tr -d ' "' \
|
||||
| head -n 1)
|
||||
if [ -z "$id" ]; then echo "<name>: id for <ip> cannot be found using target <cftarget>"; exit 0; fi; \
|
||||
curl -s -X DELETE "<_cf_api_url>/$id" \
|
||||
<_cf_api_prms> \
|
||||
|
|
@ -67,7 +68,7 @@ _cf_api_prms = -H "Authorization: Bearer <cftoken>" -H "Content-Type: applicatio
|
|||
|
||||
# Declare your Cloudflare Authorization Bearer Token in the [DEFAULT] section of your jail.local file.
|
||||
|
||||
# The Cloudflare <ZONE_ID> of hte domain you want to manage.
|
||||
# The Cloudflare <ZONE_ID> of the domain you want to manage.
|
||||
#
|
||||
# cfzone =
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
#
|
||||
# Please do not use this action unless you are certain that fail2ban
|
||||
# does not result in "false positives" for your deployment. False
|
||||
# positive reports could serve a mis-favor to the original cause by
|
||||
# positive reports could serve a misfavor to the original cause by
|
||||
# flooding corresponding contact addresses, and complicating the work
|
||||
# of administration personnel responsible for handling (verified) legit
|
||||
# complains.
|
||||
|
|
|
|||
26
config/action.d/csf.conf
Normal file
26
config/action.d/csf.conf
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# Fail2Ban configuration file
|
||||
# http://configserver.com/cp/csf.html
|
||||
#
|
||||
# Note: CSF doesn't play nicely with other actions. It has been observed to
|
||||
# remove bans created by other iptables based actions. If you are going to use
|
||||
# this action, use it for all of your jails.
|
||||
#
|
||||
# DON'T MIX CSF and other IPTABLES based actions
|
||||
|
||||
[Definition]
|
||||
|
||||
actionstart =
|
||||
actionstop =
|
||||
actioncheck =
|
||||
actionban = csf --deny <ip> "banned by Fail2Ban <name>"
|
||||
actionunban = csf --denyrm <ip>
|
||||
|
||||
[Init]
|
||||
|
||||
# Name used in CSF configuration
|
||||
#
|
||||
name = default
|
||||
|
||||
# DEV NOTES:
|
||||
#
|
||||
# based on apf.conf by Mark McKinstry
|
||||
|
|
@ -18,36 +18,36 @@ before = firewallcmd-common.conf
|
|||
|
||||
[Definition]
|
||||
|
||||
actionstart = <ipstype_<ipsettype>/actionstart>
|
||||
actionstart = <ipsbackend_<ipsetbackend>/actionstart>
|
||||
firewall-cmd --direct --add-rule <family> filter <chain> 0 <actiontype> -m set --match-set <ipmset> src -j <blocktype>
|
||||
|
||||
actionflush = <ipstype_<ipsettype>/actionflush>
|
||||
actionflush = <ipsbackend_<ipsetbackend>/actionflush>
|
||||
|
||||
actionstop = firewall-cmd --direct --remove-rule <family> filter <chain> 0 <actiontype> -m set --match-set <ipmset> src -j <blocktype>
|
||||
<actionflush>
|
||||
<ipstype_<ipsettype>/actionstop>
|
||||
<ipsbackend_<ipsetbackend>/actionstop>
|
||||
|
||||
actionban = <ipstype_<ipsettype>/actionban>
|
||||
actionban = <ipsbackend_<ipsetbackend>/actionban>
|
||||
|
||||
# actionprolong = %(actionban)s
|
||||
|
||||
actionunban = <ipstype_<ipsettype>/actionunban>
|
||||
actionunban = <ipsbackend_<ipsetbackend>/actionunban>
|
||||
|
||||
[ipstype_ipset]
|
||||
[ipsbackend_ipset]
|
||||
|
||||
actionstart = ipset -exist create <ipmset> hash:ip timeout <default-ipsettime> <familyopt>
|
||||
actionstart = ipset -exist create <ipmset> <ipsettype> timeout <default-ipsettime> maxelem <maxelem> <familyopt>
|
||||
|
||||
actionflush = ipset flush <ipmset>
|
||||
|
||||
actionstop = ipset destroy <ipmset>
|
||||
actionstop = ipset destroy <ipmset> 2>/dev/null || { sleep 1; ipset destroy <ipmset>; }
|
||||
|
||||
actionban = ipset -exist add <ipmset> <ip> timeout <ipsettime>
|
||||
|
||||
actionunban = ipset -exist del <ipmset> <ip>
|
||||
|
||||
[ipstype_firewalld]
|
||||
[ipsbackend_firewalld]
|
||||
|
||||
actionstart = firewall-cmd --direct --new-ipset=<ipmset> --type=hash:ip --option=timeout=<default-ipsettime> <firewalld_familyopt>
|
||||
actionstart = firewall-cmd --direct --new-ipset=<ipmset> --type=<ipsettype> --option=timeout=<default-ipsettime> --option=maxelem=<maxelem> <firewalld_familyopt>
|
||||
|
||||
# TODO: there doesn't seem to be an explicit way to invoke the ipset flush function using firewall-cmd
|
||||
actionflush =
|
||||
|
|
@ -60,6 +60,11 @@ actionunban = firewall-cmd --ipset=<ipmset> --remove-entry=<ip>
|
|||
|
||||
[Init]
|
||||
|
||||
# Option: ipsettype
|
||||
# Notes: specifies type of set, see `man --pager='less -p "^SET TYPES"' ipset` for details
|
||||
# Values: hash:ip, hash:net, etc... Default: hash:ip
|
||||
ipsettype = hash:ip
|
||||
|
||||
# Option: chain
|
||||
# Notes specifies the iptables chain to which the fail2ban rules should be
|
||||
# added
|
||||
|
|
@ -77,15 +82,21 @@ default-ipsettime = 0
|
|||
# Values: [ NUM ] Default: 0 (managed by fail2ban by unban)
|
||||
ipsettime = 0
|
||||
|
||||
# expresion to caclulate timeout from bantime, example:
|
||||
# Option: maxelem
|
||||
# Notes: maximal number of elements which can be stored in the ipset
|
||||
# You may want to increase this for long-duration/high-volume jails
|
||||
# Values: [ NUM ] Default: 65536
|
||||
maxelem = 65536
|
||||
|
||||
# expression to calculate timeout from bantime, example:
|
||||
# banaction = %(known/banaction)s[ipsettime='<timeout-bantime>']
|
||||
timeout-bantime = $([ "<bantime>" -le 2147483 ] && echo "<bantime>" || echo 0)
|
||||
|
||||
# Option: ipsettype
|
||||
# Notes.: defines type of ipset used for match-set (firewalld or ipset)
|
||||
# Option: ipsetbackend
|
||||
# Notes.: defines the backend of ipset used for match-set (firewalld or ipset)
|
||||
# Values: firewalld or ipset
|
||||
# Default: ipset
|
||||
ipsettype = ipset
|
||||
ipsetbackend = ipset
|
||||
|
||||
# Option: actiontype
|
||||
# Notes.: defines additions to the blocking rule
|
||||
|
|
@ -118,4 +129,4 @@ firewalld_familyopt = --option=family=inet6
|
|||
# DEV NOTES:
|
||||
#
|
||||
# Author: Edgar Hoch, Daniel Black, Sergey Brester and Mihail Politaev
|
||||
# firewallcmd-new / iptables-ipset-proto6 combined for maximium goodness
|
||||
# firewallcmd-new / iptables-ipset-proto6 combined for maximum goodness
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ actioncheck =
|
|||
#
|
||||
# Because rich rules can only handle single or a range of ports we must split ports and execute the command for each port. Ports can be single and ranges separated by a comma or space for an example: http, https, 22-60, 18 smtp
|
||||
|
||||
fwcmd_rich_rule = rule family='<family>' source address='<ip>' port port='$p' protocol='<protocol>' %(rich-suffix)s
|
||||
fwcmd_rich_rule = rule family=\"<family>\" source address=\"<ip>\" port port=\"$p\" protocol=\"<protocol>\" %(rich-suffix)s
|
||||
|
||||
actionban = ports="<port>"; for p in $(echo $ports | tr ", " " "); do firewall-cmd --add-rich-rule="%(fwcmd_rich_rule)s"; done
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ before = iptables.conf
|
|||
# Notes.: command executed on demand at the first ban (or at the start of Fail2Ban if actionstart_on_demand is set to false).
|
||||
# Values: CMD
|
||||
#
|
||||
actionstart = ipset --create f2b-<name> iphash
|
||||
actionstart = ipset --create f2b-<name> maxelem <maxelem> iphash
|
||||
<_ipt_add_rules>
|
||||
|
||||
|
||||
|
|
@ -61,6 +61,14 @@ actionban = ipset --test f2b-<name> <ip> || ipset --add f2b-<name> <ip>
|
|||
#
|
||||
actionunban = ipset --test f2b-<name> <ip> && ipset --del f2b-<name> <ip>
|
||||
|
||||
# Several capabilities used internaly:
|
||||
# Several capabilities used internally:
|
||||
|
||||
rule-jump = -m set --match-set f2b-<name> src -j <blocktype>
|
||||
|
||||
[Init]
|
||||
|
||||
# Option: maxelem
|
||||
# Notes: maximal number of elements which can be stored in the ipset
|
||||
# You may want to increase this for long-duration/high-volume jails
|
||||
# Values: [ NUM ] Default: 65536
|
||||
maxelem = 65536
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ before = iptables.conf
|
|||
# Notes.: command executed on demand at the first ban (or at the start of Fail2Ban if actionstart_on_demand is set to false).
|
||||
# Values: CMD
|
||||
#
|
||||
actionstart = ipset -exist create <ipmset> hash:ip timeout <default-ipsettime> <familyopt>
|
||||
actionstart = ipset -exist create <ipmset> <ipsettype> timeout <default-ipsettime> maxelem <maxelem> <familyopt>
|
||||
<_ipt_add_rules>
|
||||
|
||||
# Option: actionflush
|
||||
|
|
@ -39,7 +39,7 @@ actionflush = ipset flush <ipmset>
|
|||
#
|
||||
actionstop = <_ipt_del_rules>
|
||||
<actionflush>
|
||||
ipset destroy <ipmset>
|
||||
ipset destroy <ipmset> 2>/dev/null || { sleep 1; ipset destroy <ipmset>; }
|
||||
|
||||
# Option: actionban
|
||||
# Notes.: command executed when banning an IP. Take care that the
|
||||
|
|
@ -59,13 +59,18 @@ actionban = ipset -exist add <ipmset> <ip> timeout <ipsettime>
|
|||
#
|
||||
actionunban = ipset -exist del <ipmset> <ip>
|
||||
|
||||
# Several capabilities used internaly:
|
||||
# Several capabilities used internally:
|
||||
|
||||
rule-jump = -m set --match-set <ipmset> src -j <blocktype>
|
||||
|
||||
|
||||
[Init]
|
||||
|
||||
# Option: ipsettype
|
||||
# Notes: specifies type of set, see `man --pager='less -p "^SET TYPES"' ipset` for details
|
||||
# Values: hash:ip, hash:net, etc... Default: hash:ip
|
||||
ipsettype = hash:ip
|
||||
|
||||
# Option: default-ipsettime
|
||||
# Notes: specifies default timeout in seconds (handled default ipset timeout only)
|
||||
# Values: [ NUM ] Default: 0 (no timeout, managed by fail2ban by unban)
|
||||
|
|
@ -76,7 +81,13 @@ default-ipsettime = 0
|
|||
# Values: [ NUM ] Default: 0 (managed by fail2ban by unban)
|
||||
ipsettime = 0
|
||||
|
||||
# expresion to caclulate timeout from bantime, example:
|
||||
# Option: maxelem
|
||||
# Notes: maximal number of elements which can be stored in the ipset
|
||||
# You may want to increase this for long-duration/high-volume jails
|
||||
# Values: [ NUM ] Default: 65536
|
||||
maxelem = 65536
|
||||
|
||||
# expression to calculate timeout from bantime, example:
|
||||
# banaction = %(known/banaction)s[ipsettime='<timeout-bantime>']
|
||||
timeout-bantime = $([ "<bantime>" -le 2147483 ] && echo "<bantime>" || echo 0)
|
||||
|
||||
|
|
|
|||
|
|
@ -12,8 +12,9 @@ before = iptables.conf
|
|||
[Definition]
|
||||
|
||||
_ipt_chain_rule = -m recent --update --seconds 3600 --name <iptname> -j <blocktype>
|
||||
_ipt_for_proto-iter =
|
||||
_ipt_for_proto-done =
|
||||
_ipt_check_rule = <iptables> -C <chain> %(_ipt_chain_rule)s
|
||||
_ipt-iter =
|
||||
_ipt-done =
|
||||
|
||||
# Option: actionstart
|
||||
# Notes.: command executed on demand at the first ban (or at the start of Fail2Ban if actionstart_on_demand is set to false).
|
||||
|
|
@ -60,7 +61,7 @@ actionstop = echo / > /proc/net/xt_recent/<iptname>
|
|||
# Notes.: command executed as invariant check (error by ban)
|
||||
# Values: CMD
|
||||
#
|
||||
actioncheck = { <iptables> -C <chain> %(_ipt_chain_rule)s; } && test -e /proc/net/xt_recent/<iptname>
|
||||
actioncheck = { %(_ipt_check_rule)s >/dev/null 2>&1; } && test -e /proc/net/xt_recent/<iptname>
|
||||
|
||||
# Option: actionban
|
||||
# Notes.: command executed when banning an IP. Take care that the
|
||||
|
|
|
|||
|
|
@ -62,25 +62,25 @@ pre-rule =
|
|||
|
||||
rule-jump = -j <_ipt_rule_target>
|
||||
|
||||
# Several capabilities used internaly:
|
||||
# Several capabilities used internally:
|
||||
|
||||
_ipt_for_proto-iter = for proto in $(echo '<protocol>' | sed 's/,/ /g'); do
|
||||
_ipt_for_proto-done = done
|
||||
_ipt-iter = for chain in $(echo '<chain>' | sed 's/,/ /g'); do for proto in $(echo '<protocol>' | sed 's/,/ /g'); do
|
||||
_ipt-done = done; done
|
||||
|
||||
_ipt_add_rules = <_ipt_for_proto-iter>
|
||||
{ %(_ipt_check_rule)s >/dev/null 2>&1; } || { <iptables> -I <chain> %(_ipt_chain_rule)s; }
|
||||
<_ipt_for_proto-done>
|
||||
_ipt_add_rules = <_ipt-iter>
|
||||
{ %(_ipt_check_rule)s >/dev/null 2>&1; } || { <iptables> -I $chain %(_ipt_chain_rule)s; }
|
||||
<_ipt-done>
|
||||
|
||||
_ipt_del_rules = <_ipt_for_proto-iter>
|
||||
<iptables> -D <chain> %(_ipt_chain_rule)s
|
||||
<_ipt_for_proto-done>
|
||||
_ipt_del_rules = <_ipt-iter>
|
||||
<iptables> -D $chain %(_ipt_chain_rule)s
|
||||
<_ipt-done>
|
||||
|
||||
_ipt_check_rules = <_ipt_for_proto-iter>
|
||||
_ipt_check_rules = <_ipt-iter>
|
||||
%(_ipt_check_rule)s
|
||||
<_ipt_for_proto-done>
|
||||
<_ipt-done>
|
||||
|
||||
_ipt_chain_rule = <pre-rule><ipt_<type>/_chain_rule>
|
||||
_ipt_check_rule = <iptables> -C <chain> %(_ipt_chain_rule)s
|
||||
_ipt_check_rule = <iptables> -C $chain %(_ipt_chain_rule)s
|
||||
_ipt_rule_target = f2b-<name>
|
||||
|
||||
[ipt_oneport]
|
||||
|
|
@ -99,8 +99,9 @@ _chain_rule = -p $proto <rule-jump>
|
|||
[Init]
|
||||
|
||||
# Option: chain
|
||||
# Notes specifies the iptables chain to which the Fail2Ban rules should be
|
||||
# added
|
||||
# Notes specifies the iptables chains to which the Fail2Ban rules should be
|
||||
# added. May be a single chain (e.g. INPUT) or a comma separated list
|
||||
# (e.g. INPUT, FORWARD)
|
||||
# Values: STRING Default: INPUT
|
||||
chain = INPUT
|
||||
|
||||
|
|
@ -135,7 +136,7 @@ returntype = RETURN
|
|||
|
||||
# Option: lockingopt
|
||||
# Notes.: Option was introduced to iptables to prevent multiple instances from
|
||||
# running concurrently and causing irratic behavior. -w was introduced
|
||||
# running concurrently and causing erratic behavior. -w was introduced
|
||||
# in iptables 1.4.20, so might be absent on older systems
|
||||
# See https://github.com/fail2ban/fail2ban/issues/1122
|
||||
# Values: STRING
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
# Reporting an IP is a serious action. Make sure that it is legit.
|
||||
# Consider using this action only for:
|
||||
# * IP that has been banned more than once
|
||||
# * High max retry to avoid user mis-typing password
|
||||
# * High max retry to avoid user mistyping password
|
||||
# * Filters that are unlikely to be human error
|
||||
#
|
||||
# Example:
|
||||
|
|
@ -47,7 +47,7 @@
|
|||
# BadBot 256 Bad bot that is not honoring robots.txt or just flooding with too many requests, etc
|
||||
# Compromised 512 The ip has been taken over by malware or botnet
|
||||
# Phishing 1024 The ip is involved in phishing or spoofing
|
||||
# Iot 2048 The ip has targetted an iot (Internet of Things) device
|
||||
# Iot 2048 The ip has targeted an iot (Internet of Things) device
|
||||
# PortScan 4096 Port scan
|
||||
# See https://ipthreat.net/bulkreportformat for more information
|
||||
# ```
|
||||
|
|
|
|||
84
config/action.d/mikrotik.conf
Normal file
84
config/action.d/mikrotik.conf
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
# Fail2Ban configuration file
|
||||
#
|
||||
# Mikrotik routerOS action to add/remove address-list entries
|
||||
#
|
||||
# Author: Duncan Bellamy <dunk@denkimushi.com>
|
||||
# based on forum.mikrotik.com post by pakjebakmeel
|
||||
#
|
||||
# in the instructions:
|
||||
# (10.0.0.1 is ip of mikrotik router)
|
||||
# (10.0.0.2 is ip of fail2ban machine)
|
||||
#
|
||||
# on fail2ban machine:
|
||||
# sudo mkdir /var/lib/fail2ban/ssh
|
||||
# sudo chmod 700 /var/lib/fail2ban/ssh
|
||||
# sudo ssh-keygen -N "" -f /var/lib/fail2ban/ssh/fail2ban_id_rsa
|
||||
# sudo scp /var/lib/fail2ban/ssh/fail2ban_id_rsa.pub admin@10.0.0.1:/
|
||||
# ssh admin@10.0.0.1
|
||||
#
|
||||
# on mikrotik router:
|
||||
# /user add name=miki-f2b group=write address=10.0.0.2 password=""
|
||||
# /user ssh-keys import public-key-file=fail2ban_id_rsa.pub user=miki-f2b
|
||||
# /quit
|
||||
#
|
||||
# on fail2ban machine:
|
||||
# (check password login fails)
|
||||
# ssh miki-f2b@10.0.0.1
|
||||
# (check private key works)
|
||||
# sudo ssh -i /var/lib/fail2ban/ssh/fail2ban_id_rsa miki-f2b@10.0.0.1
|
||||
#
|
||||
# Then create rules on mikrorik router that use address
|
||||
# list(s) maintained by fail2ban eg in the forward chain
|
||||
# drop from address list, or in the forward chain drop
|
||||
# from address list to server
|
||||
#
|
||||
# example extract from jail.local overriding some defaults
|
||||
# action = mikrotik[keyfile="%(mkeyfile)s", user="%(muser)s", host="%(mhost)s", list="%(mlist)s"]
|
||||
#
|
||||
# ignoreip = 127.0.0.1/8 192.168.0.0/24
|
||||
|
||||
# mkeyfile = /etc/fail2ban/ssh/mykey_id_rsa
|
||||
# muser = myuser
|
||||
# mhost = 192.168.0.1
|
||||
# mlist = BAD LIST
|
||||
|
||||
[Definition]
|
||||
|
||||
actionstart =
|
||||
|
||||
actionstop = %(actionflush)s
|
||||
|
||||
actionflush = %(command)s "/ip firewall address-list remove [find list=\"%(list)s\" comment~\"%(startcomment)s-*\"]"
|
||||
|
||||
actioncheck =
|
||||
|
||||
actionban = %(command)s "/ip firewall address-list add list=\"%(list)s\" address=<ip> comment=%(comment)s"
|
||||
|
||||
actionunban = %(command)s "/ip firewall address-list remove [find list=\"%(list)s\" comment=%(comment)s]"
|
||||
|
||||
command = ssh -l %(user)s -p%(port)s -i %(keyfile)s %(host)s
|
||||
|
||||
# Option: user
|
||||
# Notes.: username to use when connecting to routerOS
|
||||
user =
|
||||
# Option: port
|
||||
# Notes.: port to use when connecting to routerOS
|
||||
port = 22
|
||||
# Option: keyfile
|
||||
# Notes.: ssh private key to use for connecting to routerOS
|
||||
keyfile =
|
||||
# Option: host
|
||||
# Notes.: hostname or ip of router
|
||||
host =
|
||||
# Option: list
|
||||
# Notes.: name of "address-list" to use on router
|
||||
list = Fail2Ban
|
||||
# Option: startcomment
|
||||
# Notes.: used as a prefix to all comments, and used to match for flushing rules
|
||||
startcomment = f2b-<name>
|
||||
# Option: comment
|
||||
# Notes.: comment to use on routerOS (must be unique as used for ip address removal)
|
||||
comment = %(startcomment)s-<ip>
|
||||
|
||||
[Init]
|
||||
name="%(__name__)s"
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
# The script will add offender IPs to a dataset on netscaler, the dataset can then be used to block the IPs at a cs/vserver or global level
|
||||
# This dataset is then used to block IPs using responder policies on the netscaler.
|
||||
#
|
||||
# The script assumes using HTTPS with unsecure certificate to access the netscaler,
|
||||
# The script assumes using HTTPS with insecure certificate to access the netscaler,
|
||||
# if you have a valid certificate installed remove the -k from the curl lines, or if you want http change it accordingly (and remove the -k)
|
||||
#
|
||||
# This action depends on curl
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ match = <rule_match-<type>>
|
|||
#
|
||||
rule_stat = %(match)s <addr_family> saddr @<addr_set> <blocktype>
|
||||
|
||||
# optional interator over protocol's:
|
||||
# optional iterator over protocol's:
|
||||
_nft_for_proto-custom-iter =
|
||||
_nft_for_proto-custom-done =
|
||||
_nft_for_proto-allports-iter =
|
||||
|
|
@ -53,9 +53,9 @@ _nft_for_proto-multiport-iter = for proto in $(echo '<protocol>' | sed 's/,/ /g'
|
|||
_nft_for_proto-multiport-done = done
|
||||
|
||||
_nft_list = <nftables> -a list chain <table_family> <table> <chain>
|
||||
_nft_get_handle_id = grep -oP '@<addr_set>\s+.*\s+\Khandle\s+(\d+)$'
|
||||
_nft_get_handle_id = sed -nE 's/.*@<addr_set>\s+.*\s+\#\s*(handle\s+[0-9]+)$/\1/p'
|
||||
|
||||
_nft_add_set = <nftables> add set <table_family> <table> <addr_set> \{ type <addr_type>\; \}
|
||||
_nft_add_set = <nftables> add set <table_family> <table> <addr_set> \{ type <addr_type>\;<addr_options> \}
|
||||
<_nft_for_proto-<type>-iter>
|
||||
<nftables> add rule <table_family> <table> <chain> %(rule_stat)s
|
||||
<_nft_for_proto-<type>-done>
|
||||
|
|
@ -67,7 +67,7 @@ _nft_del_set = { %(_nft_list)s | %(_nft_get_handle_id)s; } | while read -r hdl;
|
|||
# Notes.: command executed after the stop in order to delete table (it checks that no sets are available):
|
||||
# Values: CMD
|
||||
#
|
||||
_nft_shutdown_table = { <nftables> list table <table_family> <table> | grep -qP '^\s+set\s+'; } || {
|
||||
_nft_shutdown_table = { <nftables> list table <table_family> <table> | grep -qE '^\s+set\s+'; } || {
|
||||
<nftables> delete table <table_family> <table>
|
||||
}
|
||||
|
||||
|
|
@ -97,7 +97,7 @@ actionstop = %(_nft_del_set)s
|
|||
<_nft_shutdown_table>
|
||||
|
||||
# Option: actioncheck
|
||||
# Notes.: command executed once before each actionban command
|
||||
# Notes.: command executed once in error case by other command (during the check/restore sane environment process)
|
||||
# Values: CMD
|
||||
#
|
||||
actioncheck = <nftables> list chain <table_family> <table> <chain> | grep -q '@<addr_set>[ \t]'
|
||||
|
|
@ -197,6 +197,11 @@ addr_set = addr-set-<name>
|
|||
# Values: [ ip | ip6 ]
|
||||
addr_family = ip
|
||||
|
||||
# Option: addr_options
|
||||
# Notes: Additional options for the addr-set, by default allows to store CIDR or address ranges.
|
||||
# Can be set to empty value to create simple addresses set.
|
||||
addr_options = <sp>flags interval\;
|
||||
|
||||
[Init?family=inet6]
|
||||
addr_family = ip6
|
||||
addr_type = ipv6_addr
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#
|
||||
# Author: Nick Hilliard <nick@foobar.org>
|
||||
# Modified by: Alexander Koeppe making PF work seamless and with IPv4 and IPv6
|
||||
# Modified by: Balazs Mateffy adding allproto option so all traffic gets blocked from the malicious source
|
||||
#
|
||||
#
|
||||
|
||||
|
|
@ -26,9 +27,11 @@
|
|||
# }
|
||||
# to your main pf ruleset, where "namei" are the names of the jails
|
||||
# which invoke this action
|
||||
# to block all protocols use the pf[protocol=all] option
|
||||
actionstart = echo "table <<tablename>-<name>> persist counters" | <pfctl> -f-
|
||||
port="<port>"; if [ "$port" != "" ] && case "$port" in \{*) false;; esac; then port="{$port}"; fi
|
||||
echo "<block> proto <protocol> from <<tablename>-<name>> to <actiontype>" | <pfctl> -f-
|
||||
protocol="<protocol>"; if [ "$protocol" != "all" ]; then protocol="proto $protocol"; else protocol=all; fi
|
||||
echo "<block> $protocol from <<tablename>-<name>> to <actiontype>" | <pfctl> -f-
|
||||
|
||||
# Option: start_on_demand - to start action on demand
|
||||
# Example: `action=pf[actionstart_on_demand=true]`
|
||||
|
|
@ -98,6 +101,7 @@ tablename = f2b
|
|||
#
|
||||
# The action you want pf to take.
|
||||
# Probably, you want "block quick", but adjust as needed.
|
||||
# If you want to log all blocked use "blog log quick"
|
||||
block = block quick
|
||||
|
||||
# Option: protocol
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@
|
|||
# Values: CMD
|
||||
#
|
||||
actionstart = if ! ipset -quiet -name list f2b-<name> >/dev/null;
|
||||
then ipset -quiet -exist create f2b-<name> hash:ip timeout <default-ipsettime>;
|
||||
then ipset -quiet -exist create f2b-<name> <ipsettype> timeout <default-ipsettime> maxelem <maxelem>;
|
||||
fi
|
||||
|
||||
# Option: actionstop
|
||||
|
|
@ -88,6 +88,19 @@ default-ipsettime = 0
|
|||
# Values: [ NUM ] Default: 0 (managed by fail2ban by unban)
|
||||
ipsettime = 0
|
||||
|
||||
# expresion to caclulate timeout from bantime, example:
|
||||
# expression to calculate timeout from bantime, example:
|
||||
# banaction = %(known/banaction)s[ipsettime='<timeout-bantime>']
|
||||
timeout-bantime = $([ "<bantime>" -le 2147483 ] && echo "<bantime>" || echo 0)
|
||||
|
||||
[Init]
|
||||
|
||||
# Option: ipsettype
|
||||
# Notes: specifies type of set, see `man --pager='less -p "^SET TYPES"' ipset` for details
|
||||
# Values: hash:ip, hash:net, etc... Default: hash:ip
|
||||
ipsettype = hash:ip
|
||||
|
||||
# Option: maxelem
|
||||
# Notes: maximal number of elements which can be stored in the ipset
|
||||
# You may want to increase this for long-duration/high-volume jails
|
||||
# Values: [ NUM ] Default: 65536
|
||||
maxelem = 65536
|
||||
|
|
|
|||
|
|
@ -19,7 +19,8 @@
|
|||
|
||||
import socket
|
||||
import smtplib
|
||||
from email.mime.text import MIMEText
|
||||
import email.policy
|
||||
from email.message import EmailMessage
|
||||
from email.utils import formatdate, formataddr
|
||||
|
||||
from fail2ban.server.actions import ActionBase, CallingMap
|
||||
|
|
@ -75,7 +76,7 @@ class SMTPAction(ActionBase):
|
|||
"""
|
||||
|
||||
def __init__(
|
||||
self, jail, name, host="localhost", user=None, password=None,
|
||||
self, jail, name, host="localhost", ssl=False, user=None, password=None,
|
||||
sendername="Fail2Ban", sender="fail2ban", dest="root", matches=None):
|
||||
"""Initialise action.
|
||||
|
||||
|
|
@ -88,6 +89,8 @@ class SMTPAction(ActionBase):
|
|||
host : str, optional
|
||||
SMTP host, of host:port format. Default host "localhost" and
|
||||
port "25"
|
||||
ssl : bool, optional
|
||||
Whether to use TLS for the SMTP connection or not. Default False.
|
||||
user : str, optional
|
||||
Username used for authentication with SMTP server.
|
||||
password : str, optional
|
||||
|
|
@ -109,7 +112,7 @@ class SMTPAction(ActionBase):
|
|||
super(SMTPAction, self).__init__(jail, name)
|
||||
|
||||
self.host = host
|
||||
#TODO: self.ssl = ssl
|
||||
self.ssl = ssl
|
||||
|
||||
self.user = user
|
||||
self.password =password
|
||||
|
|
@ -149,16 +152,25 @@ class SMTPAction(ActionBase):
|
|||
See Python `smtplib` for full list of other possible
|
||||
exceptions.
|
||||
"""
|
||||
msg = MIMEText(text)
|
||||
msg = EmailMessage(policy=email.policy.SMTP)
|
||||
msg.set_content(text)
|
||||
msg['Subject'] = subject
|
||||
msg['From'] = formataddr((self.fromname, self.fromaddr))
|
||||
msg['To'] = self.toaddr
|
||||
msg['Date'] = formatdate()
|
||||
|
||||
smtp = smtplib.SMTP()
|
||||
smtp_host, smtp_port = self.host.split(':')
|
||||
smtp = smtplib.SMTP(host=smtp_host, port=smtp_port)
|
||||
try:
|
||||
r = smtp.connect(host=smtp_host, port=smtp_port)
|
||||
self._logSys.debug("Connected to SMTP '%s', response: %i: %s",
|
||||
self.host, *smtp.connect(self.host))
|
||||
self.host, *r)
|
||||
|
||||
if self.ssl: # pragma: no cover
|
||||
r = smtp.starttls()[0];
|
||||
if r != 220: # pragma: no cover
|
||||
raise Exception("Failed to starttls() on '%s': %s" % (self.host, r))
|
||||
|
||||
if self.user and self.password: # pragma: no cover (ATM no tests covering that)
|
||||
smtp.login(self.user, self.password)
|
||||
failed_recipients = smtp.sendmail(
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ _kill_conntrack = conntrack -D -s "<ip>"
|
|||
|
||||
# Option: kill
|
||||
# Notes.: can be used to specify custom killing feature, by default depending on option kill-mode
|
||||
# Examples: banaction = ufw[kill='ss -K "( sport = :http || sport = :https )" dst "[<ip>]"']
|
||||
# Examples: banaction = ufw[kill='ss -K "dst = [<ip>] && ( sport = :http || sport = :https )"']
|
||||
# banaction = ufw[kill='cutter "<ip>"']
|
||||
kill = <_kill_<kill-mode>>
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,13 @@ actioncheck =
|
|||
actionban = oifs=${IFS};
|
||||
RESOLVER_ADDR="%(addr_resolver)s"
|
||||
if [ "<debug>" -gt 0 ]; then echo "try to resolve $RESOLVER_ADDR"; fi
|
||||
ADDRESSES=$(dig +short -t txt -q $RESOLVER_ADDR | tr -d '"')
|
||||
ADDRESSES=$(dig +short -t txt -q $RESOLVER_ADDR | grep -v ';;' | tr -d '"')
|
||||
if [ "<debug>" -gt 0 ]; then echo "returned address $ADDRESSES"; fi
|
||||
if [ -z "$ADDRESSES" ]; then
|
||||
echo "address for $RESOLVER_ADDR cannot be found or timeout from dig";
|
||||
if [ "<debug>" -gt 0 ]; then exit 1; fi
|
||||
exit 0
|
||||
fi
|
||||
IFS=,; ADDRESSES=$(echo $ADDRESSES)
|
||||
IFS=${oifs}
|
||||
IP=<ip>
|
||||
|
|
@ -55,13 +61,11 @@ actionban = oifs=${IFS};
|
|||
TLP=<tlp>
|
||||
PORT=<port>
|
||||
DATE=`LC_ALL=C date --date=@<time> +"%%a, %%d %%h %%Y %%T %%z"`
|
||||
if [ ! -z "$ADDRESSES" ]; then
|
||||
oifs=${IFS}; IFS=,; ADDRESSES=$(echo $ADDRESSES)
|
||||
IFS=${oifs}
|
||||
(printf -- %%b "<header>\n<message>\n<report>\n\n";
|
||||
date '+Note: Local timezone is %%z (%%Z)';
|
||||
printf -- %%b "\n<ipmatches>\n\n<footer>") | <mailcmd> <mailargs> $ADDRESSES
|
||||
fi
|
||||
oifs=${IFS}; IFS=,; ADDRESSES=$(echo $ADDRESSES)
|
||||
IFS=${oifs}
|
||||
(printf -- %%b "<header>\n<message>\n<report>\n\n";
|
||||
date '+Note: Local timezone is %%z (%%Z)';
|
||||
printf -- %%b "\n<ipmatches>\n\n<footer>") | <mailcmd> <mailargs> $ADDRESSES
|
||||
|
||||
actionunban =
|
||||
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ ignoreregex =
|
|||
# ^user .*: one-time-nonce mismatch - sending new nonce\s*$
|
||||
# ^realm mismatch - got `(?:[^']*|.*?)' but no realm specified\s*$
|
||||
#
|
||||
# Because url/referer are foreign input, short form of regex used if long enough to idetify failure.
|
||||
# Because url/referer are foreign input, short form of regex used if long enough to identify failure.
|
||||
#
|
||||
# Author: Cyril Jaquier
|
||||
# Major edits by Daniel Black and Ben Rubson.
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@
|
|||
badbotscustom = EmailCollector|WebEMailExtrac|TrackBack/1\.02|sogou music spider|(?:Mozilla/\d+\.\d+ )?Jorgee
|
||||
badbots = Atomic_Email_Hunter/4\.0|atSpider/1\.0|autoemailspider|bwh3_user_agent|China Local Browse 2\.6|ContactBot/0\.2|ContentSmartz|DataCha0s/2\.0|DBrowse 1\.4b|DBrowse 1\.4d|Demo Bot DOT 16b|Demo Bot Z 16b|DSurf15a 01|DSurf15a 71|DSurf15a 81|DSurf15a VA|EBrowse 1\.4b|Educate Search VxB|EmailSiphon|EmailSpider|EmailWolf 1\.00|ESurf15a 15|ExtractorPro|Franklin Locator 1\.8|FSurf15a 01|Full Web Bot 0416B|Full Web Bot 0516B|Full Web Bot 2816B|Guestbook Auto Submitter|Industry Program 1\.0\.x|ISC Systems iRc Search 2\.1|IUPUI Research Bot v 1\.9a|LARBIN-EXPERIMENTAL \(efp@gmx\.net\)|LetsCrawl\.com/1\.0 \+http\://letscrawl\.com/|Lincoln State Web Browser|LMQueueBot/0\.2|LWP\:\:Simple/5\.803|Mac Finder 1\.0\.xx|MFC Foundation Class Library 4\.0|Microsoft URL Control - 6\.00\.8xxx|Missauga Locate 1\.0\.0|Missigua Locator 1\.9|Missouri College Browse|Mizzu Labs 2\.2|Mo College 1\.9|MVAClient|Mozilla/2\.0 \(compatible; NEWT ActiveX; Win32\)|Mozilla/3\.0 \(compatible; Indy Library\)|Mozilla/3\.0 \(compatible; scan4mail \(advanced version\) http\://www\.peterspages\.net/?scan4mail\)|Mozilla/4\.0 \(compatible; Advanced Email Extractor v2\.xx\)|Mozilla/4\.0 \(compatible; Iplexx Spider/1\.0 http\://www\.iplexx\.at\)|Mozilla/4\.0 \(compatible; MSIE 5\.0; Windows NT; DigExt; DTS Agent|Mozilla/4\.0 efp@gmx\.net|Mozilla/5\.0 \(Version\: xxxx Type\:xx\)|NameOfAgent \(CMS Spider\)|NASA Search 1\.0|Nsauditor/1\.x|PBrowse 1\.4b|PEval 1\.4b|Poirot|Port Huron Labs|Production Bot 0116B|Production Bot 2016B|Production Bot DOT 3016B|Program Shareware 1\.0\.2|PSurf15a 11|PSurf15a 51|PSurf15a VA|psycheclone|RSurf15a 41|RSurf15a 51|RSurf15a 81|searchbot admin@google\.com|ShablastBot 1\.0|snap\.com beta crawler v0|Snapbot/1\.0|Snapbot/1\.0 \(Snap Shots, \+http\://www\.snap\.com\)|sogou develop spider|Sogou Orion spider/3\.0\(\+http\://www\.sogou\.com/docs/help/webmasters\.htm#07\)|sogou spider|Sogou web spider/3\.0\(\+http\://www\.sogou\.com/docs/help/webmasters\.htm#07\)|sohu agent|SSurf15a 11 |TSurf15a 11|Under the Rainbow 2\.2|User-Agent\: Mozilla/4\.0 \(compatible; MSIE 6\.0; Windows NT 5\.1\)|VadixBot|WebVulnCrawl\.unknown/1\.0 libwww-perl/5\.803|Wells Search II|WEP Search 00
|
||||
|
||||
failregex = ^<HOST> -.*"(GET|POST|HEAD).*HTTP.*"(?:%(badbots)s|%(badbotscustom)s)"$
|
||||
vhostpref = (?:[\w]+[\w\-\.]*\s+)?
|
||||
failregex = ^\s*%(vhostpref)s<ADDR> [^"]*"[A-Z]{3,10} [^"]+" \d+ \d+ "[^"]+" "[^"]*(?:%(badbots)s|%(badbotscustom)s)"$
|
||||
|
||||
ignoreregex =
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ apache-prefix = <apache-prefix-<logging>>
|
|||
|
||||
apache-pref-ignore =
|
||||
|
||||
_apache_error_client = <apache-prefix>\[(:?error|<apache-pref-ignore>\S+:\S+)\]( \[pid \d+(:\S+ \d+)?\])? \[client <HOST>(:\d{1,5})?\]
|
||||
_apache_error_client = <apache-prefix>\[(:?error|<apache-pref-ignore>\S+:\S+)\]( \[pid \d+(:\S+ \d+)?\])? \[(?:client|remote) <HOST>(:\d{1,5})?\]
|
||||
|
||||
datepattern = {^LN-BEG}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
[Definition]
|
||||
|
||||
failregex = ^\s*<HOST> \S+ \S+(?: \S+)?\s+\S+ "[A-Z]+ /\S* [^"]*" \d+ \d+ \"[^"]*\" "[^"]*\bGooglebot/[^"]*"
|
||||
vhostpref = (?:[\w]+[\w\-\.]*\s+)?
|
||||
failregex = ^\s*%(vhostpref)s<ADDR> [^"]*"[A-Z]{3,10} /\S* [^"]*" \d+ \d+ "[^"]*" "[^"]*\bGooglebot/[^"]*"
|
||||
|
||||
ignoreregex =
|
||||
|
||||
|
|
|
|||
|
|
@ -19,11 +19,10 @@ before = apache-common.conf
|
|||
|
||||
script = /\S*(?:php(?:[45]|[.-]cgi)?|\.asp|\.exe|\.pl|\bcgi-bin/)
|
||||
|
||||
prefregex = ^%(_apache_error_client)s (?:AH0(?:01(?:28|30)|1(?:264|071)|2811): )?(?:(?:[Ff]ile|script|[Gg]ot) )<F-CONTENT>.+</F-CONTENT>$
|
||||
prefregex = ^%(_apache_error_client)s (?:AH0(?:01(?:28|30)|1(?:264|071)|2811): )?(?=(?:[Ff]ile|[Ss]cript|[Gg]ot error|stderr from) )<F-CONTENT>.+</F-CONTENT>$
|
||||
|
||||
failregex = ^(?:does not exist|not found or unable to stat): <script>\b
|
||||
^'<script>\S*' not found or unable to stat
|
||||
^error '[Pp]rimary script unknown(?:\\n)?'
|
||||
failregex = ^(?:(?:[Ff]ile does not exist|[Ss]cript not found or unable to stat): <script>\b|[Gg]ot error '[Pp]rimary script unknown\b)
|
||||
^(?:stderr from |script (?P<_q>'))<script>\S*(?(_q)'|) (?:script )?(?:does not exist|not found or unable to stat)
|
||||
|
||||
ignoreregex =
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ before = apache-common.conf
|
|||
|
||||
[Definition]
|
||||
|
||||
failregex = ^%(_apache_error_client)s (?:(?:AH001[23][456]: )?Invalid (method|URI) in request\b|(?:AH00565: )?request failed: URI too long \(longer than \d+\)|request failed: erroneous characters after protocol string:|(?:AH00566: )?request failed: invalid characters in URI\b)
|
||||
failregex = ^%(_apache_error_client)s (?:(?:AH(?:001[23][456]|10244): )?[Ii]nvalid (method|URI)\b|(?:AH00565: )?request failed: URI too long \(longer than \d+\)|request failed: erroneous characters after protocol string:|(?:AH00566: )?request failed: invalid characters in URI\b)
|
||||
|
||||
ignoreregex =
|
||||
|
||||
|
|
|
|||
|
|
@ -21,13 +21,13 @@ log_prefix= (?:NOTICE|SECURITY|WARNING)%(__pid_re)s:?(?:\[C-[\da-f]*\])?:? [^:]+
|
|||
prefregex = ^%(__prefix_line)s%(log_prefix)s <F-CONTENT>.+</F-CONTENT>$
|
||||
|
||||
failregex = ^Registration from '[^']*' failed for '<HOST>(:\d+)?' - (?:Wrong password|Username/auth name mismatch|No matching peer found|Not a local domain|Device does not match ACL|Peer is not supposed to register|ACL error \(permit/deny\)|Not a local domain)$
|
||||
^Call from '[^']*' \((?:(?:TCP|UDP):)?<HOST>:\d+\) to extension '[^']*' rejected because extension not found in context
|
||||
^Call (?:from '[^']*' )?\((?:(?:TCP|UDP):)?<HOST>:\d+\) to extension '[^']*' rejected because extension not found in context
|
||||
^(?:Host )?<HOST> (?:failed (?:to authenticate\b|MD5 authentication\b)|tried to authenticate with nonexistent user\b)
|
||||
^No registration for peer '[^']*' \(from <HOST>\)$
|
||||
^hacking attempt detected '<HOST>'$
|
||||
^SecurityEvent="(?:FailedACL|InvalidAccountID|ChallengeResponseFailed|InvalidPassword)"(?:(?:,(?!RemoteAddress=)\w+="[^"]*")*|.*?),RemoteAddress="IPV[46]/[^/"]+/<HOST>/\d+"(?:,(?!RemoteAddress=)\w+="[^"]*")*$
|
||||
^"Rejecting unknown SIP connection from <HOST>(?::\d+)?"$
|
||||
^Request (?:'[^']*' )?from '(?:[^']*|.*?)' failed for '<HOST>(?::\d+)?'\s\(callid: [^\)]*\) - (?:No matching endpoint found|Not match Endpoint(?: Contact)? ACL|(?:Failed|Error) to authenticate)\s*$
|
||||
^Request (?:'[^']*' )?from '(?:[^']*|.*?)' failed for '<HOST>(?::\d+)?'\s\(callid: [^\)]*\) - (?:No matching endpoint found|Not match Endpoint(?: Contact)? ACL|(?:Failed|Error) to authenticate)\b[^']*$
|
||||
|
||||
# FreePBX (todo: make optional in v.0.10):
|
||||
# ^(%(__prefix_line)s|\[\]\s*WARNING%(__pid_re)s:?(?:\[C-[\da-f]*\])? )[^:]+: Friendly Scanner from <HOST>$
|
||||
|
|
|
|||
16
config/filter.d/dante.conf
Normal file
16
config/filter.d/dante.conf
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
# Fail2Ban filter for dante
|
||||
#
|
||||
# Make sure you have "log: error" set in your "client pass" directive
|
||||
#
|
||||
|
||||
[INCLUDES]
|
||||
before = common.conf
|
||||
|
||||
[Definition]
|
||||
_daemon = danted
|
||||
|
||||
failregex = ^%(__prefix_line)sinfo: block\(\d\): tcp/accept \]: <ADDR>\.\d+ \S+: error after reading \d+ bytes? in \d+ seconds?: (?:could not access|system password authentication failed for|pam_authenticate\(\) for) user "<F-USER>[^"]+</F-USER>"
|
||||
|
||||
[Init]
|
||||
journalmatch = _SYSTEMD_UNIT=danted.service
|
||||
|
||||
|
|
@ -7,19 +7,21 @@ before = common.conf
|
|||
|
||||
[Definition]
|
||||
|
||||
_daemon = (?:dovecot(?:-auth)?|auth)
|
||||
|
||||
_auth_worker = (?:dovecot: )?auth(?:-worker)?
|
||||
_auth_worker_info = (?:conn \w+:auth(?:-worker)? \([^\)]+\): auth(?:-worker)?<\d+>: )?
|
||||
_daemon = (?:dovecot(?:-auth)?|auth)
|
||||
_bypass_reject_reason = (?:: (?:\w+\([^\):]*\) \w+|[^\(]+))*
|
||||
|
||||
prefregex = ^%(__prefix_line)s(?:%(_auth_worker)s(?:\([^\)]+\))?: )?(?:%(__pam_auth)s(?:\(dovecot:auth\))?: |(?:pop3|imap|managesieve|submission)-login: )?(?:Info: )?%(_auth_worker_info)s<F-CONTENT>.+</F-CONTENT>$
|
||||
|
||||
failregex = ^authentication failure; logname=<F-ALT_USER1>\S*</F-ALT_USER1> uid=\S* euid=\S* tty=dovecot ruser=<F-USER>\S*</F-USER> rhost=<HOST>(?:\s+user=<F-ALT_USER>\S*</F-ALT_USER>)?\s*$
|
||||
^(?:Aborted login|Disconnected|Remote closed connection|Client has quit the connection)(?:: (?:[^\(]+|\w+\([^\)]*\))+)? \((?:auth failed, \d+ attempts(?: in \d+ secs)?|tried to use (?:disabled|disallowed) \S+ auth|proxy dest auth failed)\):(?: user=<<F-USER>[^>]*</F-USER>>,)?(?: method=\S+,)? rip=<HOST>(?:[^>]*(?:, session=<\S+>)?)\s*$
|
||||
^(?:Login aborted|Aborted login|Disconnected|Remote closed connection|Client has quit the connection)%(_bypass_reject_reason)s \((?:auth failed, \d+ attempts(?: in \d+ secs)?|tried to use (?:disabled|disallowed) \S+ auth|proxy dest auth failed)\)[^:]*:(?: user=<<F-USER>[^>]*</F-USER>>,)?(?: method=\S+,)? rip=<HOST>(?:[^>]*(?:, session=<\S+>)?)\s*$
|
||||
^pam\(\S+,<HOST>(?:,\S*)?\): pam_authenticate\(\) failed: (?:User not known to the underlying authentication module: \d+ Time\(s\)|Authentication failure \([Pp]assword mismatch\?\)|Permission denied)\s*$
|
||||
^[a-z\-]{3,15}\(\S*,<HOST>(?:,\S*)?\): (?:[Uu]nknown user|[Ii]nvalid credentials|[Pp]assword mismatch)
|
||||
<mdre-<mode>>
|
||||
|
||||
mdre-aggressive = ^(?:Aborted login|Disconnected|Remote closed connection|Client has quit the connection)(?::(?: [^ \(]+)+)? \((?:no auth attempts|disconnected before auth was ready,|client didn't finish \S+ auth,)(?: (?:in|waited) \d+ secs)?\):(?: user=<[^>]*>,)?(?: method=\S+,)? rip=<HOST>(?:[^>]*(?:, session=<\S+>)?)\s*$
|
||||
mdre-aggressive = ^(?:Login aborted|Aborted login|Disconnected|Remote closed connection|Client has quit the connection)%(_bypass_reject_reason)s \((?:no auth attempts|disconnected before auth was ready,|client didn't finish \S+ auth,|disconnected during TLS handshake)(?: (?:in|waited) \d+ secs)?\)[^:]*:(?: user=<[^>]*>,)?(?: method=\S+,)? rip=<HOST>(?:[^>]*(?:, session=<\S+>)?)\s*$
|
||||
|
||||
mdre-normal =
|
||||
|
||||
|
|
@ -41,6 +43,7 @@ datepattern = {^LN-BEG}TAI64N
|
|||
# DEV Notes:
|
||||
# * the first regex is essentially a copy of pam-generic.conf
|
||||
# * Probably doesn't do dovecot sql/ldap backends properly (resolved in edit 21/03/2016)
|
||||
# * Dovecot version 2.4 changed event log structure, line prior needed to maintain 2.3 support
|
||||
#
|
||||
# Author: Martin Waschbuesch
|
||||
# Daniel Black (rewrote with begin and end anchors)
|
||||
|
|
|
|||
|
|
@ -23,14 +23,17 @@ before = common.conf
|
|||
|
||||
_daemon = dropbear
|
||||
|
||||
prefregex = ^%(__prefix_line)s<F-CONTENT>(?:[Ll]ogin|[Bb]ad|[Ee]xit).+</F-CONTENT>$
|
||||
prefregex = ^%(__prefix_line)s(?:\[\d+\] \w{2,3} [\d:\s]+)?<F-CONTENT>(?:[Ll]ogin|[Bb]ad|[Ee]xit).+</F-CONTENT>$
|
||||
|
||||
failregex = ^[Ll]ogin attempt for nonexistent user ('.*' )?from <HOST>:\d+$
|
||||
^[Bb]ad (PAM )?password attempt for .+ from <HOST>(:\d+)?$
|
||||
^[Ee]xit before auth \(user '.+', \d+ fails\): Max auth tries reached - user '.+' from <HOST>:\d+\s*$
|
||||
failregex = ^[Ll]ogin attempt for nonexistent user (?:'<F-USER>.*</F-USER>' )?from <HOST>:\d+$
|
||||
^[Bb]ad (?:PAM )?password attempt for '<F-USER>.+</F-USER>' from <HOST>(?::\d+)?$
|
||||
^[Ee]xit before auth from \<?<ADDR>:\d+\>?: (?:\([^\)]*\): )?Max auth tries reached - user '<F-USER>.+</F-USER>'\s*$
|
||||
^[Ee]xit before auth \(user '.+', \d+ fails\): Max auth tries reached - user '<F-USER>.+</F-USER>' from <HOST>:\d+\s*$
|
||||
|
||||
ignoreregex =
|
||||
|
||||
journalmatch = _SYSTEMD_UNIT=dropbear.service + _COMM=dropbear
|
||||
|
||||
# DEV Notes:
|
||||
#
|
||||
# The first two regexs here match the unmodified dropbear messages. It isn't
|
||||
|
|
|
|||
|
|
@ -9,12 +9,43 @@ after = exim-common.local
|
|||
|
||||
[Definition]
|
||||
|
||||
host_info_pre = (?:H=([\w.-]+ )?(?:\(\S+\) )?)?
|
||||
host_info_suf = (?::\d+)?(?: I=\[\S+\](:\d+)?)?(?: U=\S+)?(?: P=e?smtp)?(?: F=(?:<>|[^@]+@\S+))?\s
|
||||
host_info = %(host_info_pre)s\[<HOST>\]%(host_info_suf)s
|
||||
pid = (?: \[\d+\]| \w+ exim\[\d+\]:)?
|
||||
_fields_grp = (?: (?!H=)[A-Za-z]{1,4}(?:=\S+)?)*
|
||||
host_info = %(_fields_grp)s (?:H=)?(?:[\w.-]+)? ?(?:\(\S+\))? ?\[<ADDR>\](?::\d+)?%(_fields_grp)s
|
||||
pid = (?:\s?\[\d+\]|\s?[\w\.-]+ exim\[\d+\]:){0,2}
|
||||
|
||||
# DEV Notes:
|
||||
# From exim source code: ./src/receive.c:add_host_info_for_log
|
||||
#
|
||||
# Author: Daniel Black
|
||||
logtype = file
|
||||
_add_pref = <lt_<logtype>/_add_pref>
|
||||
|
||||
__prefix_line = %(pid)s%(_add_pref)s
|
||||
|
||||
[lt_journal]
|
||||
_add_pref = (?: \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})?
|
||||
|
||||
[lt_file]
|
||||
_add_pref =
|
||||
|
||||
# DEV Notes
|
||||
# ------------
|
||||
# Host string happens:
|
||||
# H=[ip address]
|
||||
# H=(helo_name) [ip address]
|
||||
# H=host_name [ip address]
|
||||
# H=host_name (helo_name) [ip address]
|
||||
# flags H=host_name (helo_name) [ip address] flags
|
||||
# where only [ip address] always visible, ignore ident
|
||||
# From exim source code:
|
||||
# src/src/host.c:host_and_ident()
|
||||
# src/receive.c:add_host_info_for_log()
|
||||
|
||||
# Substitution of `_fields_grp` bypasses all flags but H
|
||||
# Summary of Fields in Log Lines depending on log_selector
|
||||
# https://www.exim.org/exim-html-current/doc/html/spec_html/ch-log_files.html
|
||||
# at version exim-4.97.1
|
||||
# ---
|
||||
|
||||
# Authors:
|
||||
# Cyril Jaquier
|
||||
# Daniel Black (rewrote with strong regexs)
|
||||
# Sergey G. Brester aka sebres (optimization, rewrite to prefregex, reviews)
|
||||
# Martin O'Neal (added additional regexs to detect authentication failures, protocol errors, and drops)
|
||||
# Vladimir Varlamov (host line definition)
|
||||
|
|
|
|||
|
|
@ -26,11 +26,13 @@ before = exim-common.conf
|
|||
|
||||
[Definition]
|
||||
|
||||
failregex = ^%(pid)s \S+ F=(<>|\S+@\S+) %(host_info)srejected by local_scan\(\): .{0,256}$
|
||||
^%(pid)s %(host_info)sF=(<>|[^@]+@\S+) rejected RCPT [^@]+@\S+: .*dnsbl.*\s*$
|
||||
^%(pid)s \S+ %(host_info)sF=(<>|[^@]+@\S+) rejected after DATA: This message contains a virus \(\S+\)\.\s*$
|
||||
^%(pid)s \S+ SA: Action: flagged as Spam but accepted: score=\d+\.\d+ required=\d+\.\d+ \(scanned in \d+/\d+ secs \| Message-Id: \S+\)\. From \S+ \(host=\S+ \[<HOST>\]\) for <honeypot>$
|
||||
^%(pid)s \S+ SA: Action: silently tossed message: score=\d+\.\d+ required=\d+\.\d+ trigger=\d+\.\d+ \(scanned in \d+/\d+ secs \| Message-Id: \S+\)\. From \S+ \(host=(\S+ )?\[<HOST>\]\) for \S+$
|
||||
prefregex = ^%(__prefix_line)s<F-CONTENT>.+</F-CONTENT>$
|
||||
|
||||
failregex = ^\s?\S+%(host_info)s rejected by local_scan\(\): .{0,256}$
|
||||
^%(host_info)s rejected RCPT [^@]+@\S+: .*dnsbl.*\s*$
|
||||
^\s?\S+%(host_info)s rejected after DATA: This message contains a virus \(\S+\)\.\s*$
|
||||
^\s?\S+ SA: Action: flagged as Spam but accepted: score=\d+\.\d+ required=\d+\.\d+ \(scanned in \d+/\d+ secs \| Message-Id: \S+\)\. From \S+ \(host=\S+ \[<HOST>\]\) for <honeypot>$
|
||||
^\s?\S+ SA: Action: silently tossed message: score=\d+\.\d+ required=\d+\.\d+ trigger=\d+\.\d+ \(scanned in \d+/\d+ secs \| Message-Id: \S+\)\. From \S+ \(host=(\S+ )?\[<HOST>\]\) for \S+$
|
||||
|
||||
ignoreregex =
|
||||
|
||||
|
|
@ -43,8 +45,6 @@ ignoreregex =
|
|||
|
||||
honeypot = trap@example.com
|
||||
|
||||
# DEV Notes:
|
||||
# The %(host_info) defination contains a <HOST> match
|
||||
#
|
||||
# Author: Cyril Jaquier
|
||||
# Daniel Black (rewrote with strong regexs)
|
||||
# DEV Notes
|
||||
# -----------
|
||||
# The %(host_info) definition contains a <ADDR> match. No space before. See exim-common.conf
|
||||
|
|
|
|||
|
|
@ -13,21 +13,23 @@ before = exim-common.conf
|
|||
|
||||
[Definition]
|
||||
|
||||
# Fre-filter via "prefregex" is currently inactive because of too different failure syntax in exim-log (testing needed):
|
||||
#prefregex = ^%(pid)s <F-CONTENT>\b(?:\w+ authenticator failed|([\w\-]+ )?SMTP (?:(?:call|connection) from|protocol(?: synchronization)? error)|no MAIL in|(?:%(host_info_pre)s\[[^\]]+\]%(host_info_suf)s(?:sender verify fail|rejected RCPT|dropped|AUTH command))).+</F-CONTENT>$
|
||||
prefregex = ^%(__prefix_line)s<F-CONTENT>.+</F-CONTENT>$
|
||||
|
||||
failregex = ^%(pid)s %(host_info)ssender verify fail for <\S+>: (?:Unknown user|Unrouteable address|all relevant MX records point to non-existent hosts)\s*$
|
||||
^%(pid)s \w+ authenticator failed for (?:[^\[\( ]* )?(?:\(\S*\) )?\[<HOST>\](?::\d+)?(?: I=\[\S+\](:\d+)?)?: 535 Incorrect authentication data( \(set_id=.*\)|: \d+ Time\(s\))?\s*$
|
||||
^%(pid)s %(host_info)srejected RCPT [^@]+@\S+: (?:relay not permitted|Sender verify failed|Unknown user|Unrouteable address)\s*$
|
||||
^%(pid)s SMTP protocol synchronization error \([^)]*\): rejected (?:connection from|"\S+") %(host_info)s(?:next )?input=".*"\s*$
|
||||
^%(pid)s SMTP call from (?:[^\[\( ]* )?%(host_info)sdropped: too many (?:nonmail commands|syntax or protocol errors) \(last (?:command )?was "[^"]*"\)\s*$
|
||||
^%(pid)s SMTP protocol error in "[^"]+(?:"+[^"]*(?="))*?" %(host_info)sAUTH command used when not advertised\s*$
|
||||
^%(pid)s no MAIL in SMTP connection from (?:[^\[\( ]* )?(?:\(\S*\) )?%(host_info)sD=\d\S*s(?: C=\S*)?\s*$
|
||||
^%(pid)s (?:[\w\-]+ )?SMTP connection from (?:[^\[\( ]* )?(?:\(\S*\) )?%(host_info)sclosed by DROP in ACL\s*$
|
||||
failregex = ^\s?\w+ authenticator failed for%(host_info)s: 535 Incorrect authentication data(?: \(set_id=.*\)|: \d+ Time\(s\))?\s*$
|
||||
<mdre-<mode>>
|
||||
|
||||
mdre-aggressive = ^%(pid)s no host name found for IP address <HOST>$
|
||||
^%(pid)s no IP address found for host \S+ \(during SMTP connection from \[<HOST>\]\)$
|
||||
mdre-more = ^%(host_info)s sender verify fail for <\S+>: (?:Unknown user|Unrouteable address|all relevant MX records point to non-existent hosts)\s*$
|
||||
^%(host_info)s rejected RCPT (?:<F-RCPT>[^@]+@\S+</F-RCPT>:)?
|
||||
^\s?SMTP protocol synchronization error \([^)]*\): rejected (?:connection from|"\S+")%(host_info)s (?:next )?input=".*"\s*$
|
||||
^\s?SMTP call from%(host_info)s dropped: too many (?:(?:nonmail|unrecognized) commands|syntax or protocol errors)
|
||||
^\s?SMTP protocol error in "[^"]+(?:"+[^"]*(?="))*?"%(host_info)s [A-Z]+ (?:command used when not advertised|authentication mechanism not supported)\s*$
|
||||
^\s?no MAIL in SMTP connection from%(host_info)s
|
||||
^\s?(?:[\w\-]+ )?SMTP connection from%(host_info)s closed by DROP in ACL\s*$
|
||||
|
||||
mdre-aggressive = %(mdre-more)s
|
||||
^\s?no host name found for IP address <ADDR>$
|
||||
^\s?no IP address found for host \S+ \(during SMTP connection from%(host_info)s\)$
|
||||
^%(host_info)s dropped by '[^']+' ACL:
|
||||
|
||||
mdre-normal =
|
||||
|
||||
|
|
@ -42,13 +44,10 @@ mode = normal
|
|||
|
||||
ignoreregex =
|
||||
|
||||
# DEV Notes:
|
||||
# The %(host_info) defination contains a <HOST> match
|
||||
# DEV Notes
|
||||
# -----------
|
||||
# The %(host_info) definition contains a <ADDR> match. No space before. See exim-common.conf
|
||||
#
|
||||
# SMTP protocol synchronization error \([^)]*\) <- This needs to be non-greedy
|
||||
# to void capture beyond ")" to avoid a DoS Injection vulnerabilty as input= is
|
||||
# to void capture beyond ")" to avoid a DoS Injection vulnerability as input= is
|
||||
# user injectable data.
|
||||
#
|
||||
# Author: Cyril Jaquier
|
||||
# Daniel Black (rewrote with strong regexs)
|
||||
# Martin O'Neal (added additional regexs to detect authentication failures, protocol errors, and drops)
|
||||
|
|
|
|||
|
|
@ -29,9 +29,9 @@ _daemon = freeswitch
|
|||
mode = extra
|
||||
|
||||
# Prefix contains common prefix line (server, daemon, etc.) and 2 datetimes if used systemd backend
|
||||
_pref_line = ^%(__prefix_line)s(?:(?:\d+-)?\d+-\d+ \d+:\d+:\d+\.\d+)?
|
||||
_pref_line = ^%(__prefix_line)s[^\[]*
|
||||
|
||||
prefregex = ^%(_pref_line)s \[WARN(?:ING)?\](?: \[SOFIA\])? \[?sofia_reg\.c:\d+\]? <F-CONTENT>.+</F-CONTENT>$
|
||||
prefregex = ^%(_pref_line)s\s*\[WARN(?:ING)?\](?: \[SOFIA\])? \[?sofia_reg\.c:\d+\]? <F-CONTENT>.+</F-CONTENT>$
|
||||
|
||||
cmnfailre = ^Can't find user \[[^@]+@[^\]]+\] from <HOST>$
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,15 @@
|
|||
# Fail2Ban configuration file to block repeated failed login attempts to Frolor installation(s)
|
||||
#
|
||||
# Froxlor needs to log to Syslog User (e.g. /var/log/user.log) with one of the following messages
|
||||
# <syslog prefix> Froxlor: [Login Action <HOST>] Unknown user '<USER>' tried to login.
|
||||
# <syslog prefix> Froxlor: [Login Action <HOST>] User '<USER>' tried to login with wrong password.
|
||||
# - for type=2
|
||||
# <syslog prefix> froxlor[1-6]: froxlor.WARNING: Unknown user tried to login. {"source":"login","action":"50","user":"<ADDR>"} []
|
||||
# <syslog prefix> froxlor[1-6]: froxlor.WARNING: User tried to login with wrong password. {"source":"login","action":"50","user":"<ADDR>"} []
|
||||
# - for type=1:
|
||||
# <syslog prefix> Froxlor: [Login Action <ADDR>] Unknown user '<USER>' tried to login.
|
||||
# <syslog prefix> Froxlor: [Login Action <ADDR>] User '<USER>' tried to login with wrong password.
|
||||
#
|
||||
# Author: Joern Muehlencord
|
||||
#
|
||||
# Modified: Para-do-x™️ - Andreas Duennwald
|
||||
|
||||
[INCLUDES]
|
||||
|
||||
|
|
@ -13,28 +17,18 @@
|
|||
# common.local
|
||||
before = common.conf
|
||||
|
||||
[DEFAULT]
|
||||
_daemon = [Ff]roxlor
|
||||
|
||||
_re = (?:Unknown )?[uU]ser(?: '<F-USER>(?:\S*|[^']*)</F-USER>')? tried to login(?: with wrong password)?\.
|
||||
|
||||
[type1]
|
||||
failregex = ^%(__prefix_line)s\[Login Action <ADDR>\] %(_re)s$
|
||||
|
||||
[type2]
|
||||
failregex = ^%(__prefix_line)sfroxlor\.WARNING: %(_re)s \{(?:"[^"]+":"[^"]*",\s*){,5}"user":"<ADDR>"\} \[\]$
|
||||
|
||||
[Definition]
|
||||
|
||||
_daemon = Froxlor
|
||||
|
||||
# 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>[\w\-.^_]+)
|
||||
# Values: TEXT
|
||||
#
|
||||
|
||||
prefregex = ^%(__prefix_line)s\[Login Action <HOST>\] <F-CONTENT>.+</F-CONTENT>$
|
||||
|
||||
failregex = ^Unknown user \S* tried to login.$
|
||||
^User \S* tried to login with wrong password.$
|
||||
|
||||
|
||||
# Option: ignoreregex
|
||||
# Notes.: regex to ignore. If this regex matches, the line is ignored.
|
||||
# Values: TEXT
|
||||
#
|
||||
type = 2
|
||||
failregex = <type<type>/failregex>
|
||||
ignoreregex =
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
|
||||
[Definition]
|
||||
|
||||
failregex = ^\s*(?:: )?\(?(?:http|mod)_auth\.c\.\d+\) (?:password doesn\'t match for (?:\S+|.*?) username:\s+<F-USER>(?:\S+|.*?)</F-USER>\s*|digest: auth failed(?: for\s+<F-ALT_USER>(?:\S+|.*?)</F-ALT_USER>\s*)?: (?:wrong password|uri mismatch \([^\)]*\))|get_password failed),? IP: <HOST>\s*$
|
||||
failregex = ^[^\)]*\(?(?:http|mod)_auth\.c\.\d+\) (?:password doesn\'t match for (?:\S+|.*?) username:\s+<F-USER>(?:\S+|.*?)</F-USER>\s*|digest: auth failed(?: for\s+<F-ALT_USER>(?:\S+|.*?)</F-ALT_USER>\s*)?: (?:wrong password|uri mismatch \([^\)]*\))|get_password failed),? IP: <HOST>\s*$
|
||||
|
||||
ignoreregex =
|
||||
ignoreregex =
|
||||
|
||||
# Author: Francois Boulogne <fboulogne@april.org>
|
||||
# Authors: Francois Boulogne <fboulogne@april.org>, Lucian Maly <lmaly@redhat.com>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Fail2Ban filter for unsuccesfull MongoDB authentication attempts
|
||||
# Fail2Ban filter for unsuccessful MongoDB authentication attempts
|
||||
#
|
||||
# Logfile /var/log/mongodb/mongodb.log
|
||||
#
|
||||
|
|
@ -23,7 +23,7 @@ maxlines = 10
|
|||
#
|
||||
# Regarding the multiline regex:
|
||||
#
|
||||
# There can be a nunber of non-related lines between the first and second part
|
||||
# There can be a number of non-related lines between the first and second part
|
||||
# of this regex maxlines of 10 is quite generious.
|
||||
#
|
||||
# Note the capture __connid, includes the connection ID, used in second part of regex.
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
# Fail2Ban filter for unsuccesful MySQL authentication attempts
|
||||
# Fail2Ban filter for unsuccessful MySQL authentication attempts
|
||||
#
|
||||
#
|
||||
# To log wrong MySQL access attempts add to /etc/my.cnf in [mysqld]:
|
||||
# log-error=/var/log/mysqld.log
|
||||
# log-warnings = 2
|
||||
# To log wrong MySQL access attempts add to /etc/my.cnf in [mysqld],
|
||||
# `log_error_verbosity` system variable set to 3 (`log-warnings = 2` for older versions),
|
||||
# and check whether `log_error` (or `log-error`) system variable would match the `logpath` of fail2ban
|
||||
# (see https://dev.mysql.com/doc/refman/en/communication-errors.html)
|
||||
#
|
||||
# If using mysql syslog [mysql_safe] has syslog in /etc/my.cnf
|
||||
|
||||
|
|
@ -17,7 +18,7 @@ before = common.conf
|
|||
|
||||
_daemon = mysqld
|
||||
|
||||
failregex = ^%(__prefix_line)s(?:(?:\d{6}|\d{4}-\d{2}-\d{2})[ T]\s?\d{1,2}:\d{2}:\d{2} )?(?:\d+ )?\[\w+\] (?:\[[^\]]+\] )*Access denied for user '<F-USER>[^']+</F-USER>'@'<HOST>' (to database '[^']*'|\(using password: (YES|NO)\))*\s*$
|
||||
failregex = ^%(__prefix_line)s(?:(?:\d{6}|\d{4}-\d{2}-\d{2})[ T]\s?\d{1,2}:\d{2}:\d{2} )?(?:\d+ )?\[\w+\] (?:\[[^\]]+\] )*Access denied for user '<F-USER>[^']+</F-USER>'@'<HOST>'(?:\s+(?:to database '[^']*'|\(using password: (?:YES|NO)\)){1,2})?\s*$
|
||||
|
||||
ignoreregex =
|
||||
|
||||
|
|
|
|||
|
|
@ -30,11 +30,14 @@ __pid_re=(?:\[\d+\])
|
|||
__daemon_re=\(?%(_daemon)s(?:\(\S+\))?\)?:?
|
||||
__daemon_combs_re=(?:%(__pid_re)s?:\s+%(__daemon_re)s|%(__daemon_re)s%(__pid_re)s?:)
|
||||
|
||||
_category = (?!error|info)[\w-]+
|
||||
_category_re = (?:%(_category)s: )?
|
||||
|
||||
# hostname daemon_id spaces
|
||||
# this can be optional (for instance if we match named native log files)
|
||||
__line_prefix=(?:\s*\S+ %(__daemon_combs_re)s\s+)?
|
||||
__line_prefix=\s*(?:\S+ %(__daemon_combs_re)s\s+)?%(_category_re)s
|
||||
|
||||
prefregex = ^%(__line_prefix)s(?: error:)?\s*client(?: @\S*)? <HOST>#\S+(?: \([\S.]+\))?: <F-CONTENT>.+</F-CONTENT>\s(?:denied|\(NOTAUTH\))\s*$
|
||||
prefregex = ^%(__line_prefix)s(?:(?:error|info):\s*)?client(?: @\S*)? <HOST>#\S+(?: \([\S.]+\))?: <F-CONTENT>.+</F-CONTENT>\s(?:denied(?: \([^\)]*\))?|\(NOTAUTH\))\s*$
|
||||
|
||||
failregex = ^(?:view (?:internal|external): )?query(?: \(cache\))?
|
||||
^zone transfer
|
||||
|
|
|
|||
32
config/filter.d/nginx-error-common.conf
Normal file
32
config/filter.d/nginx-error-common.conf
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
# Generic nginx error_log configuration items (to be used as interpolations) in other
|
||||
# filters monitoring nginx error-logs
|
||||
#
|
||||
|
||||
[DEFAULT]
|
||||
|
||||
# Type of log-file resp. log-format (file, short, journal):
|
||||
logtype = file
|
||||
|
||||
# Daemon definition is to be specialized (if needed) in .conf file
|
||||
_daemon = nginx
|
||||
|
||||
# Common line prefixes (beginnings) which could be used in filters
|
||||
#
|
||||
# [bsdverbose]? [hostname] [vserver tag] daemon_id spaces
|
||||
#
|
||||
# This can be optional (for instance if we match named native log files)
|
||||
__prefix = <lt_<logtype>/__prefix>
|
||||
|
||||
__err_type = error
|
||||
|
||||
__prefix_line = %(__prefix)s\[%(__err_type)s\] \d+#\d+: \*\d+\s+
|
||||
|
||||
|
||||
[lt_file]
|
||||
__prefix = \s*
|
||||
|
||||
[lt_short]
|
||||
__prefix = \s*(?:(?!\[)\S+ %(_daemon)s\[\d+\]: [^\[]*)?
|
||||
|
||||
[lt_journal]
|
||||
__prefix = %(lt_short/__prefix)s
|
||||
29
config/filter.d/nginx-forbidden.conf
Normal file
29
config/filter.d/nginx-forbidden.conf
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
# fail2ban filter configuration for nginx forbidden accesses
|
||||
#
|
||||
# If you have configured nginx to forbid some paths in your webserver, e.g.:
|
||||
#
|
||||
# location ~ /\. {
|
||||
# deny all;
|
||||
# }
|
||||
#
|
||||
# if a client tries to access https://yoursite/.user.ini then you will see
|
||||
# in nginx error log:
|
||||
#
|
||||
# 2018/09/14 19:03:05 [error] 2035#2035: *9134 access forbidden by rule, client: 10.20.30.40, server: www.example.net, request: "GET /.user.ini HTTP/1.1", host: "www.example.net", referrer: "https://www.example.net"
|
||||
#
|
||||
# By carefully setting this filter we ban every IP that tries too many times to
|
||||
# access forbidden resources.
|
||||
#
|
||||
# Author: Michele Bologna https://www.michelebologna.net/
|
||||
|
||||
[INCLUDES]
|
||||
|
||||
before = nginx-error-common.conf
|
||||
|
||||
[Definition]
|
||||
failregex = ^%(__prefix_line)saccess forbidden by rule, client: <HOST>
|
||||
ignoreregex =
|
||||
|
||||
datepattern = {^LN-BEG}
|
||||
|
||||
journalmatch = _SYSTEMD_UNIT=nginx.service + _COMM=nginx
|
||||
|
|
@ -1,14 +1,25 @@
|
|||
# fail2ban filter configuration for nginx
|
||||
|
||||
[INCLUDES]
|
||||
|
||||
before = nginx-error-common.conf
|
||||
|
||||
[Definition]
|
||||
|
||||
mode = normal
|
||||
|
||||
mdre-auth = ^\s*\[error\] \d+#\d+: \*\d+ user "(?:[^"]+|.*?)":? (?:password mismatch|was not found in "[^\"]*"), client: <HOST>, server: \S*, request: "\S+ \S+ HTTP/\d+\.\d+", host: "\S+"(?:, referrer: "\S+")?\s*$
|
||||
mdre-fallback = ^\s*\[crit\] \d+#\d+: \*\d+ SSL_do_handshake\(\) failed \(SSL: error:\S+(?: \S+){1,3} too (?:long|short)\)[^,]*, client: <HOST>
|
||||
__err_type = (?:error|crit)
|
||||
|
||||
__suffix_line = , client: <ADDR>(?:, (?:server|request|host|referrer): (?:"[^"]*"|\S*)){0,4}
|
||||
|
||||
prefregex = ^%(__prefix_line)s<F-CONTENT>.*</F-CONTENT>%(__suffix_line)s\s*$
|
||||
|
||||
mdre-auth = ^user "<F-USER>(?:[^"]+|.*?)</F-USER>":? (?:password mismatch|was not found in "[^\"]*")$
|
||||
^(?:PAM: )?user '<F-USER>(?:[^']+|.*?)</F-USER>' - not authenticated: Authentication failure$
|
||||
mdre-fallback = ^SSL_(?:do_handshake|read)\(\) failed \(SSL: error:\S+(?: \S+){1,3}[^\)]*\)[^,]*
|
||||
|
||||
mdre-normal = %(mdre-auth)s
|
||||
|
||||
mdre-aggressive = %(mdre-auth)s
|
||||
%(mdre-fallback)s
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,10 @@
|
|||
# ...
|
||||
#
|
||||
|
||||
[INCLUDES]
|
||||
|
||||
before = nginx-error-common.conf
|
||||
|
||||
[Definition]
|
||||
|
||||
# Specify following expression to define exact zones, if you want to ban IPs limited
|
||||
|
|
@ -33,13 +37,16 @@
|
|||
#
|
||||
ngx_limit_req_zones = [^"]+
|
||||
|
||||
# Depending on limit_req_log_level directive (may be: info | notice | warn | error):
|
||||
__err_type = [a-z]+
|
||||
|
||||
# Use following full expression if you should range limit request to specified
|
||||
# servers, requests, referrers etc. only :
|
||||
#
|
||||
# failregex = ^\s*\[[a-z]+\] \d+#\d+: \*\d+ limiting requests, excess: [\d\.]+ by zone "(?:%(ngx_limit_req_zones)s)", client: <HOST>, server: \S*, request: "\S+ \S+ HTTP/\d+\.\d+", host: "\S+"(, referrer: "\S+")?\s*$
|
||||
# failregex = ^%(__prefix_line)slimiting requests, excess: [\d\.]+ by zone "(?:%(ngx_limit_req_zones)s)", client: <HOST>, server: \S*, request: "\S+ \S+ HTTP/\d+\.\d+", host: "\S+"(, referrer: "\S+")?\s*$
|
||||
|
||||
# Shortly, much faster and stable version of regexp:
|
||||
failregex = ^\s*\[[a-z]+\] \d+#\d+: \*\d+ limiting requests, excess: [\d\.]+ by zone "(?:%(ngx_limit_req_zones)s)", client: <HOST>,
|
||||
failregex = ^%(__prefix_line)s(?:limiting|delaying) (?:request|connection)s?(?:, excess: [\d\.]+,?)? by zone "(?:%(ngx_limit_req_zones)s)", client: <ADDR>,
|
||||
|
||||
ignoreregex =
|
||||
|
||||
|
|
|
|||
13
config/filter.d/openvpn.conf
Normal file
13
config/filter.d/openvpn.conf
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
# Fail2Ban filter for openvpn server
|
||||
# Detecting wrong TLS handshakes
|
||||
# typically logged in /var/log/syslog
|
||||
# Author: Philipp Burndorfer
|
||||
|
||||
[INCLUDES]
|
||||
before = common.conf
|
||||
|
||||
[Definition]
|
||||
_daemon = ovpn-server\d*
|
||||
|
||||
failregex = ^%(__prefix_line)s<HOST>:\d{4,5} (?:TLS Auth Error:|VERIFY ERROR:|TLS Error: TLS handshake failed\b|SIGUSR1\[soft,connection-reset\] received\b)
|
||||
^%(__prefix_line)sTLS Error: cannot locate HMAC in incoming packet from \[AF_INET\]\s*<HOST>:\d{4,5}
|
||||
|
|
@ -10,50 +10,63 @@ before = common.conf
|
|||
|
||||
[Definition]
|
||||
|
||||
_daemon = postfix(-\w+)?/\w+(?:/smtp[ds])?
|
||||
_daemon = postfix\b([^\[\s]+)?
|
||||
# optional port:
|
||||
_port = (?::\d+)?
|
||||
_pref = [A-Z]{4}
|
||||
# optional prefix like `NOQUEUE: ` or `00ADB3C0899: ` etc...
|
||||
_pref = (?:\w+: )?
|
||||
# SMTP commands like RCPT etc
|
||||
_cmd = [A-Z]{4,}
|
||||
|
||||
prefregex = ^%(__prefix_line)s<mdpr-<mode>> <F-CONTENT>.+</F-CONTENT>$
|
||||
prefregex = ^%(__prefix_line)s%(_pref)s<mdpr-<mode>> <F-CONTENT>.+</F-CONTENT>$
|
||||
|
||||
# Extended RE for normal mode to match reject by unknown users or undeliverable address, can be set to empty to avoid this:
|
||||
exre-user = |[Uu](?:ser unknown|ndeliverable address)
|
||||
exre-user = |[Uu](?:ser unknown|ndeliverable address) ; pragma: codespell-ignore
|
||||
|
||||
mdpr-normal = (?:\w+: (?:milter-)?reject:|(?:improper command pipelining|too many errors) after \S+)
|
||||
mdre-normal=^%(_pref)s from [^[]*\[<HOST>\]%(_port)s: [45][50][04] [45]\.\d\.\d+ (?:(?:<[^>]*>)?: )?(?:(?:Helo command|(?:Sender|Recipient) address) rejected: )?(?:Service unavailable|(?:Client host|Command|Data command) rejected|Relay access denied|(?:Host|Domain) not found|need fully-qualified hostname|match%(exre-user)s)\b
|
||||
mdpr-normal = (?:(?:milter-)?reject:|(?:improper command pipelining|too many errors) after \S+)
|
||||
mdre-normal=^%(_cmd)s from [^[]*\[<HOST>\]%(_port)s: [45][50][04] [45]\.\d\.\d+ (?:(?:<[^>]*>)?: )?(?:(?:Helo command|(?:Sender|Recipient) address) rejected: )?(?:Service unavailable|Access denied|(?:Client host|Command|Data command) rejected|Relay access denied|Malformed DNS server reply|(?:Host|Domain) not found|need fully-qualified hostname|match%(exre-user)s)\b
|
||||
^from [^[]*\[<HOST>\]%(_port)s:?
|
||||
mdad-normal =
|
||||
|
||||
mdpr-auth = warning:
|
||||
mdre-auth = ^[^[]*\[<HOST>\]%(_port)s: SASL ((?i)LOGIN|PLAIN|(?:CRAM|DIGEST)-MD5) authentication failed:(?! Connection lost to authentication server| Invalid authentication mechanism)
|
||||
mdre-auth2= ^[^[]*\[<HOST>\]%(_port)s: SASL ((?i)LOGIN|PLAIN|(?:CRAM|DIGEST)-MD5) authentication failed:(?! Connection lost to authentication server)
|
||||
# todo: check/remove "Invalid authentication mechanism" from ignore list, if gh-1243 will get finished (see gh-1297).
|
||||
mdad-auth =
|
||||
mdad-auth2 =
|
||||
|
||||
# Mode "rbl" currently included in mode "normal", but if needed for jail "postfix-rbl" only:
|
||||
mdpr-rbl = %(mdpr-normal)s
|
||||
mdre-rbl = ^%(_pref)s from [^[]*\[<HOST>\]%(_port)s: [45]54 [45]\.7\.1 Service unavailable; Client host \[\S+\] blocked\b
|
||||
mdre-rbl = ^%(_cmd)s from [^[]*\[<HOST>\]%(_port)s: [45]54 [45]\.7\.1 Service unavailable; Client host \[\S+\] blocked\b
|
||||
mdad-rbl =
|
||||
|
||||
# Mode "rbl" currently included in mode "normal" (within 1st rule)
|
||||
mdpr-more = %(mdpr-normal)s
|
||||
mdre-more = %(mdre-normal)s
|
||||
mdad-more =
|
||||
|
||||
# Includes some of the log messages described in
|
||||
# <http://www.postfix.org/POSTSCREEN_README.html>.
|
||||
mdpr-ddos = (?:lost connection after(?! DATA) [A-Z]+|disconnect(?= from \S+(?: \S+=\d+)* auth=0/(?:[1-9]|\d\d+))|(?:PREGREET \d+|HANGUP) after \S+|COMMAND (?:TIME|COUNT|LENGTH) LIMIT)
|
||||
mdpr-ddos = (?:lost connection after (?!(?:DATA|AUTH)\b)[A-Z]+|disconnect(?= from \S+(?: \S+=\d+)* auth=0/(?:[1-9]|\d\d+))|(?:PREGREET \d+|HANGUP) after \S+|COMMAND (?:TIME|COUNT|LENGTH) LIMIT|warning:)
|
||||
mdre-ddos = ^from [^[]*\[<HOST>\]%(_port)s:?
|
||||
mdad-ddos = ^(?:Message delivery request|Connection) rate limit exceeded: \d+ from [^[]*\[<ADDR>\]
|
||||
|
||||
mdpr-extra = (?:%(mdpr-auth)s|%(mdpr-normal)s)
|
||||
mdre-extra = %(mdre-auth)s
|
||||
%(mdre-normal)s
|
||||
mdad-extra =
|
||||
|
||||
mdpr-aggressive = (?:%(mdpr-auth)s|%(mdpr-normal)s|%(mdpr-ddos)s)
|
||||
mdre-aggressive = %(mdre-auth2)s
|
||||
%(mdre-normal)s
|
||||
mdad-aggressive = %(mdad-ddos)s
|
||||
|
||||
mdpr-errors = too many errors after \S+
|
||||
mdre-errors = ^from [^[]*\[<HOST>\]%(_port)s$
|
||||
|
||||
mdad-errors =
|
||||
|
||||
failregex = <mdre-<mode>>
|
||||
<mdad-<mode>>
|
||||
|
||||
# Parameter "mode": more (default combines normal and rbl), auth, normal, rbl, ddos, extra or aggressive (combines all)
|
||||
# Usage example (for jail.local):
|
||||
|
|
@ -76,6 +89,6 @@ ignoreregex =
|
|||
|
||||
[Init]
|
||||
|
||||
journalmatch = _SYSTEMD_UNIT=postfix.service
|
||||
journalmatch = _SYSTEMD_UNIT=postfix.service _SYSTEMD_UNIT=postfix@-.service
|
||||
|
||||
# Author: Cyril Jaquier
|
||||
|
|
|
|||
20
config/filter.d/proxmox.conf
Normal file
20
config/filter.d/proxmox.conf
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
# Fail2Ban filter for Proxmox Web GUI
|
||||
#
|
||||
# Jail example:
|
||||
# [proxmox]
|
||||
# enabled = true
|
||||
# port = https,http,8006
|
||||
# filter = proxmox
|
||||
# logpath = /var/log/daemon.log
|
||||
# maxretry = 3
|
||||
# # 1 hour
|
||||
# bantime = 3600
|
||||
|
||||
[Definition]
|
||||
|
||||
_daemon = pvedaemon
|
||||
|
||||
failregex = ^\s*\S+ %(_daemon)s\[\d+\]: authentication failure; rhost=<ADDR> user=<F-USER>\S+</F-USER>
|
||||
|
||||
ignoreregex =
|
||||
|
||||
|
|
@ -19,20 +19,34 @@
|
|||
# common.local
|
||||
before = common.conf
|
||||
|
||||
[Definition]
|
||||
[DEFAULT]
|
||||
|
||||
_daemon = (?:fail2ban(?:-server|\.actions)\s*)
|
||||
|
||||
# The name of the jail that this filter is used for. In jail.conf, name the jail using
|
||||
# this filter 'recidive', or supply another name with `filter = recidive[_jailname="jail"]`
|
||||
_jailname = recidive
|
||||
# this filter 'recidive', or supply another name with `filter = recidive[_jailname="jail"]`,
|
||||
# default all jails excepting recidive
|
||||
_jailname = (?!recidive\])[^\]]*
|
||||
|
||||
failregex = ^%(__prefix_line)s(?:\s*fail2ban\.actions\s*%(__pid_re)s?:\s+)?NOTICE\s+\[(?!%(_jailname)s\])(?:.*)\]\s+Ban\s+<HOST>\s*$
|
||||
failregex = ^%(__prefix_line)s(?:\s*fail2ban\.actions\s*%(__pid_re)s?:\s+)?NOTICE\s+\[<_jailname>\]\s+Ban\s+<HOST>
|
||||
|
||||
[lt_short]
|
||||
_daemon = (?:fail2ban(?:-server|\.actions)?\s*)
|
||||
failregex = ^%(__prefix_line)s(?:\s*fail2ban(?:\.actions)?\s*%(__pid_re)s?:\s+)?(?:NOTICE\s+)?\[<_jailname>\]\s+Ban\s+<HOST>
|
||||
|
||||
[lt_journal]
|
||||
_daemon = <lt_short/_daemon>
|
||||
failregex = <lt_short/failregex>
|
||||
|
||||
[Definition]
|
||||
|
||||
_daemon = <lt_<logtype>/_daemon>
|
||||
failregex = <lt_<logtype>/failregex>
|
||||
|
||||
datepattern = ^{DATE}
|
||||
|
||||
ignoreregex =
|
||||
|
||||
journalmatch = _SYSTEMD_UNIT=fail2ban.service PRIORITY=5
|
||||
journalmatch = _SYSTEMD_UNIT=fail2ban.service
|
||||
|
||||
# Author: Tom Hendrikx, modifications by Amir Caspi
|
||||
|
|
|
|||
|
|
@ -13,10 +13,9 @@ before = common.conf
|
|||
|
||||
[Definition]
|
||||
|
||||
prefregex = ^\s*(\[\])?(%(__hostname)s\s*(?:roundcube(?:\[(\d*)\])?:)?\s*(<[\w]+>)? IMAP Error)?: <F-CONTENT>.+</F-CONTENT>$
|
||||
prefregex = ^\s*(\[\])?(%(__hostname)s\s*(?:roundcube(?:\[(\d*)\])?:)?\s*(<[\w]+>)? IMAP Error)?: (?:<[\w]+> )?<F-CONTENT>.+</F-CONTENT>$
|
||||
|
||||
failregex = ^(?:FAILED login|Login failed) for <F-USER>.*</F-USER> from <HOST>(?:(?:\([^\)]*\))?\. (?:(?! from ).)*(?: user=(?P=user))? in \S+\.php on line \d+ \(\S+ \S+\))?$
|
||||
^(?:<[\w]+> )?Failed login for <F-USER>.*</F-USER> from <HOST> in session \w+( \(error: \d\))?$
|
||||
failregex = ^(?:Login failed|(?i:Failed) login) for <F-USER>(?:(?P<simple>\S+)|.*)</F-USER> (?:against \S+ )?from <ADDR>(?:(?:\([^\)]*\))?\.(?! from ) (?(simple)(?:\S+(?! from ) )*|(?:(?! from ).)*(?: user=(?P=user))? )in \S+\.php on line \d+| in session \w+)?(?: \([^\)]*\))?$
|
||||
|
||||
ignoreregex =
|
||||
|
||||
|
|
|
|||
10
config/filter.d/routeros-auth.conf
Normal file
10
config/filter.d/routeros-auth.conf
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# Fail2Ban filter for failure attempts in MikroTik RouterOS
|
||||
#
|
||||
#
|
||||
|
||||
[Definition]
|
||||
|
||||
failregex = ^\s*\S+ system,error,critical login failure for user <F-USER>.*?</F-USER> from <ADDR> via \S+$
|
||||
|
||||
# Author: Vit Kabele <vit@kabele.me>
|
||||
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
[Definition]
|
||||
|
||||
failregex = ^type=%(_type)s msg=audit\(:\d+\): (user )?pid=\d+ uid=%(_uid)s auid=%(_auid)s ses=\d+ subj=%(_subj)s msg='%(_msg)s'$
|
||||
failregex = ^type=%(_type)s msg=audit\(:\d+\): (?:user )?pid=\d+ uid=%(_uid)s auid=%(_auid)s ses=\d+ subj=%(_subj)s msg='%(_msg)s'(?:\x1D|$)
|
||||
|
||||
ignoreregex =
|
||||
|
||||
|
|
|
|||
|
|
@ -15,11 +15,13 @@ _subj = (?:unconfined_u|system_u):system_r:sshd_t:s0-s0:c0\.c1023
|
|||
_exe =/usr/sbin/sshd
|
||||
_terminal = ssh
|
||||
|
||||
_msg = op=\S+ acct=(?P<_quote_acct>"?)\S+(?P=_quote_acct) exe="%(_exe)s" hostname=(\?|(\d+\.){3}\d+) addr=<HOST> terminal=%(_terminal)s res=failed
|
||||
_anygrp = (?!acct=|exe=|addr=|terminal=|res=)\w+=(?:"[^"]+"|\S*)
|
||||
|
||||
_msg = (?:%(_anygrp)s )*acct=(?:"<F-USER>[^"]+</F-USER>"|<F-ALT_USER>\S+</F-ALT_USER>) exe="%(_exe)s" (?:%(_anygrp)s )*addr=<ADDR> terminal=%(_terminal)s res=failed
|
||||
|
||||
# DEV Notes:
|
||||
#
|
||||
# Note: USER_LOGIN is ignored as this is the duplicate messsage
|
||||
# Note: USER_LOGIN is ignored as this is the duplicate message
|
||||
# ssh logs after 3 USER_AUTH failures.
|
||||
#
|
||||
# Author: Daniel Black
|
||||
|
|
|
|||
|
|
@ -22,21 +22,28 @@ before = common.conf
|
|||
_daemon = (?:(sm-(mta|acceptingconnections)|sendmail))
|
||||
__prefix_line = %(known/__prefix_line)s(?:\w{14,20}: )?
|
||||
addr = (?:(?:IPv6:)?<IP6>|<IP4>)
|
||||
# mta_dname -- matches name of MTA daemon (typically specified in DAEMON_OPTIONS),
|
||||
# normally something without spaces like MTA-v4 or Deamon0, etc. If it'd contain spaces, one can
|
||||
# rewrite it in jail using `filter = %(known/filter)s[mta_dname="[^,]+"]` or in .local overwrite
|
||||
# of the filter. (we would not use catch-alls here to satisfy obscure artificial case).
|
||||
mta_dname = \S+
|
||||
|
||||
prefregex = ^<F-MLFID>%(__prefix_line)s</F-MLFID><F-CONTENT>.+</F-CONTENT>$
|
||||
prefregex = ^\s*(?:<mail\.[^\>]+> )?<F-MLFID>%(__prefix_line)s</F-MLFID><F-CONTENT>.+</F-CONTENT>$
|
||||
|
||||
cmnfailre = ^ruleset=check_rcpt, arg1=(?P<email><\S+@\S+>), relay=(\S+ )?\[%(addr)s\](?: \(may be forged\))?, reject=(?:550 5\.7\.1(?: (?P=email)\.\.\.)?(?: Relaying denied\.)? (?:IP name possibly forged \[(\d+\.){3}\d+\]|Proper authentication required\.|IP name lookup failed \[(\d+\.){3}\d+\]|Fix reverse DNS for \S+)|553 5\.1\.8(?: (?P=email)\.\.\.)? Domain of sender address \S+ does not exist|550 5\.[71]\.1 (?P=email)\.\.\. (Rejected: .*|User unknown))$
|
||||
cmnfailre = ^ruleset=check_rcpt, arg1=(?P<email><\S+@\S+>), relay=(\S+ )?\[%(addr)s\](?: \(may be forged\))?, reject=(?:550 5\.7\.1(?: (?P=email)\.\.\.)?(?: Relaying denied\.)? (?:IP name possibly forged \[(\d+\.){3}\d+\]|Proper authentication required\.|IP name lookup failed \[(\d+\.){3}\d+\]|Fix reverse DNS for \S+)|[45]5[13] [45]\.1\.8(?: (?P=email)\.\.\.)? Domain of sender address \S+ does not (?:exist|resolve)|550 5\.[71]\.1 (?P=email)\.\.\. (Rejected: .*|User unknown))$
|
||||
^ruleset=check_relay(?:, arg\d+=\S*)*, relay=(\S+ )?\[%(addr)s\](?: \(may be forged\))?, reject=421 4\.3\.2 (Connection rate limit exceeded\.|Too many open connections\.)$
|
||||
^rejecting commands from (\S* )?\[%(addr)s\] due to pre-greeting traffic after \d+ seconds$
|
||||
^(?:\S+ )?\[%(addr)s\]: (?:(?i)expn|vrfy) \S+ \[rejected\]$
|
||||
^<[^@]+@[^>]+>\.\.\. No such user here$
|
||||
^<F-NOFAIL>from=<[^@]+@[^>]+></F-NOFAIL>, size=\d+, class=\d+, nrcpts=\d+, bodytype=\w+, proto=E?SMTP, daemon=MTA, relay=\S+ \[%(addr)s\]$
|
||||
^<[^@]+@[^>]+>\.\.\. (?:No such user here|User unknown)$
|
||||
^<F-NOFAIL>from=<[^@]+@[^>]+></F-NOFAIL>, size=\d+, class=\d+, nrcpts=\d+,(?: bodytype=\w+,)? proto=E?SMTP, daemon=%(mta_dname)s, relay=(?:\S+ )?\[%(addr)s\]$
|
||||
|
||||
mdre-normal =
|
||||
|
||||
mdre-extra = ^(?:\S+ )?\[%(addr)s\](?: \(may be forged\))? did not issue \S+ during connection
|
||||
|
||||
mdre-aggressive = %(mdre-extra)s
|
||||
^lost input channel from (?:\S+ )?\[%(addr)s\] to %(mta_dname)s after rcpt$
|
||||
^ruleset=check_rcpt, arg1=(?P<email><\S+@\S+>), relay=(?:\S+ )?\[%(addr)s\](?: \(may be forged\))?, reject=(?:450 4\.4\.0(?: (?P=email)\.\.\.)?(?: Relaying temporarily denied\.)?(?: Cannot resolve PTR record for (\d+\.){3}\d+))$
|
||||
|
||||
failregex = %(cmnfailre)s
|
||||
<mdre-<mode>>
|
||||
|
|
@ -63,6 +70,8 @@ journalmatch = SYSLOG_IDENTIFIER=sm-mta + _SYSTEMD_UNIT=sendmail.service
|
|||
# Note the capture <F-MLFID>, includes both the __prefix_lines (which includes
|
||||
# the sendmail PID), but also the `\w{14}` which the the sendmail assigned
|
||||
# mail ID (todo: check this is necessary, possible obsolete).
|
||||
# Avoid moving <F-MLFID> into the entire prefregex because the grouped messages we
|
||||
# need have different syslog levels (info vs notice) that break the group if BSD verbose format is set
|
||||
#
|
||||
# Author: Daniel Black, Fabian Wenk and Sergey Brester aka sebres.
|
||||
# Rewritten using prefregex by Serg G. Brester.
|
||||
|
|
|
|||
|
|
@ -13,13 +13,11 @@ before = common.conf
|
|||
|
||||
_daemon = slapd
|
||||
|
||||
failregex = ^(?P<__prefix>%(__prefix_line)s)conn=(?P<_conn_>\d+) fd=\d+ ACCEPT from IP=<HOST>:\d{1,5} \(IP=\S+\)\s*<SKIPLINES>(?P=__prefix)conn=(?P=_conn_) op=\d+ RESULT(?:\s(?!err)\S+=\S*)* err=49 text=[\w\s]*$
|
||||
prefregex = ^%(__prefix_line)sconn=<F-MLFID>\d+</F-MLFID>(?: (?:fd|op)=\d+){0,2} (?=ACCEPT|RESULT)<F-CONTENT>.+</F-CONTENT>$
|
||||
|
||||
failregex = ^<F-NOFAIL>ACCEPT</F-NOFAIL> from IP=<ADDR>:\d{1,5}\s+
|
||||
^RESULT(?:\s(?!err)\S+=\S*)* err=49\b
|
||||
|
||||
ignoreregex =
|
||||
|
||||
[Init]
|
||||
|
||||
# "maxlines" is number of log lines to buffer for multi-line regex searches
|
||||
maxlines = 20
|
||||
|
||||
# Author: Andrii Melnyk
|
||||
# Author: Andrii Melnyk, Sergey G. Brester
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Fail2ban filter for SOGo authentcation
|
||||
# Fail2ban filter for SOGo authentication
|
||||
#
|
||||
# Log file usually in /var/log/sogo/sogo.log
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ before = common.conf
|
|||
|
||||
[DEFAULT]
|
||||
|
||||
_daemon = sshd
|
||||
_daemon = sshd(?:-session)?
|
||||
|
||||
# optional prefix (logged from several ssh versions) like "error: ", "error: PAM: " or "fatal: "
|
||||
__pref = (?:(?:error|fatal): (?:PAM: )?)?
|
||||
|
|
@ -24,8 +24,8 @@ __pref = (?:(?:error|fatal): (?:PAM: )?)?
|
|||
#__suff = (?: port \d+)?(?: \[preauth\])?\s*
|
||||
__suff = (?: (?:port \d+|on \S+|\[preauth\])){0,3}\s*
|
||||
__on_port_opt = (?: (?:port \d+|on \S+)){0,2}
|
||||
# close by authenticating user:
|
||||
__authng_user = (?: (?:invalid|authenticating) user <F-USER>\S+|.*?</F-USER>)?
|
||||
# close by authenticating user (don't use <HOST> after %(__authng_user)s because of catch-all `.*?`):
|
||||
__authng_user = (?: (?:by|from))?(?: (?:invalid|authenticating) user <F-USER>\S+|.*?</F-USER>)?(?: from)?
|
||||
|
||||
# for all possible (also future) forms of "no matching (cipher|mac|MAC|compression method|key exchange method|host key type) found",
|
||||
# see ssherr.c for all possible SSH_ERR_..._ALG_MATCH errors.
|
||||
|
|
@ -38,21 +38,21 @@ __pam_auth = pam_[a-z]+
|
|||
|
||||
prefregex = ^<F-MLFID>%(__prefix_line)s</F-MLFID>%(__pref)s<F-CONTENT>.+</F-CONTENT>$
|
||||
|
||||
cmnfailre = ^[aA]uthentication (?:failure|error|failed) for <F-USER>.*</F-USER> from <HOST>( via \S+)?%(__suff)s$
|
||||
^User not known to the underlying authentication module for <F-USER>.*</F-USER> from <HOST>%(__suff)s$
|
||||
cmnfailre = ^[aA]uthentication (?:failure|error|failed) for <F-USER>.*?</F-USER> (?:from )?<HOST>( via \S+)?%(__suff)s$
|
||||
^User not known to the underlying authentication module for <F-USER>.*?</F-USER> (?:from )?<HOST>%(__suff)s$
|
||||
<cmnfailre-failed-pub-<publickey>>
|
||||
^Failed <cmnfailed> for (?P<cond_inv>invalid user )?<F-USER>(?P<cond_user>\S+)|(?(cond_inv)(?:(?! from ).)*?|[^:]+)</F-USER> from <HOST>%(__on_port_opt)s(?: ssh\d*)?(?(cond_user): |(?:(?:(?! from ).)*)$)
|
||||
^<F-USER>ROOT</F-USER> LOGIN REFUSED FROM <HOST>
|
||||
^[iI](?:llegal|nvalid) user <F-USER>.*?</F-USER> from <HOST>%(__suff)s$
|
||||
^User <F-USER>\S+|.*?</F-USER> from <HOST> not allowed because not listed in AllowUsers%(__suff)s$
|
||||
^User <F-USER>\S+|.*?</F-USER> from <HOST> not allowed because listed in DenyUsers%(__suff)s$
|
||||
^User <F-USER>\S+|.*?</F-USER> from <HOST> not allowed because not in any group%(__suff)s$
|
||||
^[iI](?:llegal|nvalid) user <F-USER>.*?</F-USER> (?:from )?<HOST>%(__suff)s$
|
||||
^User <F-USER>\S+|.*?</F-USER> (?:from )?<HOST> not allowed because not listed in AllowUsers%(__suff)s$
|
||||
^User <F-USER>\S+|.*?</F-USER> (?:from )?<HOST> not allowed because listed in DenyUsers%(__suff)s$
|
||||
^User <F-USER>\S+|.*?</F-USER> (?:from )?<HOST> not allowed because not in any group%(__suff)s$
|
||||
^refused connect from \S+ \(<HOST>\)
|
||||
^Received <F-MLFFORGET>disconnect</F-MLFFORGET> from <HOST>%(__on_port_opt)s:\s*3: .*: Auth fail%(__suff)s$
|
||||
^User <F-USER>\S+|.*?</F-USER> from <HOST> not allowed because a group is listed in DenyGroups%(__suff)s$
|
||||
^User <F-USER>\S+|.*?</F-USER> from <HOST> not allowed because none of user's groups are listed in AllowGroups%(__suff)s$
|
||||
^User <F-USER>\S+|.*?</F-USER> (?:from )?<HOST> not allowed because a group is listed in DenyGroups%(__suff)s$
|
||||
^User <F-USER>\S+|.*?</F-USER> (?:from )?<HOST> not allowed because none of user's groups are listed in AllowGroups%(__suff)s$
|
||||
^<F-NOFAIL>%(__pam_auth)s\(sshd:auth\):\s+authentication failure;</F-NOFAIL>(?:\s+(?:(?:logname|e?uid|tty)=\S*)){0,4}\s+ruser=<F-ALT_USER>\S*</F-ALT_USER>\s+rhost=<HOST>(?:\s+user=<F-USER>\S*</F-USER>)?%(__suff)s$
|
||||
^maximum authentication attempts exceeded for <F-USER>.*</F-USER> from <HOST>%(__on_port_opt)s(?: ssh\d*)?%(__suff)s$
|
||||
^maximum authentication attempts exceeded for (?:invalid user )?<F-USER>.*?</F-USER> (?:from )?<HOST>%(__on_port_opt)s(?: ssh\d*)?%(__suff)s$
|
||||
^User <F-USER>\S+|.*?</F-USER> not allowed because account is locked%(__suff)s
|
||||
^<F-MLFFORGET>Disconnecting</F-MLFFORGET>(?: from)?(?: (?:invalid|authenticating)) user <F-USER>\S+</F-USER> <HOST>%(__on_port_opt)s:\s*Change of username or service not allowed:\s*.*\[preauth\]\s*$
|
||||
^Disconnecting: Too many authentication failures(?: for <F-USER>\S+|.*?</F-USER>)?%(__suff)s$
|
||||
|
|
@ -68,24 +68,25 @@ cmnfailed = <cmnfailed-<publickey>>
|
|||
|
||||
mdre-normal =
|
||||
# used to differentiate "connection closed" with and without `[preauth]` (fail/nofail cases in ddos mode)
|
||||
mdre-normal-other = ^<F-NOFAIL><F-MLFFORGET>(Connection (?:closed|reset)|Disconnected)</F-MLFFORGET></F-NOFAIL> (?:by|from)%(__authng_user)s <HOST>(?:%(__suff)s|\s*)$
|
||||
mdre-normal-other = ^<F-NOFAIL><F-MLFFORGET>(?:Connection (?:closed|reset)|Disconnect(?:ed|ing))</F-MLFFORGET></F-NOFAIL>%(__authng_user)s <ADDR>%(__on_port_opt)s(?:: (?!Too many authentication failures)[^\[]+)?(?: \[preauth\])?\s*$
|
||||
|
||||
mdre-ddos = ^Did not receive identification string from <HOST>
|
||||
mdre-ddos = ^(?:Did not receive identification string from|Timeout before authentication for(?: connection from)?) <HOST>
|
||||
^kex_exchange_identification: (?:read: )?(?:[Cc]lient sent invalid protocol identifier|[Cc]onnection (?:closed by remote host|reset by peer))
|
||||
^Bad protocol version identification '.*' from <HOST>
|
||||
^Bad protocol version identification '(?:[^']|.*?)' (?:from )?<HOST>%(__suff)s$
|
||||
^<F-NOFAIL>SSH: Server;Ltype:</F-NOFAIL> (?:Authname|Version|Kex);Remote: <HOST>-\d+;[A-Z]\w+:
|
||||
^Read from socket failed: Connection <F-MLFFORGET>reset</F-MLFFORGET> by peer
|
||||
^banner exchange: Connection from <HOST><__on_port_opt>: invalid format
|
||||
^(?:banner exchange|ssh_dispatch_run_fatal): Connection from <HOST><__on_port_opt>: (?:invalid format|(?:message authentication code incorrect|[Cc]onnection corrupted) \[preauth\])
|
||||
|
||||
# same as mdre-normal-other, but as failure (without <F-NOFAIL> with [preauth] and with <F-NOFAIL> on no preauth phase as helper to identify address):
|
||||
mdre-ddos-other = ^<F-MLFFORGET>(Connection (?:closed|reset)|Disconnected)</F-MLFFORGET> (?:by|from)%(__authng_user)s <HOST>%(__on_port_opt)s\s+\[preauth\]\s*$
|
||||
^<F-NOFAIL><F-MLFFORGET>(Connection (?:closed|reset)|Disconnected)</F-MLFFORGET></F-NOFAIL> (?:by|from)%(__authng_user)s <HOST>(?:%(__on_port_opt)s|\s*)$
|
||||
mdre-ddos-other = ^<F-MLFFORGET>(?:Connection (?:closed|reset)|Disconnect(?:ed|ing))</F-MLFFORGET>%(__authng_user)s <ADDR>%(__on_port_opt)s(?:: (?!Too many authentication failures)[^\[]+)?\s+\[preauth\]\s*$
|
||||
^<F-NOFAIL><F-MLFFORGET>(?:Connection (?:closed|reset)|Disconnect(?:ed|ing))</F-MLFFORGET></F-NOFAIL>%(__authng_user)s <ADDR>(?:%(__on_port_opt)s(?:: (?!Too many authentication failures)[^\[]+)?|\s*)$
|
||||
|
||||
mdre-extra = ^Received <F-MLFFORGET>disconnect</F-MLFFORGET> from <HOST>%(__on_port_opt)s:\s*14: No(?: supported)? authentication methods available
|
||||
^Unable to negotiate with <HOST>%(__on_port_opt)s: no matching <__alg_match> found.
|
||||
^Unable to negotiate a <__alg_match>
|
||||
^no matching <__alg_match> found:
|
||||
# part of mdre-ddos-other, but user name is supplied (invalid/authenticating) on [preauth] phase only:
|
||||
mdre-extra-other = ^<F-MLFFORGET>Disconnected</F-MLFFORGET>(?: from)?(?: (?:invalid|authenticating)) user <F-USER>\S+|.*?</F-USER> <HOST>%(__on_port_opt)s \[preauth\]\s*$
|
||||
mdre-extra-other = ^<F-MLFFORGET>Disconnected</F-MLFFORGET>(?: from)?(?: (?:invalid|authenticating)) user <F-USER>\S+|.*?</F-USER> (?:from )?<HOST>%(__on_port_opt)s \[preauth\]\s*$
|
||||
|
||||
mdre-aggressive = %(mdre-ddos)s
|
||||
%(mdre-extra)s
|
||||
|
|
@ -125,7 +126,7 @@ ignoreregex =
|
|||
|
||||
maxlines = 1
|
||||
|
||||
journalmatch = _SYSTEMD_UNIT=sshd.service + _COMM=sshd
|
||||
journalmatch = _SYSTEMD_UNIT=sshd.service + _COMM=sshd + _COMM=sshd-session
|
||||
|
||||
# DEV Notes:
|
||||
#
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
#
|
||||
# To use 'traefik-auth' filter you have to configure your Traefik instance to write
|
||||
# the access logs as describe in https://docs.traefik.io/configuration/logs/#access-logs
|
||||
# into a log file on host and specifiy users for Basic Authentication
|
||||
# into a log file on host and specify users for Basic Authentication
|
||||
# https://docs.traefik.io/configuration/entrypoints/#basic-authentication
|
||||
#
|
||||
# Example:
|
||||
|
|
@ -51,7 +51,7 @@
|
|||
|
||||
[Definition]
|
||||
|
||||
# Parameter "method" can be used to specifiy request method
|
||||
# Parameter "method" can be used to specify request method
|
||||
req-method = \S+
|
||||
# Usage example (for jail.local):
|
||||
# filter = traefik-auth[req-method="GET|POST|HEAD"]
|
||||
|
|
|
|||
8
config/filter.d/vaultwarden.conf
Normal file
8
config/filter.d/vaultwarden.conf
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
# Fail2Ban filter for unsuccessful Vaultwarden authentication attempts
|
||||
# Logged in /var/log/vaultwarden.log
|
||||
# Author: LearningSpot
|
||||
|
||||
[Definition]
|
||||
|
||||
failregex = ^\s*(?:\[\]\s*)?\[vaultwarden::api::(?:identity|admin|core::two_factor::authenticator)?\]\[ERROR\] (?:Invalid admin token|Invalid TOTP code|Username or password is incorrect)[\.!](?:\s+(?!IP:)\S+)* IP: <ADDR>(?:\. Username: <F-USER>\S+</F-USER>)?
|
||||
ignoreregex =
|
||||
|
|
@ -10,13 +10,13 @@ before = common.conf
|
|||
|
||||
[Definition]
|
||||
|
||||
__pam_re=\(?%(__pam_auth)s(?:\(\S+\))?\)?:?
|
||||
__pam_re=(?:\(?%(__pam_auth)s(?:\(\S+\))?\)?:?\s+)?
|
||||
_daemon = vsftpd
|
||||
|
||||
failregex = ^%(__prefix_line)s%(__pam_re)s\s+authentication failure; logname=\S* uid=\S* euid=\S* tty=(ftp)? ruser=\S* rhost=<HOST>(?:\s+user=.*)?\s*$
|
||||
^ \[pid \d+\] \[[^\]]+\] FAIL LOGIN: Client "<HOST>"(?:\s*$|,)
|
||||
failregex = ^%(__prefix_line)s%(__pam_re)sauthentication failure; logname=<F-ALT_USER1>\S*</F-ALT_USER1> uid=\S* euid=\S* tty=(?:ftp)? ruser=<F-USER>\S*</F-USER> rhost=<HOST>(?:\s+user=<F-ALT_USER>\S*</F-ALT_USER>)?\s*$
|
||||
^(?:\s*\[pid \d+\] |%(__prefix_line)s)\[<F-USER>[^\]]+</F-USER>\] FAIL LOGIN: Client "<HOST>"(?:\s*$|,)
|
||||
|
||||
ignoreregex =
|
||||
ignoreregex =
|
||||
|
||||
# Author: Cyril Jaquier
|
||||
# Authors: Cyril Jaquier, Lucian Maly <lmaly@redhat.com>
|
||||
# Documentation from fail2ban wiki
|
||||
|
|
|
|||
35
config/filter.d/xrdp.conf
Normal file
35
config/filter.d/xrdp.conf
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
#
|
||||
# Fail2Ban filter for XRDP
|
||||
#
|
||||
# Detects login attempts with invalid credentials
|
||||
#
|
||||
# Requirements:
|
||||
# - xrdp >= 0.9.19
|
||||
# - The log level in sesman.ini should be set to `INFO` or higher
|
||||
# to emit the log messages needed for this filter.
|
||||
#
|
||||
# Author: Evan Linde
|
||||
#
|
||||
|
||||
[INCLUDES]
|
||||
|
||||
# Read common prefixes. If any customizations available -- read them from
|
||||
# common.local
|
||||
before = common.conf
|
||||
|
||||
|
||||
[DEFAULT]
|
||||
|
||||
_daemon = xrdp-sesman
|
||||
|
||||
|
||||
[Definition]
|
||||
|
||||
authfail_re = \[INFO \] AUTHFAIL: user=<F-USER>(?:\S+|.+)</F-USER> ip=<ADDR> time=\d+
|
||||
|
||||
failregex = ^%(__prefix_line)s%(authfail_re)s$
|
||||
|
||||
ignoreregex =
|
||||
|
||||
datepattern = ^\[?%%ExY%%Exm%%Exd-%%ExH:%%ExM:%%ExS\]?
|
||||
^{DATE}
|
||||
|
|
@ -97,7 +97,9 @@ before = paths-debian.conf
|
|||
# ignorecommand = /path/to/command <ip>
|
||||
ignorecommand =
|
||||
|
||||
# "bantime" is the number of seconds that a host is banned.
|
||||
# "bantime" is the amount of time that a host is banned, integer in seconds or
|
||||
# time abbreviation format (m - minutes, h - hours, d - days, w - weeks, mo - months, y - years).
|
||||
# This is to consider as an initial time if bantime.increment gets enabled.
|
||||
bantime = 10m
|
||||
|
||||
# A host is banned if it has generated "maxretry" during the last "findtime"
|
||||
|
|
@ -111,19 +113,17 @@ maxretry = 5
|
|||
maxmatches = %(maxretry)s
|
||||
|
||||
# "backend" specifies the backend used to get files modification.
|
||||
# Available options are "pyinotify", "gamin", "polling", "systemd" and "auto".
|
||||
# Available options are "pyinotify", "polling", "systemd" and "auto".
|
||||
# This option can be overridden in each jail as well.
|
||||
#
|
||||
# pyinotify: requires pyinotify (a file alteration monitor) to be installed.
|
||||
# If pyinotify is not installed, Fail2ban will use auto.
|
||||
# gamin: requires Gamin (a file alteration monitor) to be installed.
|
||||
# If Gamin is not installed, Fail2ban will use auto.
|
||||
# polling: uses a polling algorithm which does not require external libraries.
|
||||
# systemd: uses systemd python library to access the systemd journal.
|
||||
# Specifying "logpath" is not valid for this backend.
|
||||
# See "journalmatch" in the jails associated filter config
|
||||
# auto: will try to use the following backends, in order:
|
||||
# pyinotify, gamin, polling.
|
||||
# pyinotify, polling.
|
||||
#
|
||||
# Note: if systemd backend is chosen as the default but you enable a jail
|
||||
# for which logs are present only in its own log files, specify some other
|
||||
|
|
@ -205,8 +205,8 @@ fail2ban_agent = Fail2Ban/%(fail2ban_version)s
|
|||
# iptables-multiport, shorewall, etc) It is used to define
|
||||
# action_* variables. Can be overridden globally or per
|
||||
# section within jail.local file
|
||||
banaction = iptables-multiport
|
||||
banaction_allports = iptables-allports
|
||||
#banaction = iptables-multiport
|
||||
#banaction_allports = iptables-allports
|
||||
|
||||
# The simplest action to take: ban only
|
||||
action_ = %(banaction)s[port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
|
||||
|
|
@ -227,14 +227,11 @@ action_mwl = %(action_)s
|
|||
action_xarf = %(action_)s
|
||||
xarf-login-attack[service=%(__name__)s, sender="%(sender)s", logpath="%(logpath)s", port="%(port)s"]
|
||||
|
||||
# ban & send a notification to one or more of the 50+ services supported by Apprise.
|
||||
# See https://github.com/caronc/apprise/wiki for details on what is supported.
|
||||
#
|
||||
# You may optionally over-ride the default configuration line (containing the Apprise URLs)
|
||||
# by using 'apprise[config="/alternate/path/to/apprise.cfg"]' otherwise
|
||||
# /etc/fail2ban/apprise.conf is sourced for your supported notification configuration.
|
||||
# ban & send a notification to one or more of the 120+ services supported by Apprise.
|
||||
# action = %(action_)s
|
||||
# apprise
|
||||
# apprise[config="/alternate/path/to/apprise.yaml", args='--tag fail2ban']
|
||||
# See https://appriseit.com/services/ for details on what is supported.
|
||||
# Or action.d/apprise.conf for more details how to configure or customize it.
|
||||
|
||||
# ban IP on CloudFlare & send an e-mail with whois report and relevant log lines
|
||||
# to the destemail.
|
||||
|
|
@ -395,6 +392,10 @@ logpath = %(nginx_error_log)s
|
|||
port = http,https
|
||||
logpath = %(nginx_access_log)s
|
||||
|
||||
[nginx-forbidden]
|
||||
port = http,https
|
||||
logpath = %(nginx_error_log)s
|
||||
|
||||
# Ban attackers that try to use PHP's URL-fopen() functionality
|
||||
# through GET/POST variables. - Experimental, with more than a year
|
||||
# of usage in production environments.
|
||||
|
|
@ -497,7 +498,7 @@ backend = %(syslog_backend)s
|
|||
[froxlor-auth]
|
||||
|
||||
port = http,https
|
||||
logpath = %(syslog_authpriv)s
|
||||
logpath = %(syslog_user)s
|
||||
backend = %(syslog_backend)s
|
||||
|
||||
|
||||
|
|
@ -781,17 +782,11 @@ logpath = /var/lib/znc/moddata/adminlog/znc.log
|
|||
|
||||
# To log wrong MySQL access attempts add to /etc/my.cnf in [mysqld] or
|
||||
# equivalent section:
|
||||
# log-warnings = 2
|
||||
#
|
||||
# for syslog (daemon facility)
|
||||
# [mysqld_safe]
|
||||
# syslog
|
||||
#
|
||||
# for own logfile
|
||||
# [mysqld]
|
||||
# log-error=/var/log/mysqld.log
|
||||
# log_error_verbosity = 3
|
||||
# for older versions:
|
||||
# log-warnings = 2
|
||||
# Also check whether `log_error` (or `log-error`) system variable match the `logpath`.
|
||||
[mysqld-auth]
|
||||
|
||||
port = 3306
|
||||
logpath = %(mysql_log)s
|
||||
backend = %(mysql_backend)s
|
||||
|
|
@ -958,6 +953,9 @@ port = http,https
|
|||
logpath = %(syslog_authpriv)s
|
||||
backend = %(syslog_backend)s
|
||||
|
||||
[routeros-auth]
|
||||
port = ssh,http,https
|
||||
logpath = /var/log/MikroTik/router.log
|
||||
|
||||
[zoneminder]
|
||||
# Zoneminder HTTP/HTTPS web interface auth
|
||||
|
|
@ -971,6 +969,10 @@ logpath = %(apache_error_log)s
|
|||
port = http,https
|
||||
logpath = /var/log/traefik/access.log
|
||||
|
||||
[openvpn]
|
||||
port = 443
|
||||
logpath = /var/log/syslog
|
||||
|
||||
[scanlogd]
|
||||
logpath = %(syslog_local0)s
|
||||
banaction = %(banaction_allports)s
|
||||
|
|
@ -978,3 +980,19 @@ banaction = %(banaction_allports)s
|
|||
[monitorix]
|
||||
port = 8080
|
||||
logpath = /var/log/monitorix-httpd
|
||||
|
||||
[dante]
|
||||
port = 1080
|
||||
logpath = %(syslog_daemon)s
|
||||
|
||||
[proxmox]
|
||||
port = https,http,8006
|
||||
logpath = /var/log/daemon.log
|
||||
|
||||
[vaultwarden]
|
||||
port = http,https
|
||||
logpath = /var/log/vaultwarden.log
|
||||
|
||||
[xrdp]
|
||||
port = 3389
|
||||
logpath = /var/log/xrdp-sesman.log
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ proftpd_backend = %(default_backend)s
|
|||
pureftpd_log = %(syslog_ftp)s
|
||||
pureftpd_backend = %(default_backend)s
|
||||
|
||||
# ftp, daemon and then local7 are tried at configure time however it is overwriteable at configure time
|
||||
# ftp, daemon and then local7 are tried at configure time however it is overwritable at configure time
|
||||
#
|
||||
wuftpd_log = %(syslog_ftp)s
|
||||
wuftpd_backend = %(default_backend)s
|
||||
|
|
@ -87,7 +87,12 @@ dovecot_backend = %(default_backend)s
|
|||
# Seems to be set at compile time only to LOG_LOCAL0 (src/const.h) at Notice level
|
||||
solidpop3d_log = %(syslog_local0)s
|
||||
|
||||
mysql_log = %(syslog_daemon)s
|
||||
mysql_log = /var/log/mariadb/mariadb.log
|
||||
/var/log/mariadb/error.log
|
||||
/var/log/mysql/mysqld.log
|
||||
/var/log/mysql/error.log
|
||||
/var/log/mysqld.log
|
||||
|
||||
mysql_backend = %(default_backend)s
|
||||
|
||||
roundcube_errors_log = /var/log/roundcube/errors
|
||||
|
|
|
|||
|
|
@ -9,6 +9,12 @@ after = paths-overrides.local
|
|||
|
||||
[DEFAULT]
|
||||
|
||||
banaction = nftables
|
||||
banaction_allports = nftables[type=allports]
|
||||
|
||||
sshd_backend = systemd
|
||||
postfix_backend = systemd
|
||||
|
||||
syslog_mail = /var/log/mail.log
|
||||
|
||||
# control the `mail.warn` setting, see `/etc/rsyslog.d/50-default.conf` (if commented `mail.*` wins).
|
||||
|
|
|
|||
|
|
@ -47,12 +47,9 @@ copyright = u'2014'
|
|||
#
|
||||
|
||||
from fail2ban.version import version as fail2ban_version
|
||||
from distutils.version import LooseVersion
|
||||
|
||||
fail2ban_loose_version = LooseVersion(fail2ban_version)
|
||||
|
||||
# The short X.Y version.
|
||||
version = ".".join(str(_) for _ in fail2ban_loose_version.version[:2])
|
||||
version = ".".join(str(_) for _ in fail2ban_version.split(".")[:2])
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = fail2ban_version
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +0,0 @@
|
|||
fail2ban.server.filtergamin module
|
||||
==================================
|
||||
|
||||
.. automodule:: fail2ban.server.filtergamin
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
|
@ -13,7 +13,6 @@ fail2ban.server package
|
|||
fail2ban.server.failmanager
|
||||
fail2ban.server.failregex
|
||||
fail2ban.server.filter
|
||||
fail2ban.server.filtergamin
|
||||
fail2ban.server.filterpoll
|
||||
fail2ban.server.filterpyinotify
|
||||
fail2ban.server.filtersystemd
|
||||
|
|
|
|||
|
|
@ -1,14 +0,0 @@
|
|||
#!/bin/bash
|
||||
# This script carries out conversion of fail2ban to python3
|
||||
# A backup of any converted files are created with ".bak"
|
||||
# extension
|
||||
|
||||
set -eu
|
||||
|
||||
if 2to3 -w --no-diffs bin/* fail2ban;then
|
||||
echo "Success!" >&2
|
||||
exit 0
|
||||
else
|
||||
echo "Fail!" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
|
@ -89,11 +89,11 @@ class ActionReader(DefinitionInitConfigReader):
|
|||
stream = list()
|
||||
stream.append(head + ["addaction", self._name])
|
||||
multi = []
|
||||
for opt, optval in opts.iteritems():
|
||||
for opt, optval in opts.items():
|
||||
if opt in self._configOpts and not opt.startswith('known/'):
|
||||
multi.append([opt, optval])
|
||||
if self._initOpts:
|
||||
for opt, optval in self._initOpts.iteritems():
|
||||
for opt, optval in self._initOpts.items():
|
||||
if opt not in self._configOpts and not opt.startswith('known/'):
|
||||
multi.append([opt, optval])
|
||||
if len(multi) > 1:
|
||||
|
|
|
|||
|
|
@ -21,8 +21,10 @@ __author__ = "Cyril Jaquier, Yaroslav Halchenko"
|
|||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2013- Yaroslav Halchenko"
|
||||
__license__ = "GPL"
|
||||
|
||||
import sys
|
||||
|
||||
from ..exceptions import UnknownJailException, DuplicateJailException
|
||||
from ..helpers import getLogger, logging
|
||||
from ..helpers import getLogger, logging, PREFER_ENC
|
||||
|
||||
# Gets the instance of the logger.
|
||||
logSys = getLogger(__name__)
|
||||
|
|
@ -36,6 +38,11 @@ logSys = getLogger(__name__)
|
|||
|
||||
class Beautifier:
|
||||
|
||||
stdoutEnc = PREFER_ENC
|
||||
if sys.stdout and sys.stdout.encoding is not None:
|
||||
stdoutEnc = sys.stdout.encoding
|
||||
encUtf = 1 if stdoutEnc.lower() == 'utf-8' else 0
|
||||
|
||||
def __init__(self, cmd = None):
|
||||
self.__inputCmd = cmd
|
||||
|
||||
|
|
@ -71,24 +78,84 @@ class Beautifier:
|
|||
elif inC[0] == "echo":
|
||||
msg = ' '.join(msg)
|
||||
elif inC[0:1] == ['status']:
|
||||
if len(inC) > 1:
|
||||
# Display information
|
||||
msg = ["Status for the jail: %s" % inC[1]]
|
||||
def jail_stat(response, pref=""):
|
||||
# Display jail information
|
||||
for n, res1 in enumerate(response):
|
||||
prefix1 = "`-" if n == len(response) - 1 else "|-"
|
||||
prefix1 = pref + ("`-" if n == len(response) - 1 else "|-")
|
||||
msg.append("%s %s" % (prefix1, res1[0]))
|
||||
prefix1 = " " if n == len(response) - 1 else "| "
|
||||
prefix1 = pref + (" " if n == len(response) - 1 else "| ")
|
||||
for m, res2 in enumerate(res1[1]):
|
||||
prefix2 = prefix1 + ("`-" if m == len(res1[1]) - 1 else "|-")
|
||||
val = " ".join(map(str, res2[1])) if isinstance(res2[1], list) else res2[1]
|
||||
msg.append("%s %s:\t%s" % (prefix2, res2[0], val))
|
||||
if len(inC) > 1 and inC[1] != "--all":
|
||||
msg = ["Status for the jail: %s" % inC[1]]
|
||||
jail_stat(response)
|
||||
else:
|
||||
jstat = None
|
||||
if len(inC) > 1: # --all
|
||||
jstat = response[-1]
|
||||
response = response[:-1]
|
||||
msg = ["Status"]
|
||||
for n, res1 in enumerate(response):
|
||||
prefix1 = "`-" if n == len(response) - 1 else "|-"
|
||||
prefix1 = "`-" if not jstat and n == len(response) - 1 else "|-"
|
||||
val = " ".join(map(str, res1[1])) if isinstance(res1[1], list) else res1[1]
|
||||
msg.append("%s %s:\t%s" % (prefix1, res1[0], val))
|
||||
if jstat:
|
||||
msg.append("`- Status for the jails:")
|
||||
i = 0
|
||||
for n, j in jstat.items():
|
||||
i += 1
|
||||
prefix1 = "`-" if i == len(jstat) else "|-"
|
||||
msg.append(" %s Jail: %s" % (prefix1, n))
|
||||
jail_stat(j, " " if i == len(jstat) else " | ")
|
||||
msg = "\n".join(msg)
|
||||
elif inC[0:1] == ['stats'] or inC[0:1] == ['statistics']:
|
||||
chrTable = [
|
||||
['|', '-', '|', 'x', 'x', '-', '|', '-'], ## ascii
|
||||
["\u2551", "\u2550", "\u255F", "\u256B", "\u256C", "\u2569", "\u2502", "\u2500"] ## utf-8
|
||||
];
|
||||
def _statstable(response, ct):
|
||||
tophead = ["Jail", "Backend", "Filter", "Actions"]
|
||||
headers = ["", "", "cur", "tot", "cur", "tot"]
|
||||
minlens = [8, 8, 3, 3, 3, 3]
|
||||
ralign = [0, 0, 1, 1, 1, 1]
|
||||
rows = [[n, r[0], *r[1], *r[2]] for n, r in response.items()]
|
||||
lens = []
|
||||
for i in range(len(rows[0])):
|
||||
col = (len(str(s[i])) for s in rows)
|
||||
lens.append(max(minlens[i], max(col)))
|
||||
rfmt = []
|
||||
hfmt = []
|
||||
for i in range(len(rows[0])):
|
||||
f = "%%%ds" if ralign[i] else "%%-%ds"
|
||||
rfmt.append(f % lens[i])
|
||||
hfmt.append(f % lens[i])
|
||||
rfmt = [rfmt[0], rfmt[1], "%s %s %s" % (rfmt[2], ct[6], rfmt[3]), "%s %s %s" % (rfmt[4], ct[6], rfmt[5])]
|
||||
hfmt = [hfmt[0], hfmt[1], "%s %s %s" % (hfmt[2], ct[6], hfmt[3]), "%s %s %s" % (hfmt[4], ct[6], hfmt[5])]
|
||||
tlens = [lens[0], lens[1], 3 + lens[2] + lens[3], 3 + lens[4] + lens[5]]
|
||||
tfmt = [hfmt[0], hfmt[1], "%%-%ds" % (tlens[2],), "%%-%ds" % (tlens[3],)]
|
||||
tsep = tfmt[0:2]
|
||||
rfmt = (" "+ct[0]+" ").join(rfmt)
|
||||
hfmt = (" "+ct[0]+" ").join(hfmt)
|
||||
tfmt = (" "+ct[0]+" ").join(tfmt)
|
||||
tsep = (" "+ct[0]+" ").join(tsep)
|
||||
separator = ((tsep % tuple(tophead[0:2])) + " "+ct[2]+ct[7] +
|
||||
((ct[7]+ct[3]+ct[7]).join([ct[7] * n for n in tlens[2:]])) + ct[7])
|
||||
ret = []
|
||||
ret.append(" "+tfmt % tuple(["", ""]+tophead[2:]))
|
||||
ret.append(" "+separator)
|
||||
ret.append(" "+hfmt % tuple(headers))
|
||||
separator = (ct[1]+ct[4]+ct[1]).join([ct[1] * n for n in tlens]) + ct[1]
|
||||
ret.append(ct[1]+separator)
|
||||
for row in rows:
|
||||
ret.append(" "+rfmt % tuple(row))
|
||||
separator = (ct[1]+ct[5]+ct[1]).join([ct[1] * n for n in tlens]) + ct[1]
|
||||
ret.append(ct[1]+separator)
|
||||
return ret
|
||||
if not response:
|
||||
return "No jails found."
|
||||
msg = "\n".join(_statstable(response, chrTable[self.encUtf]))
|
||||
elif len(inC) < 2:
|
||||
pass # to few cmd args for below
|
||||
elif inC[1] == "syslogsocket":
|
||||
|
|
@ -145,8 +212,8 @@ class Beautifier:
|
|||
else:
|
||||
msg = "These IP addresses/networks are ignored:\n"
|
||||
for ip in response[:-1]:
|
||||
msg += "|- " + ip + "\n"
|
||||
msg += "`- " + response[-1]
|
||||
msg += "|- " + str(ip) + "\n"
|
||||
msg += "`- " + str(response[-1])
|
||||
elif inC[2] in ("failregex", "addfailregex", "delfailregex",
|
||||
"ignoreregex", "addignoreregex", "delignoreregex"):
|
||||
if len(response) == 0:
|
||||
|
|
|
|||
|
|
@ -29,49 +29,36 @@ import re
|
|||
import sys
|
||||
from ..helpers import getLogger
|
||||
|
||||
if sys.version_info >= (3,): # pragma: 2.x no cover
|
||||
# SafeConfigParser deprecated from Python 3.2 (renamed to ConfigParser)
|
||||
from configparser import ConfigParser as SafeConfigParser, BasicInterpolation, \
|
||||
InterpolationMissingOptionError, NoOptionError, NoSectionError
|
||||
|
||||
# SafeConfigParser deprecated from Python 3.2 (renamed to ConfigParser)
|
||||
from configparser import ConfigParser as SafeConfigParser, BasicInterpolation, \
|
||||
InterpolationMissingOptionError, NoOptionError, NoSectionError
|
||||
# And interpolation of __name__ was simply removed, thus we need to
|
||||
# decorate default interpolator to handle it
|
||||
class BasicInterpolationWithName(BasicInterpolation):
|
||||
"""Decorator to bring __name__ interpolation back.
|
||||
|
||||
# And interpolation of __name__ was simply removed, thus we need to
|
||||
# decorate default interpolator to handle it
|
||||
class BasicInterpolationWithName(BasicInterpolation):
|
||||
"""Decorator to bring __name__ interpolation back.
|
||||
Original handling of __name__ was removed because of
|
||||
functional deficiencies: http://bugs.python.org/issue10489
|
||||
|
||||
Original handling of __name__ was removed because of
|
||||
functional deficiencies: http://bugs.python.org/issue10489
|
||||
commit v3.2a4-105-g61f2761
|
||||
Author: Lukasz Langa <lukasz@langa.pl>
|
||||
Date: Sun Nov 21 13:41:35 2010 +0000
|
||||
|
||||
commit v3.2a4-105-g61f2761
|
||||
Author: Lukasz Langa <lukasz@langa.pl>
|
||||
Date: Sun Nov 21 13:41:35 2010 +0000
|
||||
Issue #10489: removed broken `__name__` support from configparser
|
||||
|
||||
Issue #10489: removed broken `__name__` support from configparser
|
||||
But should be fine to reincarnate for our use case
|
||||
"""
|
||||
def _interpolate_some(self, parser, option, accum, rest, section, map,
|
||||
*args, **kwargs):
|
||||
if section and not (__name__ in map):
|
||||
map = map.copy() # just to be safe
|
||||
map['__name__'] = section
|
||||
# try to wrap section options like %(section/option)s:
|
||||
parser._map_section_options(section, option, rest, map)
|
||||
return super(BasicInterpolationWithName, self)._interpolate_some(
|
||||
parser, option, accum, rest, section, map, *args, **kwargs)
|
||||
|
||||
But should be fine to reincarnate for our use case
|
||||
"""
|
||||
def _interpolate_some(self, parser, option, accum, rest, section, map,
|
||||
*args, **kwargs):
|
||||
if section and not (__name__ in map):
|
||||
map = map.copy() # just to be safe
|
||||
map['__name__'] = section
|
||||
# try to wrap section options like %(section/option)s:
|
||||
parser._map_section_options(section, option, rest, map)
|
||||
return super(BasicInterpolationWithName, self)._interpolate_some(
|
||||
parser, option, accum, rest, section, map, *args, **kwargs)
|
||||
|
||||
else: # pragma: 3.x no cover
|
||||
from ConfigParser import SafeConfigParser, \
|
||||
InterpolationMissingOptionError, NoOptionError, NoSectionError
|
||||
|
||||
# Interpolate missing known/option as option from default section
|
||||
SafeConfigParser._cp_interpolate_some = SafeConfigParser._interpolate_some
|
||||
def _interpolate_some(self, option, accum, rest, section, map, *args, **kwargs):
|
||||
# try to wrap section options like %(section/option)s:
|
||||
self._map_section_options(section, option, rest, map)
|
||||
return self._cp_interpolate_some(option, accum, rest, section, map, *args, **kwargs)
|
||||
SafeConfigParser._interpolate_some = _interpolate_some
|
||||
|
||||
def _expandConfFilesWithLocal(filenames):
|
||||
"""Expands config files with local extension.
|
||||
|
|
@ -129,20 +116,14 @@ after = 1.conf
|
|||
|
||||
CONDITIONAL_RE = re.compile(r"^(\w+)(\?.+)$")
|
||||
|
||||
if sys.version_info >= (3,2):
|
||||
# overload constructor only for fancy new Python3's
|
||||
def __init__(self, share_config=None, *args, **kwargs):
|
||||
kwargs = kwargs.copy()
|
||||
kwargs['interpolation'] = BasicInterpolationWithName()
|
||||
kwargs['inline_comment_prefixes'] = ";"
|
||||
super(SafeConfigParserWithIncludes, self).__init__(
|
||||
*args, **kwargs)
|
||||
self._cfg_share = share_config
|
||||
|
||||
else:
|
||||
def __init__(self, share_config=None, *args, **kwargs):
|
||||
SafeConfigParser.__init__(self, *args, **kwargs)
|
||||
self._cfg_share = share_config
|
||||
# overload constructor only for fancy new Python3's
|
||||
def __init__(self, share_config=None, *args, **kwargs):
|
||||
kwargs = kwargs.copy()
|
||||
kwargs['interpolation'] = BasicInterpolationWithName()
|
||||
kwargs['inline_comment_prefixes'] = ";"
|
||||
super(SafeConfigParserWithIncludes, self).__init__(
|
||||
*args, **kwargs)
|
||||
self._cfg_share = share_config
|
||||
|
||||
def get_ex(self, section, option, raw=False, vars={}):
|
||||
"""Get an option value for a given section.
|
||||
|
|
@ -327,7 +308,7 @@ after = 1.conf
|
|||
# mix it with defaults:
|
||||
return set(opts.keys()) | set(self._defaults)
|
||||
# only own option names:
|
||||
return opts.keys()
|
||||
return list(opts.keys())
|
||||
|
||||
def read(self, filenames, get_includes=True):
|
||||
if not isinstance(filenames, list):
|
||||
|
|
@ -356,7 +337,7 @@ after = 1.conf
|
|||
ret += i
|
||||
# merge defaults and all sections to self:
|
||||
alld.update(cfg.get_defaults())
|
||||
for n, s in cfg.get_sections().iteritems():
|
||||
for n, s in cfg.get_sections().items():
|
||||
# conditional sections
|
||||
cond = SafeConfigParserWithIncludes.CONDITIONAL_RE.match(n)
|
||||
if cond:
|
||||
|
|
@ -366,14 +347,14 @@ after = 1.conf
|
|||
del(s['__name__'])
|
||||
except KeyError:
|
||||
pass
|
||||
for k in s.keys():
|
||||
for k in list(s.keys()):
|
||||
v = s.pop(k)
|
||||
s[k + cond] = v
|
||||
s2 = alls.get(n)
|
||||
if isinstance(s2, dict):
|
||||
# save previous known values, for possible using in local interpolations later:
|
||||
self.merge_section('KNOWN/'+n,
|
||||
dict(filter(lambda i: i[0] in s, s2.iteritems())), '')
|
||||
dict([i for i in iter(s2.items()) if i[0] in s]), '')
|
||||
# merge section
|
||||
s2.update(s)
|
||||
else:
|
||||
|
|
@ -385,10 +366,7 @@ after = 1.conf
|
|||
if logSys.getEffectiveLevel() <= logLevel:
|
||||
logSys.log(logLevel, " Reading file: %s", fileNamesFull[0])
|
||||
# read file(s) :
|
||||
if sys.version_info >= (3,2): # pragma: no cover
|
||||
return SafeConfigParser.read(self, fileNamesFull, encoding='utf-8')
|
||||
else:
|
||||
return SafeConfigParser.read(self, fileNamesFull)
|
||||
return SafeConfigParser.read(self, fileNamesFull, encoding='utf-8')
|
||||
|
||||
def merge_section(self, section, options, pref=None):
|
||||
alls = self.get_sections()
|
||||
|
|
@ -400,7 +378,7 @@ after = 1.conf
|
|||
sec.update(options)
|
||||
return
|
||||
sk = {}
|
||||
for k, v in options.iteritems():
|
||||
for k, v in options.items():
|
||||
if not k.startswith(pref) and k != '__name__':
|
||||
sk[pref+k] = v
|
||||
sec.update(sk)
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ __license__ = "GPL"
|
|||
|
||||
import glob
|
||||
import os
|
||||
from ConfigParser import NoOptionError, NoSectionError
|
||||
from configparser import NoOptionError, NoSectionError
|
||||
|
||||
from .configparserinc import sys, SafeConfigParserWithIncludes, logLevel
|
||||
from ..helpers import getLogger, _as_bool, _merge_dicts, substituteRecursiveTags
|
||||
|
|
@ -98,7 +98,7 @@ class ConfigReader():
|
|||
def read(self, name, once=True):
|
||||
""" Overloads a default (not shared) read of config reader.
|
||||
|
||||
To prevent mutiple reads of config files with it includes, reads into
|
||||
To prevent multiple reads of config files with it includes, reads into
|
||||
the config reader, if it was not yet cached/shared by 'name'.
|
||||
"""
|
||||
# already shared ?
|
||||
|
|
@ -183,7 +183,7 @@ class ConfigReader():
|
|||
class ConfigReaderUnshared(SafeConfigParserWithIncludes):
|
||||
"""Unshared config reader (previously ConfigReader).
|
||||
|
||||
Do not use this class (internal not shared/cached represenation).
|
||||
Do not use this class (internal not shared/cached representation).
|
||||
Use ConfigReader instead.
|
||||
"""
|
||||
|
||||
|
|
@ -221,7 +221,7 @@ class ConfigReaderUnshared(SafeConfigParserWithIncludes):
|
|||
config_files += sorted(glob.glob('%s/*.local' % config_dir))
|
||||
|
||||
# choose only existing ones
|
||||
config_files = filter(os.path.exists, config_files)
|
||||
config_files = list(filter(os.path.exists, config_files))
|
||||
|
||||
if len(config_files):
|
||||
# at least one config exists and accessible
|
||||
|
|
@ -230,6 +230,7 @@ class ConfigReaderUnshared(SafeConfigParserWithIncludes):
|
|||
missed = [ cf for cf in config_files if cf not in config_files_read ]
|
||||
if missed:
|
||||
logSys.error("Could not read config files: %s", ', '.join(missed))
|
||||
return False
|
||||
if config_files_read:
|
||||
return True
|
||||
logSys.error("Found no accessible config files for %r under %s",
|
||||
|
|
@ -277,7 +278,7 @@ class ConfigReaderUnshared(SafeConfigParserWithIncludes):
|
|||
# TODO: validate error handling here.
|
||||
except NoOptionError:
|
||||
if not optvalue is None:
|
||||
logSys.warning("'%s' not defined in '%s'. Using default one: %r"
|
||||
logSys.debug("'%s' not defined in '%s'. Using default one: %r"
|
||||
% (optname, sec, optvalue))
|
||||
values[optname] = optvalue
|
||||
# elif logSys.getEffectiveLevel() <= logLevel:
|
||||
|
|
@ -353,6 +354,11 @@ class DefinitionInitConfigReader(ConfigReader):
|
|||
if v is None: v = getopt(opt)
|
||||
self._initOpts['known/'+opt] = v
|
||||
if opt not in self._initOpts:
|
||||
# overwrite also conditional init options (from init?... section):
|
||||
cond = SafeConfigParserWithIncludes.CONDITIONAL_RE.match(opt)
|
||||
if cond:
|
||||
optc, cond = cond.groups()
|
||||
v = pOpts.get(optc, v)
|
||||
if v is None: v = getopt(opt)
|
||||
self._initOpts[opt] = v
|
||||
if all and self.has_section("Definition"):
|
||||
|
|
@ -406,7 +412,7 @@ class DefinitionInitConfigReader(ConfigReader):
|
|||
if cond:
|
||||
n, cond = cond.groups()
|
||||
ignore.add(n)
|
||||
# substiture options already specified direct:
|
||||
# substitute options already specified direct:
|
||||
opts = substituteRecursiveTags(combinedopts,
|
||||
ignore=ignore, addrepl=self.getCombOption)
|
||||
if not opts:
|
||||
|
|
|
|||
|
|
@ -63,11 +63,13 @@ class Configurator:
|
|||
return fail2ban_basedir
|
||||
|
||||
def readEarly(self):
|
||||
self.__fail2ban.read()
|
||||
if not self.__fail2ban.read():
|
||||
raise LookupError("Read fail2ban configuration failed.")
|
||||
|
||||
def readAll(self):
|
||||
self.readEarly()
|
||||
self.__jails.read()
|
||||
if not self.__jails.read():
|
||||
raise LookupError("Read jails configuration failed.")
|
||||
|
||||
def getEarlyOptions(self):
|
||||
return self.__fail2ban.getEarlyOptions()
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ class CSocket:
|
|||
|
||||
def send(self, msg, nonblocking=False, timeout=None):
|
||||
# Convert every list member to string
|
||||
obj = dumps(map(CSocket.convert, msg), HIGHEST_PROTOCOL)
|
||||
obj = dumps(list(map(CSocket.convert, msg)), HIGHEST_PROTOCOL)
|
||||
self.__csock.send(obj)
|
||||
self.__csock.send(CSPROTO.END)
|
||||
return self.receive(self.__csock, nonblocking, timeout)
|
||||
|
|
@ -72,7 +72,7 @@ class CSocket:
|
|||
@staticmethod
|
||||
def convert(m):
|
||||
"""Convert every "unexpected" member of message to string"""
|
||||
if isinstance(m, (basestring, bool, int, float, list, dict, set)):
|
||||
if isinstance(m, (str, bool, int, float, list, dict, set)):
|
||||
return m
|
||||
else: # pragma: no cover
|
||||
return str(m)
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ def _thread_name():
|
|||
return threading.current_thread().__class__.__name__
|
||||
|
||||
def input_command(): # pragma: no cover
|
||||
return raw_input(PROMPT)
|
||||
return input(PROMPT)
|
||||
|
||||
##
|
||||
#
|
||||
|
|
@ -406,6 +406,8 @@ class Fail2banClient(Fail2banCmdLine, Thread):
|
|||
if ret is not None:
|
||||
if ret:
|
||||
return True
|
||||
if self._conf.get("test", False) and not self._args: # test only
|
||||
return False
|
||||
raise ServerExecutionException("Init of command line failed")
|
||||
|
||||
# Commands
|
||||
|
|
@ -456,7 +458,7 @@ class Fail2banClient(Fail2banCmdLine, Thread):
|
|||
return False
|
||||
finally:
|
||||
self._alive = False
|
||||
for s, sh in _prev_signals.iteritems():
|
||||
for s, sh in _prev_signals.items():
|
||||
signal.signal(s, sh)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ import sys
|
|||
|
||||
from ..version import version, normVersion
|
||||
from ..protocol import printFormatted
|
||||
from ..helpers import getLogger, str2LogLevel, getVerbosityFormat, BrokenPipeError
|
||||
from ..helpers import getLogger, str2LogLevel, getVerbosityFormat
|
||||
|
||||
# Gets the instance of the logger.
|
||||
logSys = getLogger("fail2ban")
|
||||
|
|
@ -260,12 +260,15 @@ class Fail2banCmdLine():
|
|||
if readcfg:
|
||||
readcfg = False
|
||||
ret, stream = self.readConfig()
|
||||
if not ret:
|
||||
raise ServerExecutionException("ERROR: test configuration failed")
|
||||
# exit after test if no commands specified (test only):
|
||||
if not len(self._args):
|
||||
output("OK: configuration test is successful")
|
||||
if ret:
|
||||
output("OK: configuration test is successful")
|
||||
else:
|
||||
output("ERROR: test configuration failed")
|
||||
return ret
|
||||
if not ret:
|
||||
raise ServerExecutionException("ERROR: test configuration failed")
|
||||
|
||||
# Nothing to do here, process in client/server
|
||||
return None
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ class Fail2banReader(ConfigReader):
|
|||
ConfigReader.__init__(self, **kwargs)
|
||||
|
||||
def read(self):
|
||||
ConfigReader.read(self, "fail2ban")
|
||||
return ConfigReader.read(self, "fail2ban")
|
||||
|
||||
def getEarlyOptions(self):
|
||||
opts = [
|
||||
|
|
|
|||
|
|
@ -40,10 +40,10 @@ import os
|
|||
import shlex
|
||||
import sys
|
||||
import time
|
||||
import urllib
|
||||
import urllib.request, urllib.parse, urllib.error
|
||||
from optparse import OptionParser, Option
|
||||
|
||||
from ConfigParser import NoOptionError, NoSectionError, MissingSectionHeaderError
|
||||
from configparser import NoOptionError, NoSectionError, MissingSectionHeaderError
|
||||
|
||||
try: # pragma: no cover
|
||||
from ..server.filtersystemd import FilterSystemd
|
||||
|
|
@ -51,7 +51,7 @@ except ImportError:
|
|||
FilterSystemd = None
|
||||
|
||||
from ..version import version, normVersion
|
||||
from .filterreader import FilterReader
|
||||
from .jailreader import FilterReader, JailReader, NoJailError
|
||||
from ..server.filter import Filter, FileContainer, MyTime
|
||||
from ..server.failregex import Regex, RegexException
|
||||
|
||||
|
|
@ -67,9 +67,9 @@ def debuggexURL(sample, regex, multiline=False, useDns="yes"):
|
|||
'flavor': 'python'
|
||||
}
|
||||
if multiline: args['flags'] = 'm'
|
||||
return 'https://www.debuggex.com/?' + urllib.urlencode(args)
|
||||
return 'https://www.debuggex.com/?' + urllib.parse.urlencode(args)
|
||||
|
||||
def output(args): # pragma: no cover (overriden in test-cases)
|
||||
def output(args): # pragma: no cover (overridden in test-cases)
|
||||
print(args)
|
||||
|
||||
def shortstr(s, l=53):
|
||||
|
|
@ -106,7 +106,7 @@ usage = lambda: "%s [OPTIONS] <LOG> <REGEX> [IGNOREREGEX]" % sys.argv[0]
|
|||
|
||||
class _f2bOptParser(OptionParser):
|
||||
def format_help(self, *args, **kwargs):
|
||||
""" Overwritten format helper with full ussage."""
|
||||
""" Overwritten format helper with full usage."""
|
||||
self.usage = ''
|
||||
return "Usage: " + usage() + "\n" + __doc__ + """
|
||||
LOG:
|
||||
|
|
@ -118,12 +118,11 @@ LOG:
|
|||
|
||||
REGEX:
|
||||
string a string representing a 'failregex'
|
||||
filter name of filter, optionally with options (sshd[mode=aggressive])
|
||||
filter name of jail or filter, optionally with options (sshd[mode=aggressive])
|
||||
filename path to a filter file (filter.d/sshd.conf)
|
||||
|
||||
IGNOREREGEX:
|
||||
string a string representing an 'ignoreregex'
|
||||
filename path to a filter file (filter.d/sshd.conf)
|
||||
\n""" + OptionParser.format_help(self, *args, **kwargs) + """\n
|
||||
Report bugs to https://github.com/fail2ban/fail2ban/issues\n
|
||||
""" + __copyright__ + "\n"
|
||||
|
|
@ -173,6 +172,8 @@ def get_opt_parser():
|
|||
help="Disable check for all regex's"),
|
||||
Option("-o", "--out", action="store", dest="out", default=None,
|
||||
help="Set token to print failure information only (row, id, ip, msg, host, ip4, ip6, dns, matches, ...)"),
|
||||
Option("-i", "--invert", action="store_true", dest="invert",
|
||||
help="Invert the sense of matching, to output non-matching lines."),
|
||||
Option("--print-no-missed", action='store_true',
|
||||
help="Do not print any missed lines"),
|
||||
Option("--print-no-ignored", action='store_true',
|
||||
|
|
@ -246,7 +247,7 @@ class Fail2banRegex(object):
|
|||
|
||||
def __init__(self, opts):
|
||||
# set local protected members from given options:
|
||||
self.__dict__.update(dict(('_'+o,v) for o,v in opts.__dict__.iteritems()))
|
||||
self.__dict__.update(dict(('_'+o,v) for o,v in opts.__dict__.items()))
|
||||
self._opts = opts
|
||||
self._maxlines_set = False # so we allow to override maxlines in cmdline
|
||||
self._datepattern_set = False
|
||||
|
|
@ -280,7 +281,7 @@ class Fail2banRegex(object):
|
|||
self._filter.setUseDns(opts.usedns)
|
||||
self._filter.returnRawHost = opts.raw
|
||||
self._filter.checkAllRegex = opts.checkAllRegex and not opts.out
|
||||
# ignore pending (without ID/IP), added to matches if it hits later (if ID/IP can be retreved)
|
||||
# ignore pending (without ID/IP), added to matches if it hits later (if ID/IP can be retrieved)
|
||||
self._filter.ignorePending = bool(opts.out)
|
||||
# callback to increment ignored RE's by index (during process):
|
||||
self._filter.onIgnoreRegex = self._onIgnoreRegex
|
||||
|
|
@ -312,12 +313,18 @@ class Fail2banRegex(object):
|
|||
def _dumpRealOptions(self, reader, fltOpt):
|
||||
realopts = {}
|
||||
combopts = reader.getCombined()
|
||||
if isinstance(reader, FilterReader):
|
||||
_get_opt = lambda k: reader.get('Definition', k)
|
||||
elif reader.filter: # JailReader for jail with filter:
|
||||
_get_opt = lambda k: reader.filter.get('Definition', k)
|
||||
else: # JailReader for jail without filter:
|
||||
_get_opt = lambda k: None
|
||||
# output all options that are specified in filter-argument as well as some special (mostly interested):
|
||||
for k in ['logtype', 'datepattern'] + fltOpt.keys():
|
||||
for k in ['logtype', 'datepattern'] + list(fltOpt.keys()):
|
||||
# combined options win, but they contain only a sub-set in filter expected keys,
|
||||
# so get the rest from definition section:
|
||||
try:
|
||||
realopts[k] = combopts[k] if k in combopts else reader.get('Definition', k)
|
||||
realopts[k] = combopts[k] if k in combopts else _get_opt(k)
|
||||
except NoOptionError: # pragma: no cover
|
||||
pass
|
||||
self.output("Real filter options : %r" % realopts)
|
||||
|
|
@ -330,16 +337,26 @@ class Fail2banRegex(object):
|
|||
fltName = value
|
||||
fltFile = None
|
||||
fltOpt = {}
|
||||
jail = None
|
||||
if regextype == 'fail':
|
||||
if re.search(r'(?ms)^/{0,3}[\w/_\-.]+(?:\[.*\])?$', value):
|
||||
try:
|
||||
fltName, fltOpt = extractOptions(value)
|
||||
if not re.search(r'(?ms)(?:/|\.(?:conf|local)$)', fltName): # name of jail?
|
||||
try:
|
||||
jail = JailReader(fltName, force_enable=True,
|
||||
share_config=self.share_config, basedir=basedir)
|
||||
jail.read()
|
||||
except NoJailError:
|
||||
jail = None
|
||||
if "." in fltName[~5:]:
|
||||
tryNames = (fltName,)
|
||||
else:
|
||||
tryNames = (fltName, fltName + '.conf', fltName + '.local')
|
||||
for fltFile in tryNames:
|
||||
if not "/" in fltFile:
|
||||
if os.path.dirname(fltFile) == 'filter.d':
|
||||
fltFile = os.path.join(basedir, fltFile)
|
||||
elif not "/" in fltFile:
|
||||
if os.path.basename(basedir) == 'filter.d':
|
||||
fltFile = os.path.join(basedir, fltFile)
|
||||
else:
|
||||
|
|
@ -354,8 +371,28 @@ class Fail2banRegex(object):
|
|||
output(" while parsing: %s" % (value,))
|
||||
if self._verbose: raise(e)
|
||||
return False
|
||||
elif self._ignoreregex:
|
||||
# clear ignoreregex that could be previously loaded from filter:
|
||||
self._filter.delIgnoreRegex()
|
||||
|
||||
readercommands = None
|
||||
# if it is jail:
|
||||
if jail:
|
||||
self.output( "Use %11s jail : %s" % ('', fltName) )
|
||||
if fltOpt:
|
||||
self.output( "Use jail/flt options : %r" % fltOpt )
|
||||
if not fltOpt: fltOpt = {}
|
||||
fltOpt['backend'] = self._backend
|
||||
ret = jail.getOptions(addOpts=fltOpt)
|
||||
if not ret:
|
||||
output('ERROR: Failed to get jail for %r' % (value,))
|
||||
return False
|
||||
# show real options if expected:
|
||||
if self._verbose > 1 or logSys.getEffectiveLevel()<=logging.DEBUG:
|
||||
self._dumpRealOptions(jail, fltOpt)
|
||||
readercommands = jail.convert(allow_no_files=True)
|
||||
# if it is filter file:
|
||||
if fltFile is not None:
|
||||
elif fltFile is not None:
|
||||
if (basedir == self._opts.config
|
||||
or os.path.basename(basedir) == 'filter.d'
|
||||
or ("." not in fltName[~5:] and "/" not in fltName)
|
||||
|
|
@ -364,16 +401,17 @@ class Fail2banRegex(object):
|
|||
if os.path.basename(basedir) == 'filter.d':
|
||||
basedir = os.path.dirname(basedir)
|
||||
fltName = os.path.splitext(os.path.basename(fltName))[0]
|
||||
self.output( "Use %11s filter file : %s, basedir: %s" % (regex, fltName, basedir) )
|
||||
self.output( "Use %11s file : %s, basedir: %s" % ('filter', fltName, basedir) )
|
||||
else:
|
||||
## foreign file - readexplicit this file and includes if possible:
|
||||
self.output( "Use %11s file : %s" % (regex, fltName) )
|
||||
self.output( "Use %11s file : %s" % ('filter', fltName) )
|
||||
basedir = None
|
||||
if not os.path.isabs(fltName): # avoid join with "filter.d" inside FilterReader
|
||||
fltName = os.path.abspath(fltName)
|
||||
if fltOpt:
|
||||
self.output( "Use filter options : %r" % fltOpt )
|
||||
reader = FilterReader(fltName, 'fail2ban-regex-jail', fltOpt, share_config=self.share_config, basedir=basedir)
|
||||
reader = FilterReader(fltName, 'fail2ban-regex-jail', fltOpt,
|
||||
share_config=self.share_config, basedir=basedir)
|
||||
ret = None
|
||||
try:
|
||||
if basedir is not None:
|
||||
|
|
@ -398,7 +436,8 @@ class Fail2banRegex(object):
|
|||
# to stream:
|
||||
readercommands = reader.convert()
|
||||
|
||||
regex_values = {}
|
||||
regex_values = {}
|
||||
if readercommands:
|
||||
for opt in readercommands:
|
||||
if opt[0] == 'multi-set':
|
||||
optval = opt[3]
|
||||
|
|
@ -438,9 +477,9 @@ class Fail2banRegex(object):
|
|||
|
||||
else:
|
||||
self.output( "Use %11s line : %s" % (regex, shortstr(value)) )
|
||||
regex_values = {regextype: [RegexStat(value)]}
|
||||
regex_values[regextype] = [RegexStat(value)]
|
||||
|
||||
for regextype, regex_values in regex_values.iteritems():
|
||||
for regextype, regex_values in regex_values.items():
|
||||
regex = regextype + 'regex'
|
||||
setattr(self, "_" + regex, regex_values)
|
||||
for regex in regex_values:
|
||||
|
|
@ -476,7 +515,7 @@ class Fail2banRegex(object):
|
|||
ret.append(match)
|
||||
else:
|
||||
is_ignored = True
|
||||
if self._opts.out: # (formated) output - don't need stats:
|
||||
if self._opts.out: # (formatted) output - don't need stats:
|
||||
return None, ret, None
|
||||
# prefregex stats:
|
||||
if self._filter.prefRegex:
|
||||
|
|
@ -492,7 +531,7 @@ class Fail2banRegex(object):
|
|||
except RegexException as e: # pragma: no cover
|
||||
output( 'ERROR: %s' % e )
|
||||
return None, 0, None
|
||||
if self._filter.getMaxLines() > 1:
|
||||
if self._filter.getMaxLines() > 1 and not self._opts.out:
|
||||
for bufLine in orgLineBuffer[int(fullBuffer):]:
|
||||
if bufLine not in self._filter._Filter__lineBuffer:
|
||||
try:
|
||||
|
|
@ -532,13 +571,13 @@ class Fail2banRegex(object):
|
|||
def _out(ret):
|
||||
for r in ret:
|
||||
for r in r[3].get('matches'):
|
||||
if not isinstance(r, basestring):
|
||||
if not isinstance(r, str):
|
||||
r = ''.join(r for r in r)
|
||||
output(r)
|
||||
elif ofmt == 'row':
|
||||
def _out(ret):
|
||||
for r in ret:
|
||||
output('[%r,\t%r,\t%r],' % (r[1],r[2],dict((k,v) for k, v in r[3].iteritems() if k != 'matches')))
|
||||
output('[%r,\t%r,\t%r],' % (r[1],r[2],dict((k,v) for k, v in r[3].items() if k != 'matches')))
|
||||
elif '<' not in ofmt:
|
||||
def _out(ret):
|
||||
for r in ret:
|
||||
|
|
@ -573,7 +612,7 @@ class Fail2banRegex(object):
|
|||
# wrap multiline tag (msg) interpolations to single line:
|
||||
for r, v in rows:
|
||||
for r in r[3].get('matches'):
|
||||
if not isinstance(r, basestring):
|
||||
if not isinstance(r, str):
|
||||
r = ''.join(r for r in r)
|
||||
r = v.replace("\x00msg\x00", r)
|
||||
output(r)
|
||||
|
|
@ -582,8 +621,10 @@ class Fail2banRegex(object):
|
|||
|
||||
def process(self, test_lines):
|
||||
t0 = time.time()
|
||||
out = None
|
||||
if self._opts.out: # get out function
|
||||
out = self._prepaireOutput()
|
||||
outinv = self._opts.invert
|
||||
for line in test_lines:
|
||||
if isinstance(line, tuple):
|
||||
line_datetimestripped, ret, is_ignored = self.testRegex(line[0], line[1])
|
||||
|
|
@ -595,8 +636,13 @@ class Fail2banRegex(object):
|
|||
continue
|
||||
line_datetimestripped, ret, is_ignored = self.testRegex(line)
|
||||
|
||||
if self._opts.out: # (formated) output:
|
||||
if len(ret) > 0 and not is_ignored: out(ret)
|
||||
if out: # (formatted) output:
|
||||
if len(ret) > 0 and not is_ignored:
|
||||
if not outinv: out(ret)
|
||||
elif outinv: # inverted output (currently only time and message as matches):
|
||||
if not len(ret): # [failRegexIndex, fid, date, fail]
|
||||
ret = [[-1, "", self._filter._Filter__lastDate, {"fid":"", "matches":[line]}]]
|
||||
out(ret)
|
||||
continue
|
||||
|
||||
if is_ignored:
|
||||
|
|
@ -639,9 +685,9 @@ class Fail2banRegex(object):
|
|||
ans = [[]]
|
||||
for arg in [l, regexlist]:
|
||||
ans = [ x + [y] for x in ans for y in arg ]
|
||||
b = map(lambda a: a[0] + ' | ' + a[1].getFailRegex() + ' | ' +
|
||||
b = [a[0] + ' | ' + a[1].getFailRegex() + ' | ' +
|
||||
debuggexURL(self.encode_line(a[0]), a[1].getFailRegex(),
|
||||
multiline, self._opts.usedns), ans)
|
||||
multiline, self._opts.usedns) for a in ans]
|
||||
pprint_list([x.rstrip() for x in b], header)
|
||||
else:
|
||||
output( "%s too many to print. Use --print-all-%s " \
|
||||
|
|
@ -789,7 +835,15 @@ class Fail2banRegex(object):
|
|||
return True
|
||||
|
||||
|
||||
def _loc_except_hook(exctype, value, traceback):
|
||||
if (exctype != BrokenPipeError and exctype != IOError or value.errno != 32):
|
||||
return sys.__excepthook__(exctype, value, traceback)
|
||||
# pipe seems to be closed (head / tail / etc), thus simply exit:
|
||||
sys.exit(0)
|
||||
|
||||
def exec_command_line(*args):
|
||||
sys.excepthook = _loc_except_hook; # stop on closed/broken pipe
|
||||
|
||||
logging.exitOnIOError = True
|
||||
parser = get_opt_parser()
|
||||
(opts, args) = parser.parse_args(*args)
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ class Fail2banServer(Fail2banCmdLine):
|
|||
|
||||
@staticmethod
|
||||
def startServerDirect(conf, daemon=True, setServer=None):
|
||||
logSys.debug(" direct starting of server in %s, deamon: %s", os.getpid(), daemon)
|
||||
logSys.debug(" direct starting of server in %s, daemon: %s", os.getpid(), daemon)
|
||||
from ..server.server import Server
|
||||
server = None
|
||||
try:
|
||||
|
|
@ -120,7 +120,7 @@ class Fail2banServer(Fail2banCmdLine):
|
|||
if frk: # pragma: no cover
|
||||
os.execv(exe, args)
|
||||
else:
|
||||
# use P_WAIT instead of P_NOWAIT (to prevent defunct-zomby process), it startet as daemon, so parent exit fast after fork):
|
||||
# use P_WAIT instead of P_NOWAIT (to prevent defunct-zomby process), it started as daemon, so parent exit fast after fork):
|
||||
ret = os.spawnv(os.P_WAIT, exe, args)
|
||||
if ret != 0: # pragma: no cover
|
||||
raise OSError(ret, "Unknown error by executing server %r with %r" % (args[1], exe))
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ class FilterReader(DefinitionInitConfigReader):
|
|||
@staticmethod
|
||||
def _fillStream(stream, opts, jailName):
|
||||
prio0idx = 0
|
||||
for opt, value in opts.iteritems():
|
||||
for opt, value in opts.items():
|
||||
# Do not send a command if the value is not set (empty).
|
||||
if value is None: continue
|
||||
if opt in ("failregex", "ignoreregex"):
|
||||
|
|
@ -89,7 +89,7 @@ class FilterReader(DefinitionInitConfigReader):
|
|||
stream.insert(0 if opt == 'usedns' else prio0idx,
|
||||
["set", jailName, opt, value])
|
||||
prio0idx += 1
|
||||
elif opt in ('datepattern'):
|
||||
elif opt == 'datepattern':
|
||||
stream.append(["set", jailName, opt, value])
|
||||
elif opt == 'journalmatch':
|
||||
for match in value.split("\n"):
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue