update: release version 1.1.0
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing

This commit is contained in:
Paul 2023-01-07 15:53:33 +01:00
commit b4664ba797
15 changed files with 693 additions and 520 deletions

1
.gitignore vendored
View File

@ -1,5 +1,6 @@
*.json *.json
*.swp *.swp
/*diff*
/*.gz /*.gz
/perf* /perf*
/sample /sample

374
Cargo.lock generated
View File

@ -4,9 +4,9 @@ version = 3
[[package]] [[package]]
name = "aho-corasick" name = "aho-corasick"
version = "0.7.18" version = "0.7.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e"
dependencies = [ dependencies = [
"memchr", "memchr",
] ]
@ -20,17 +20,6 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi",
]
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.1.0" version = "1.1.0"
@ -103,28 +92,36 @@ dependencies = [
[[package]] [[package]]
name = "clap" name = "clap"
version = "3.2.19" version = "4.0.32"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68d43934757334b5c0519ff882e1ab9647ac0258b47c24c4f490d78e42697fd5" checksum = "a7db700bc935f9e43e88d00b0850dae18a63773cfbec6d8e070fccf7fef89a39"
dependencies = [ dependencies = [
"atty",
"bitflags", "bitflags",
"clap_lex", "clap_lex",
"indexmap", "is-terminal",
"strsim", "strsim",
"termcolor", "termcolor",
"textwrap",
] ]
[[package]] [[package]]
name = "clap_lex" name = "clap_lex"
version = "0.2.4" version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8"
dependencies = [ dependencies = [
"os_str_bytes", "os_str_bytes",
] ]
[[package]]
name = "codespan-reporting"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e"
dependencies = [
"termcolor",
"unicode-width",
]
[[package]] [[package]]
name = "core-foundation-sys" name = "core-foundation-sys"
version = "0.8.3" version = "0.8.3"
@ -198,6 +195,50 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "cxx"
version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19f39818dcfc97d45b03953c1292efc4e80954e1583c4aa770bac1383e2310a4"
dependencies = [
"cc",
"cxxbridge-flags",
"cxxbridge-macro",
"link-cplusplus",
]
[[package]]
name = "cxx-build"
version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e580d70777c116df50c390d1211993f62d40302881e54d4b79727acb83d0199"
dependencies = [
"cc",
"codespan-reporting",
"once_cell",
"proc-macro2",
"quote",
"scratch",
"syn",
]
[[package]]
name = "cxxbridge-flags"
version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56a46460b88d1cec95112c8c363f0e2c39afdb237f60583b0b36343bf627ea9c"
[[package]]
name = "cxxbridge-macro"
version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "747b608fecf06b0d72d440f27acc99288207324b793be2c17991839f3d4995ea"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "dircpy" name = "dircpy"
version = "0.3.13" version = "0.3.13"
@ -238,6 +279,27 @@ dependencies = [
"synstructure", "synstructure",
] ]
[[package]]
name = "errno"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1"
dependencies = [
"errno-dragonfly",
"libc",
"winapi",
]
[[package]]
name = "errno-dragonfly"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
dependencies = [
"cc",
"libc",
]
[[package]] [[package]]
name = "fnv" name = "fnv"
version = "1.0.7" version = "1.0.7"
@ -246,11 +308,10 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]] [[package]]
name = "form_urlencoded" name = "form_urlencoded"
version = "1.0.1" version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8"
dependencies = [ dependencies = [
"matches",
"percent-encoding", "percent-encoding",
] ]
@ -293,6 +354,28 @@ dependencies = [
"pin-utils", "pin-utils",
] ]
[[package]]
name = "git-version"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6b0decc02f4636b9ccad390dcbe77b722a77efedfa393caf8379a51d5c61899"
dependencies = [
"git-version-macro",
"proc-macro-hack",
]
[[package]]
name = "git-version-macro"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe69f1cbdb6e28af2bac214e943b99ce8a0a06b447d15d3e61161b0423139f3f"
dependencies = [
"proc-macro-hack",
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "h2" name = "h2"
version = "0.3.14" version = "0.3.14"
@ -333,6 +416,15 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "hermit-abi"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "http" name = "http"
version = "0.2.8" version = "0.2.8"
@ -357,9 +449,9 @@ dependencies = [
[[package]] [[package]]
name = "httparse" name = "httparse"
version = "1.7.1" version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c" checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
[[package]] [[package]]
name = "httpdate" name = "httpdate"
@ -406,25 +498,34 @@ dependencies = [
[[package]] [[package]]
name = "iana-time-zone" name = "iana-time-zone"
version = "0.1.47" version = "0.1.51"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c495f162af0bf17656d0014a0eded5f3cd2f365fdd204548c2869db89359dc7" checksum = "f5a6ef98976b22b3b7f2f3a806f858cb862044cfa66805aa3ad84cb3d3b785ed"
dependencies = [ dependencies = [
"android_system_properties", "android_system_properties",
"core-foundation-sys", "core-foundation-sys",
"iana-time-zone-haiku",
"js-sys", "js-sys",
"once_cell",
"wasm-bindgen", "wasm-bindgen",
"winapi", "winapi",
] ]
[[package]] [[package]]
name = "idna" name = "iana-time-zone-haiku"
version = "0.2.3" version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" checksum = "fde6edd6cef363e9359ed3c98ba64590ba9eecba2293eb5a723ab32aee8926aa"
dependencies = [
"cxx",
"cxx-build",
]
[[package]]
name = "idna"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6"
dependencies = [ dependencies = [
"matches",
"unicode-bidi", "unicode-bidi",
"unicode-normalization", "unicode-normalization",
] ]
@ -439,12 +540,23 @@ dependencies = [
"hashbrown", "hashbrown",
] ]
[[package]]
name = "io-lifetimes"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46112a93252b123d31a119a8d1a1ac19deac4fac6e0e8b0df58f0d4e5870e63c"
dependencies = [
"libc",
"windows-sys 0.42.0",
]
[[package]] [[package]]
name = "ipblc" name = "ipblc"
version = "1.0.1" version = "1.1.0"
dependencies = [ dependencies = [
"chrono", "chrono",
"clap", "clap",
"git-version",
"ipnet", "ipnet",
"lazy_static", "lazy_static",
"mnl", "mnl",
@ -465,10 +577,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11b0d96e660696543b251e58030cf9787df56da39dab19ad60eae7353040917e" checksum = "11b0d96e660696543b251e58030cf9787df56da39dab19ad60eae7353040917e"
[[package]] [[package]]
name = "itoa" name = "is-terminal"
version = "1.0.3" version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" checksum = "28dfb6c8100ccc63462345b67d1bbc3679177c75ee4bf59bf29c8b1d110b8189"
dependencies = [
"hermit-abi 0.2.6",
"io-lifetimes",
"rustix",
"windows-sys 0.42.0",
]
[[package]]
name = "itoa"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc"
[[package]] [[package]]
name = "jobserver" name = "jobserver"
@ -481,9 +605,9 @@ dependencies = [
[[package]] [[package]]
name = "js-sys" name = "js-sys"
version = "0.3.59" version = "0.3.60"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "258451ab10b34f8af53416d1fdab72c22e805f0c92a1136d59470ec0b11138b2" checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47"
dependencies = [ dependencies = [
"wasm-bindgen", "wasm-bindgen",
] ]
@ -511,10 +635,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
[[package]] [[package]]
name = "lock_api" name = "link-cplusplus"
version = "0.4.8" version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f80bf5aacaf25cbfc8210d1cfb718f2bf3b11c4c54e5afe36c236853a8ec390" checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369"
dependencies = [
"cc",
]
[[package]]
name = "linux-raw-sys"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
[[package]]
name = "lock_api"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"scopeguard", "scopeguard",
@ -529,12 +668,6 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "matches"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.5.0" version = "2.5.0"
@ -651,15 +784,15 @@ version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
dependencies = [ dependencies = [
"hermit-abi", "hermit-abi 0.1.19",
"libc", "libc",
] ]
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.13.1" version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "074864da206b4973b84eb91683020dbefd6a8c3f0f38e054d93954e891935e4e" checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1"
[[package]] [[package]]
name = "os_str_bytes" name = "os_str_bytes"
@ -692,9 +825,9 @@ dependencies = [
[[package]] [[package]]
name = "percent-encoding" name = "percent-encoding"
version = "2.1.0" version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
[[package]] [[package]]
name = "pin-project-lite" name = "pin-project-lite"
@ -739,10 +872,16 @@ dependencies = [
] ]
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro-hack"
version = "1.0.43" version = "0.5.20+deprecated"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
[[package]]
name = "proc-macro2"
version = "1.0.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94e2ef8dbfc347b10c094890f778ee2e36ca9bb4262e86dc99cd217e35f3470b"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
@ -806,9 +945,9 @@ checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
[[package]] [[package]]
name = "reqwest" name = "reqwest"
version = "0.11.11" version = "0.11.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b75aa69a3f06bbcc66ede33af2af253c6f7a86b1ca0033f60c580a27074fbf92" checksum = "431949c384f4e2ae07605ccaa56d1d9d2ecdb5cadd4f9577ccfab29f2e5149fc"
dependencies = [ dependencies = [
"base64", "base64",
"bytes", "bytes",
@ -822,9 +961,9 @@ dependencies = [
"hyper-rustls", "hyper-rustls",
"ipnet", "ipnet",
"js-sys", "js-sys",
"lazy_static",
"log", "log",
"mime", "mime",
"once_cell",
"percent-encoding", "percent-encoding",
"pin-project-lite", "pin-project-lite",
"rustls", "rustls",
@ -858,6 +997,20 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "rustix"
version = "0.36.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4feacf7db682c6c329c4ede12649cd36ecab0f3be5b7d74e6a20304725db4549"
dependencies = [
"bitflags",
"errno",
"io-lifetimes",
"libc",
"linux-raw-sys",
"windows-sys 0.42.0",
]
[[package]] [[package]]
name = "rustls" name = "rustls"
version = "0.20.6" version = "0.20.6"
@ -906,6 +1059,12 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "scratch"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898"
[[package]] [[package]]
name = "sct" name = "sct"
version = "0.7.0" version = "0.7.0"
@ -918,18 +1077,18 @@ dependencies = [
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.144" version = "1.0.145"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860" checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.144" version = "1.0.145"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00" checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -938,9 +1097,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.85" version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" checksum = "41feea4228a6f1cd09ec7a3593a682276702cd67b5273544757dae23c096f074"
dependencies = [ dependencies = [
"itoa", "itoa",
"ryu", "ryu",
@ -979,15 +1138,15 @@ dependencies = [
[[package]] [[package]]
name = "smallvec" name = "smallvec"
version = "1.9.0" version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
[[package]] [[package]]
name = "socket2" name = "socket2"
version = "0.4.6" version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10c98bba371b9b22a71a9414e420f92ddeb2369239af08200816169d5e2dd7aa" checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd"
dependencies = [ dependencies = [
"libc", "libc",
"winapi", "winapi",
@ -1013,9 +1172,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.99" version = "1.0.102"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" checksum = "3fcd952facd492f9be3ef0d0b7032a6e442ee9b361d4acc2b1d0c4aaa5f613a1"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -1056,12 +1215,6 @@ dependencies = [
"winapi-util", "winapi-util",
] ]
[[package]]
name = "textwrap"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb"
[[package]] [[package]]
name = "time" name = "time"
version = "0.1.44" version = "0.1.44"
@ -1132,9 +1285,9 @@ dependencies = [
[[package]] [[package]]
name = "tokio-util" name = "tokio-util"
version = "0.7.3" version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc463cd8deddc3770d20f9852143d50bf6094e640b485cb2e189a2099085ff45" checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740"
dependencies = [ dependencies = [
"bytes", "bytes",
"futures-core", "futures-core",
@ -1161,9 +1314,9 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
[[package]] [[package]]
name = "tracing" name = "tracing"
version = "0.1.36" version = "0.1.37"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307" checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"pin-project-lite", "pin-project-lite",
@ -1172,9 +1325,9 @@ dependencies = [
[[package]] [[package]]
name = "tracing-core" name = "tracing-core"
version = "0.1.29" version = "0.1.30"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7" checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a"
dependencies = [ dependencies = [
"once_cell", "once_cell",
] ]
@ -1193,24 +1346,30 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.3" version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
[[package]] [[package]]
name = "unicode-normalization" name = "unicode-normalization"
version = "0.1.21" version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "854cbdc4f7bc6ae19c820d44abdc3277ac3e1b2b93db20a636825d9322fb60e6" checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
dependencies = [ dependencies = [
"tinyvec", "tinyvec",
] ]
[[package]] [[package]]
name = "unicode-xid" name = "unicode-width"
version = "0.2.3" version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
[[package]]
name = "unicode-xid"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
[[package]] [[package]]
name = "untrusted" name = "untrusted"
@ -1220,13 +1379,12 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
[[package]] [[package]]
name = "url" name = "url"
version = "2.2.2" version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643"
dependencies = [ dependencies = [
"form_urlencoded", "form_urlencoded",
"idna", "idna",
"matches",
"percent-encoding", "percent-encoding",
] ]
@ -1277,9 +1435,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]] [[package]]
name = "wasm-bindgen" name = "wasm-bindgen"
version = "0.2.82" version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc7652e3f6c4706c8d9cd54832c4a4ccb9b5336e2c3bd154d5cccfbf1c1f5f7d" checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"wasm-bindgen-macro", "wasm-bindgen-macro",
@ -1287,9 +1445,9 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-backend" name = "wasm-bindgen-backend"
version = "0.2.82" version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "662cd44805586bd52971b9586b1df85cdbbd9112e4ef4d8f41559c334dc6ac3f" checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142"
dependencies = [ dependencies = [
"bumpalo", "bumpalo",
"log", "log",
@ -1302,9 +1460,9 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-futures" name = "wasm-bindgen-futures"
version = "0.4.32" version = "0.4.33"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa76fb221a1f8acddf5b54ace85912606980ad661ac7a503b4570ffd3a624dad" checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"js-sys", "js-sys",
@ -1314,9 +1472,9 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-macro" name = "wasm-bindgen-macro"
version = "0.2.82" version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b260f13d3012071dfb1512849c033b1925038373aea48ced3012c09df952c602" checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810"
dependencies = [ dependencies = [
"quote", "quote",
"wasm-bindgen-macro-support", "wasm-bindgen-macro-support",
@ -1324,9 +1482,9 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-macro-support" name = "wasm-bindgen-macro-support"
version = "0.2.82" version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5be8e654bdd9b79216c2929ab90721aa82faf65c48cdf08bdc4e7f51357b80da" checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -1337,15 +1495,15 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-shared" name = "wasm-bindgen-shared"
version = "0.2.82" version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6598dd0bd3c7d51095ff6531a5b23e02acdc81804e30d8f07afb77b7215a140a" checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
[[package]] [[package]]
name = "web-sys" name = "web-sys"
version = "0.3.59" version = "0.3.60"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed055ab27f941423197eb86b2035720b1a3ce40504df082cac2ecc6ed73335a1" checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f"
dependencies = [ dependencies = [
"js-sys", "js-sys",
"wasm-bindgen", "wasm-bindgen",
@ -1363,9 +1521,9 @@ dependencies = [
[[package]] [[package]]
name = "webpki-roots" name = "webpki-roots"
version = "0.22.4" version = "0.22.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1c760f0d366a6c24a02ed7816e23e691f5d92291f94d15e836006fd11b04daf" checksum = "368bfe657969fb01238bb756d351dcade285e0f6fcbd36dcb23359a5169975be"
dependencies = [ dependencies = [
"webpki", "webpki",
] ]

View File

@ -1,6 +1,6 @@
[package] [package]
name = "ipblc" name = "ipblc"
version = "1.0.1" version = "1.1.0"
edition = "2021" edition = "2021"
authors = ["PaulBSD <paul@paulbsd.com>"] authors = ["PaulBSD <paul@paulbsd.com>"]
description = "ipblc is a tool that search and send attacking ip addresses to ipbl" description = "ipblc is a tool that search and send attacking ip addresses to ipbl"
@ -10,7 +10,8 @@ repository = "https://git.paulbsd.com/paulbsd/ipblc"
[dependencies] [dependencies]
chrono = { version = "0.4", features = ["serde"] } chrono = { version = "0.4", features = ["serde"] }
clap = "3.2" clap = { version = "4.0", features = ["string"] }
git-version = "0.3.5"
ipnet = "2.7" ipnet = "2.7"
lazy_static = "1.4" lazy_static = "1.4"
mnl = "0.2" mnl = "0.2"

View File

@ -1,9 +1,11 @@
use crate::ip::{BlockIpData, IpData}; use crate::ip::{BlockIpData, IpData};
use crate::utils::*; use crate::utils::{gethostname, sleep_s};
use chrono::prelude::*; use chrono::prelude::*;
use chrono::Duration; use chrono::Duration;
use clap::{Arg, ArgMatches, Command}; use clap::{Arg, ArgAction, ArgMatches, Command};
use git_version::git_version;
use ipnet::IpNet;
use nix::sys::inotify::{AddWatchFlags, InitFlags, Inotify, WatchDescriptor}; use nix::sys::inotify::{AddWatchFlags, InitFlags, Inotify, WatchDescriptor};
use regex::Regex; use regex::Regex;
use reqwest::{Client, Error as ReqError, Response}; use reqwest::{Client, Error as ReqError, Response};
@ -12,8 +14,10 @@ use std::collections::HashMap;
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use std::path::Path; use std::path::Path;
pub const GIT_VERSION: &str = git_version!();
const MASTERSERVER: &str = "ipbl.paulbsd.com"; const MASTERSERVER: &str = "ipbl.paulbsd.com";
const ZMQSUBSCRIPTION: &str = "ipbl"; const ZMQSUBSCRIPTION: &str = "ipbl";
const CONFIG_RETRY: u64 = 10;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Context { pub struct Context {
@ -45,21 +49,17 @@ pub struct Flags {
} }
impl Context { impl Context {
pub async fn new() -> Self { pub async fn new<'a>() -> Self {
// Get flags // Get flags
let debug = Context::argparse().is_present("debug"); let argp: ArgMatches = Context::argparse();
let server = Context::argparse() //let debug: bool = argp.contains_id("debug");
.value_of("server") let debug: bool = argp.get_one::<bool>("debug").unwrap().to_owned();
.unwrap_or(format!("https://{}", MASTERSERVER).as_str()) let server: String = argp.get_one::<String>("server").unwrap().to_string();
.to_string();
// Build context // Build context
let mut ctx = Context { let mut ctx = Context {
cfg: Config::new(), cfg: Config::new(),
flags: Flags { flags: Flags { debug, server },
debug: debug,
server: server,
},
hostname: gethostname(true), hostname: gethostname(true),
discovery: Discovery { discovery: Discovery {
version: "1.0".to_string(), version: "1.0".to_string(),
@ -67,9 +67,10 @@ impl Context {
}, },
client: Client::builder() client: Client::builder()
.user_agent(format!( .user_agent(format!(
"{}/{}@{}", "{}/{}@{}/{}",
env!("CARGO_PKG_NAME"), env!("CARGO_PKG_NAME"),
env!("CARGO_PKG_VERSION"), env!("CARGO_PKG_VERSION"),
GIT_VERSION,
gethostname(false) gethostname(false)
)) ))
.build() .build()
@ -87,18 +88,17 @@ impl Context {
break; break;
} }
Err(err) => { Err(err) => {
let retry = 10; println!("error loading config: {err}, retrying in {CONFIG_RETRY} secs");
println!("error loading config: {err}, retrying in {retry} secs"); sleep_s(CONFIG_RETRY);
std::thread::sleep(std::time::Duration::from_secs(retry));
} }
} }
} }
ctx ctx
} }
pub fn argparse() -> ArgMatches { pub fn argparse<'a>() -> ArgMatches {
Command::new(env!("CARGO_PKG_NAME")) Command::new(env!("CARGO_PKG_NAME"))
.version(env!("CARGO_PKG_VERSION")) .version(format!("{}@{}", env!("CARGO_PKG_VERSION"), GIT_VERSION))
.author(env!("CARGO_PKG_AUTHORS")) .author(env!("CARGO_PKG_AUTHORS"))
.about(env!("CARGO_PKG_DESCRIPTION")) .about(env!("CARGO_PKG_DESCRIPTION"))
.arg( .arg(
@ -106,15 +106,14 @@ impl Context {
.short('s') .short('s')
.long("server") .long("server")
.value_name("server") .value_name("server")
.default_value(format!("https://{MASTERSERVER}").as_str()) .default_value(format!("https://{MASTERSERVER}"))
.help("Sets a http server") .help("Sets a http server"),
.takes_value(true),
) )
.arg( .arg(
Arg::new("debug") Arg::new("debug")
.short('d') .short('d')
.takes_value(false) .help("Enable debugging")
.help("Enable debugging"), .action(ArgAction::SetTrue),
) )
.get_matches() .get_matches()
} }
@ -137,9 +136,9 @@ impl Context {
} }
pub async fn load(&mut self) -> Result<(), Box<dyn std::error::Error>> { pub async fn load(&mut self) -> Result<(), Box<dyn std::error::Error>> {
#[cfg(test)] if cfg!(test) {
return Ok(()); return Ok(());
}
self.discovery = self.discovery().await?; self.discovery = self.discovery().await?;
self.cfg.load(self.to_owned()).await?; self.cfg.load(self.to_owned()).await?;
self.create_sas().await?; self.create_sas().await?;
@ -163,40 +162,43 @@ impl Context {
if block.tryfail >= set.tryfail { if block.tryfail >= set.tryfail {
res.push(block.ipdata.clone()); res.push(block.ipdata.clone());
if block.tryfail == set.tryfail { if block.tryfail == set.tryfail {
block.starttime = now; block.starttime = DateTime::from(now);
} }
} }
} }
res res
} }
pub async fn update_blocklist(&mut self, ipdata: &IpData) -> IpData { pub async fn update_blocklist(&mut self, ipdata: &mut IpData) -> Option<IpData> {
if self.blocklist.contains_key(&ipdata.ip) { match self.cfg.sets.get(&ipdata.src) {
let mut a = self.blocklist.get_mut(&ipdata.ip).unwrap(); Some(set) => {
a.tryfail += 1; if self.blocklist.contains_key(&ipdata.ip)
return a.ipdata.clone(); && self.hostname == ipdata.hostname
} else { && ipdata.mode == "file".to_string()
let now = Local::now().trunc_subsecs(0); {
let mut tryfail = 0; let mut block = self.blocklist.get_mut(&ipdata.ip).unwrap();
if ipdata.mode == "zmq".to_string() { block.tryfail += 1;
tryfail = 100; block.blocktime = set.blocktime;
} if block.tryfail >= set.tryfail {
match self.cfg.sets.get(&ipdata.src) { return Some(block.ipdata.clone());
Some(set) => { }
self.blocklist.insert( } else {
ipdata.ip.to_string(), let starttime = DateTime::parse_from_rfc3339(ipdata.date.as_str())
BlockIpData { .unwrap()
.with_timezone(&chrono::Local);
self.blocklist
.entry(ipdata.ip.to_string())
.or_insert(BlockIpData {
ipdata: ipdata.clone(), ipdata: ipdata.clone(),
tryfail, tryfail: 100,
starttime: now, starttime,
blocktime: set.blocktime, blocktime: set.blocktime,
}, });
);
} }
None => {}
} }
return ipdata.clone(); None => {}
} }
None
} }
pub async fn gc_blocklist(&mut self) -> Vec<IpData> { pub async fn gc_blocklist(&mut self) -> Vec<IpData> {
@ -218,7 +220,7 @@ impl Context {
for (src, set) in self.cfg.sets.iter() { for (src, set) in self.cfg.sets.iter() {
let p = Path::new(set.path.as_str()); let p = Path::new(set.path.as_str());
if p.is_dir() { if p.is_dir() {
let res = match self.hashwd.get(&set.path.to_string()) { let wd = match self.hashwd.get(&set.path.to_string()) {
Some(wd) => *wd, Some(wd) => *wd,
None => { None => {
let res = self let res = self
@ -239,17 +241,27 @@ impl Context {
) )
} }
}; };
self.sas.insert( match self.sas.get_mut(&src.clone()) {
src.clone(), Some(s) => {
SetMap { s.filename = set.filename.clone();
filename: set.filename.clone(), s.fullpath = fullpath;
fullpath: fullpath, s.set = set.clone();
set: set.clone(), s.regex = Regex::new(set.regex.as_str()).unwrap();
regex: Regex::new(set.regex.as_str()).unwrap(), }
wd: res, None => {
watchedfiles: HashMap::new(), self.sas.insert(
}, src.clone(),
); SetMap {
filename: set.filename.clone(),
fullpath,
set: set.clone(),
regex: Regex::new(set.regex.as_str()).unwrap(),
wd,
watchedfiles: HashMap::new(),
},
);
}
}
} }
} }
Ok(()) Ok(())
@ -396,6 +408,19 @@ impl Config {
self.zmq = data; self.zmq = data;
Ok(()) Ok(())
} }
pub fn build_trustnets(&self) -> Vec<IpNet> {
let mut trustnets: Vec<IpNet> = vec![];
for trustnet in &self.trustnets {
match trustnet.parse() {
Ok(net) => trustnets.push(net),
Err(err) => {
println!("error parsing {trustnet}, error: {err}");
}
};
}
trustnets
}
} }
#[derive(Debug, Deserialize, Serialize, Clone)] #[derive(Debug, Deserialize, Serialize, Clone)]
@ -453,7 +478,7 @@ mod test {
ctx.blocklist = HashMap::new(); ctx.blocklist = HashMap::new();
for _i in 0..10 { for _i in 0..10 {
ctx.update_blocklist(&IpData { ctx.update_blocklist(&mut IpData {
ip: "1.1.1.1".to_string(), ip: "1.1.1.1".to_string(),
hostname: "test1".to_string(), hostname: "test1".to_string(),
date: now.to_rfc3339().to_string(), date: now.to_rfc3339().to_string(),
@ -463,8 +488,8 @@ mod test {
.await; .await;
} }
for _i in 0..10 { for _ in 0..10 {
ctx.update_blocklist(&IpData { ctx.update_blocklist(&mut IpData {
ip: "1.1.1.2".to_string(), ip: "1.1.1.2".to_string(),
hostname: "test2".to_string(), hostname: "test2".to_string(),
date: now.to_rfc3339().to_string(), date: now.to_rfc3339().to_string(),
@ -474,7 +499,7 @@ mod test {
.await; .await;
} }
ctx.update_blocklist(&IpData { ctx.update_blocklist(&mut IpData {
ip: "1.1.1.3".to_string(), ip: "1.1.1.3".to_string(),
hostname: "testgood".to_string(), hostname: "testgood".to_string(),
date: now.to_rfc3339().to_string(), date: now.to_rfc3339().to_string(),
@ -483,7 +508,7 @@ mod test {
}) })
.await; .await;
ctx.update_blocklist(&IpData { ctx.update_blocklist(&mut IpData {
ip: "1.1.1.4".to_string(), ip: "1.1.1.4".to_string(),
hostname: "testgood".to_string(), hostname: "testgood".to_string(),
date: now.to_rfc3339().to_string(), date: now.to_rfc3339().to_string(),
@ -492,7 +517,7 @@ mod test {
}) })
.await; .await;
ctx.update_blocklist(&IpData { ctx.update_blocklist(&mut IpData {
ip: "1.1.1.4".to_string(), ip: "1.1.1.4".to_string(),
hostname: "testgood".to_string(), hostname: "testgood".to_string(),
date: now.to_rfc3339().to_string(), date: now.to_rfc3339().to_string(),
@ -502,10 +527,10 @@ mod test {
.await; .await;
let mut ip1 = ctx.blocklist.get_mut(&"1.1.1.1".to_string()).unwrap(); let mut ip1 = ctx.blocklist.get_mut(&"1.1.1.1".to_string()).unwrap();
ip1.starttime = now - Duration::minutes(61); ip1.starttime = DateTime::from(now) - Duration::minutes(61);
let mut ip2 = ctx.blocklist.get_mut(&"1.1.1.2".to_string()).unwrap(); let mut ip2 = ctx.blocklist.get_mut(&"1.1.1.2".to_string()).unwrap();
ip2.starttime = now - Duration::minutes(62); ip2.starttime = DateTime::from(now) - Duration::minutes(62);
ctx ctx
} }
@ -515,7 +540,8 @@ mod test {
let pending = ctx.get_blocklist_pending().await; let pending = ctx.get_blocklist_pending().await;
assert_eq!(pending.len(), 4); assert_eq!(pending.len(), 4);
for i in ["1.1.1.1", "1.1.1.2", "1.1.1.3", "1.1.1.4"] { let ips = ["1.1.1.1", "1.1.1.2", "1.1.1.3", "1.1.1.4"];
for i in ips {
let ip = ctx let ip = ctx
.blocklist .blocklist
.get(&i.to_string()) .get(&i.to_string())
@ -530,6 +556,7 @@ mod test {
#[tokio::test] #[tokio::test]
pub async fn test_blocklist_toblock() { pub async fn test_blocklist_toblock() {
let mut ctx = prepare_test_data().await; let mut ctx = prepare_test_data().await;
ctx.gc_blocklist().await;
let toblock = ctx.get_blocklist_toblock().await; let toblock = ctx.get_blocklist_toblock().await;
assert_eq!(toblock.len(), 2); assert_eq!(toblock.len(), 2);
} }
@ -539,11 +566,10 @@ mod test {
let mut ctx = prepare_test_data().await; let mut ctx = prepare_test_data().await;
let after_gc = ctx.gc_blocklist().await; let after_gc = ctx.gc_blocklist().await;
assert_eq!(after_gc.len(), 2); assert_eq!(after_gc.len(), 2);
for i in &["1.1.1.3", "1.1.1.4"] { let ips = &["1.1.1.3", "1.1.1.4"];
assert_eq!( for ip in ips {
ctx.blocklist.get(&i.to_string()).unwrap().ipdata.ip, let ipstring = ip.to_string();
i.to_string() assert_eq!(ctx.blocklist.get(&ipstring).unwrap().ipdata.ip, ipstring);
);
} }
} }
} }

View File

@ -22,6 +22,7 @@ pub fn block(
tablename: &String, tablename: &String,
ips_add: &Vec<IpData>, ips_add: &Vec<IpData>,
ret: &mut Vec<String>, ret: &mut Vec<String>,
fwlen: &mut usize,
) -> std::result::Result<(), Error> { ) -> std::result::Result<(), Error> {
// convert chain // convert chain
let ips_add = convert(ips_add); let ips_add = convert(ips_add);
@ -35,6 +36,9 @@ pub fn block(
// add chain // add chain
batch.add(&chain, nftnl::MsgType::Add); batch.add(&chain, nftnl::MsgType::Add);
let rule = Rule::new(&chain);
batch.add(&rule, nftnl::MsgType::Del);
let mut rule = Rule::new(&chain); let mut rule = Rule::new(&chain);
rule.add_expr(&nft_expr!(ct state)); rule.add_expr(&nft_expr!(ct state));
rule.add_expr(&nft_expr!(bitwise mask 4u32, xor 0u32)); rule.add_expr(&nft_expr!(bitwise mask 4u32, xor 0u32));
@ -59,7 +63,10 @@ pub fn block(
// validate and send batch // validate and send batch
let finalized_batch = batch.finalize(); let finalized_batch = batch.finalize();
send_and_process(&finalized_batch)?; send_and_process(&finalized_batch)?;
ret.push(format!("{length} ip in memory", length = ips_add.len())); if fwlen != &mut ips_add.len() {
ret.push(format!("{length} ip in firewall", length = ips_add.len()));
}
*fwlen = ips_add.len();
Ok(()) Ok(())
} }

View File

@ -1,5 +1,5 @@
use crate::config::Context; use crate::config::Context;
use crate::utils::*; use crate::utils::gethostname;
use chrono::prelude::*; use chrono::prelude::*;
use ipnet::IpNet; use ipnet::IpNet;
@ -60,11 +60,12 @@ impl Display for IpData {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
write!( write!(
f, f,
"ip: {ip}, src: {src}, date: {date}, hostname: {hostname}", "ip: {ip}, src: {src}, date: {date}, hostname: {hostname}, mode: {mode}",
ip = self.ip, ip = self.ip,
src = self.src, src = self.src,
date = self.date, date = self.date,
hostname = self.hostname, hostname = self.hostname,
mode = self.mode,
) )
} }
} }
@ -145,7 +146,7 @@ pub fn filter(
trustnets: &Vec<IpNet>, trustnets: &Vec<IpNet>,
regex: &Regex, regex: &Regex,
src: &String, src: &String,
lastprocess: &DateTime<Local>, last: &DateTime<Local>,
) -> isize { ) -> isize {
let mut ips = 0; let mut ips = 0;
let hostname = gethostname(true); let hostname = gethostname(true);
@ -159,15 +160,14 @@ pub fn filter(
s_ipaddr = sv4.get(0).unwrap().as_str().to_string(); s_ipaddr = sv4.get(0).unwrap().as_str().to_string();
} }
None => { None => {
continue; match R_IPV6.captures(l.as_str()) {
/*match R_IPV6.captures(l.as_str()) {
Some(sv6) => { Some(sv6) => {
s_ipaddr = sv6.get(0).unwrap().as_str().to_string(); s_ipaddr = sv6.get(0).unwrap().as_str().to_string();
} }
None => { None => {
continue; continue;
} }
};*/ };
} }
}; };
@ -175,7 +175,7 @@ pub fn filter(
match R_DATE.captures(l.as_str()) { match R_DATE.captures(l.as_str()) {
Some(sdt) => { Some(sdt) => {
s_date = parse_date(sdt); s_date = parse_date(sdt);
if &s_date < lastprocess { if &s_date < last {
continue; continue;
} }
} }

300
src/ipblc.rs Normal file
View File

@ -0,0 +1,300 @@
use crate::config::{Context, GIT_VERSION};
use crate::fw::{block, init};
use crate::ip::{filter, push_ip, IpData};
use crate::utils::{gethostname, read_lines, sleep_s};
use crate::zmqcom::zconnect;
use chrono::prelude::*;
use chrono::prelude::{DateTime, Local};
use chrono::Duration;
use nix::sys::inotify::InotifyEvent;
use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::mpsc::{channel, Receiver, Sender};
use tokio::sync::Mutex;
const BL_CHAN_SIZE: usize = 32;
const ZMQ_CHAN_SIZE: usize = 64;
pub async fn run() {
let ctx = Arc::new(Mutex::new(Context::new().await));
println!(
"Launching {}, version {}",
env!("CARGO_PKG_NAME"),
format!("{}@{}", env!("CARGO_PKG_VERSION"), GIT_VERSION)
);
let (ipdatatx, mut ipdatarx): (Sender<IpData>, Receiver<IpData>) = channel(ZMQ_CHAN_SIZE);
// initialize the firewall table
init(&env!("CARGO_PKG_NAME").to_string());
let mut fwlen: usize = 0;
// initialize zeromq sockets
let reqsocket;
let subsocket;
{
let ctxarc = Arc::clone(&ctx);
let zmqctx = ctxarc.lock().await;
reqsocket = zconnect(&zmqctx.cfg.zmq.get("reqrep").unwrap(), zmq::REQ)
.await
.unwrap();
subsocket = zconnect(&zmqctx.cfg.zmq.get("pubsub").unwrap(), zmq::SUB)
.await
.unwrap();
}
listenpubsub(&ctx, ipdatatx.clone(), subsocket).await;
let mut blrx = watchfiles(&ctx).await;
let ctxarc = Arc::clone(&ctx);
tokio::spawn(async move {
compare_files_changes(&ctxarc, &mut blrx, &ipdatatx).await;
});
let mut ip_init = IpData {
ip: "".to_string(),
src: "".to_string(),
date: "".to_string(),
hostname: "".to_string(),
mode: "init".to_string(),
};
send_to_ipbl_zmq(&reqsocket, &mut ip_init).await;
loop {
let mut ret: Vec<String> = Vec::new();
let begin: DateTime<Local> = Local::now().trunc_subsecs(0);
// wait for logs parse and zmq channel receive
let mut received_ip = ipdatarx.recv().await.unwrap();
// lock the context mutex
let ctxarc = Arc::clone(&ctx);
let mut ctx = ctxarc.lock().await;
if received_ip.ip == "".to_string() && received_ip.mode == "init".to_string() {
for ip_to_send in &mut ctx.get_blocklist_toblock().await {
ip_to_send.mode = "init".to_string();
send_to_ipbl_zmq(&reqsocket, ip_to_send).await;
}
continue;
}
// refresh context blocklist
let filtered_ip = ctx.update_blocklist(&mut received_ip).await;
ctx.gc_blocklist().await;
// send ip list to ws and zmq sockets
if let Some(mut ip) = filtered_ip {
send_to_ipbl_ws(&ctx, &mut ip, &mut ret).await;
send_to_ipbl_zmq(&reqsocket, &mut ip).await;
}
// apply firewall blocking
block(
&env!("CARGO_PKG_NAME").to_string(),
&ctx.get_blocklist_toblock().await,
&mut ret,
&mut fwlen,
)
.unwrap();
// log lines
if ret.len() > 0 {
println!("{ret}", ret = ret.join(", "));
}
let end: DateTime<Local> = Local::now().trunc_subsecs(0);
if (end - begin) > Duration::seconds(5) {
// reload configuration from the server
match ctx.load().await {
Ok(_) => {}
Err(err) => {
println!("error loading config: {err}");
}
}
}
}
}
async fn watchfiles(ctx: &Arc<Mutex<Context>>) -> Receiver<FileEvent> {
let (bltx, blrx): (Sender<FileEvent>, Receiver<FileEvent>) = channel(BL_CHAN_SIZE);
let ctx = Arc::clone(ctx);
tokio::spawn(async move {
loop {
let events: Vec<InotifyEvent>;
{
let c = ctx.lock().await;
let instance = c.instance.clone();
drop(c);
events = instance.read_events().unwrap();
}
for inevent in events {
let date: DateTime<Local> = Local::now().trunc_subsecs(0);
bltx.send(FileEvent { inevent, date }).await.unwrap();
}
}
});
blrx
}
async fn get_last_file_size(w: &mut HashMap<String, u64>, path: &str) -> (u64, bool) {
let currentlen = match std::fs::metadata(&path.to_string()) {
Ok(u) => u.len().clone(),
Err(_) => 0u64,
};
let lastlen = match w.insert(path.to_string(), currentlen) {
Some(u) => u,
None => 0u64,
};
(lastlen, lastlen != currentlen)
}
async fn compare_files_changes(
ctx: &Arc<Mutex<Context>>,
inrx: &mut Receiver<FileEvent>,
ipdatatx: &Sender<IpData>,
) {
let mut tnets;
loop {
let modfiles = inrx.recv().await.unwrap();
let mut iplist: Vec<IpData> = vec![];
let mut ctx = ctx.lock().await;
tnets = ctx.cfg.build_trustnets();
match modfiles.inevent.name {
Some(name) => {
let filename = name.to_str().unwrap();
for sak in &mut ctx.clone().sas.keys() {
let sa = &mut ctx.sas.get_mut(sak).unwrap();
if modfiles.inevent.wd == sa.wd {
let handle: String;
if sa.filename.as_str() == "" {
handle = format!("{}/{}", &sa.fullpath, filename);
} else if filename.starts_with(sa.filename.as_str()) {
handle = sa.fullpath.to_owned();
} else {
continue;
}
let (filesize, sizechanged) =
get_last_file_size(&mut sa.watchedfiles, &handle).await;
if !sizechanged {
continue;
}
match read_lines(&handle, filesize) {
Some(lines) => {
filter(
lines,
&mut iplist,
&tnets,
&sa.regex,
&sa.set.src,
&modfiles.date,
);
}
None => {}
};
break;
}
}
for ip in iplist {
ipdatatx.send(ip).await.unwrap();
}
}
None => {}
}
}
}
pub struct FileEvent {
pub inevent: InotifyEvent,
pub date: DateTime<Local>,
}
impl std::fmt::Debug for FileEvent {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{ie:?}", ie = self.inevent)
}
}
async fn send_to_ipbl_zmq(reqsocket: &zmq::Socket, ip: &mut IpData) {
let msg = format!("{val}", val = serde_json::to_string(&ip).unwrap());
match reqsocket.send(&msg, 0) {
Ok(_) => {}
Err(e) => {
println!("{e:?}")
}
};
match reqsocket.recv_string(0) {
Ok(o) => match o {
Ok(_) => {}
Err(ee) => {
println!("{ee:?}")
}
},
Err(e) => {
println!("{e:?}")
}
};
}
async fn send_to_ipbl_ws(ctx: &Context, ip: &mut IpData, ret: &mut Vec<String>) {
ret.push(format!("host: {hostname}", hostname = ctx.hostname));
loop {
match push_ip(&ctx, &ip, ret).await {
Ok(_) => {
break;
}
Err(err) => {
println!("{err}");
sleep_s(1);
}
};
}
}
async fn listenpubsub(ctx: &Arc<Mutex<Context>>, txpubsub: Sender<IpData>, socket: zmq::Socket) {
let ctx = ctx.lock().await;
let prefix = format!(
"{sub} ",
sub = ctx.cfg.zmq.get("pubsub").unwrap().subscription
);
socket
.set_subscribe(ctx.cfg.zmq.get("pubsub").unwrap().subscription.as_bytes())
.expect("failed setting subscription");
drop(ctx);
tokio::spawn(async move {
loop {
let msgs: Option<String> = match socket.recv_string(0) {
Ok(s) => match s {
Ok(ss) => Some(ss),
Err(e) => {
println!("{e:?}");
None
}
},
Err(e) => {
println!("{e:?}");
None
}
};
match msgs {
Some(ss) => {
let msg = ss.strip_prefix(prefix.as_str()).unwrap();
let tosend: IpData = serde_json::from_str(msg).unwrap();
if tosend.hostname != gethostname(true) || tosend.mode == "init".to_string() {
txpubsub.send(tosend).await.unwrap();
}
}
None => {}
};
}
});
}

View File

@ -1,202 +0,0 @@
use super::*;
use chrono::prelude::*;
use chrono::Duration;
use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::mpsc::{channel, Receiver, Sender};
use tokio::sync::Mutex;
const BL_CHAN_SIZE: usize = 32;
const ZMQ_CHAN_SIZE: usize = 64;
pub async fn process(ctx: &Arc<Mutex<Context>>) {
println!(
"Launching {} version {}",
env!("CARGO_PKG_NAME"),
env!("CARGO_PKG_VERSION")
);
let (ipdatatx, mut ipdatarx): (Sender<IpData>, Receiver<IpData>) = channel(ZMQ_CHAN_SIZE);
// initialize the firewall table
//firewall::init(&env!("CARGO_PKG_NAME").to_string());
// initialize zeromq sockets
let reqsocket;
let subsocket;
{
let ctxarc = Arc::clone(&ctx);
let zmqctx = ctxarc.lock().await;
reqsocket = zconnect(&zmqctx.cfg.zmq.get("reqrep").unwrap(), zmq::REQ)
.await
.unwrap();
subsocket = zconnect(&zmqctx.cfg.zmq.get("pubsub").unwrap(), zmq::SUB)
.await
.unwrap();
}
listenpubsub(&ctx, ipdatatx.clone(), subsocket).await;
let mut blrx = watchfiles(&ctx).await;
let ctxarc = Arc::clone(&ctx);
tokio::spawn(async move {
compare_files_changes(&ctxarc, &mut blrx, &ipdatatx).await;
});
let mut ip = IpData {
ip: "".to_string(),
src: "".to_string(),
date: "".to_string(),
hostname: "".to_string(),
mode: "init".to_string(),
};
send_to_ipbl_zmq(&reqsocket, &mut ip).await;
loop {
let mut ret: Vec<String> = Vec::new();
let begin: DateTime<Local> = Local::now().trunc_subsecs(0);
// wait for logs parse and zmq channel receive
let mut ip = ipdatarx.recv().await.unwrap();
// lock the context mutex
let ctxarc = Arc::clone(&ctx);
let mut ctx = ctxarc.lock().await;
if ip.mode == "init" {
for i in &mut ctx.get_blocklist_toblock().await {
i.mode = "zmq".to_string();
send_to_ipbl_zmq(&reqsocket, i).await;
}
continue;
}
// refresh context blocklist
ctx.update_blocklist(&ip).await;
ctx.gc_blocklist().await;
// send ip list to ws and zmq sockets
if ip.hostname == ctx.hostname {
send_to_ipbl_ws(&ctx, &ip, &mut ret).await;
send_to_ipbl_zmq(&reqsocket, &mut ip).await;
}
// apply firewall blocking
firewall::block(
&env!("CARGO_PKG_NAME").to_string(),
&ctx.get_blocklist_toblock().await,
&mut ret,
)
.unwrap();
// log lines
println!("{ret}", ret = ret.join(", "));
let end: DateTime<Local> = Local::now().trunc_subsecs(0);
if (end - begin) > Duration::seconds(5) {
// reload configuration from the server
match ctx.load().await {
Ok(_) => {}
Err(err) => {
println!("error loading config: {err}");
}
}
}
}
}
async fn watchfiles(ctx: &Arc<Mutex<Context>>) -> Receiver<FileEvent> {
let (bltx, blrx): (Sender<FileEvent>, Receiver<FileEvent>) = channel(BL_CHAN_SIZE);
let ctx = Arc::clone(ctx);
tokio::spawn(async move {
loop {
let events: Vec<InotifyEvent>;
{
let ctx = ctx.lock().await;
events = ctx.instance.read_events().unwrap();
}
for event in events {
let date: DateTime<Local> = Local::now().trunc_subsecs(0);
bltx.send(FileEvent {
inotifyevent: event,
date: date,
})
.await
.unwrap();
}
}
});
blrx
}
async fn get_last_file_size(watchedfiles: &mut HashMap<String, u64>, path: &str) -> u64 {
let currentlen = match std::fs::metadata(&path.to_string()) {
Ok(u) => u.len().clone(),
Err(_) => 0u64,
};
let lastlen = match watchedfiles.insert(path.to_string(), currentlen) {
Some(u) => u,
None => 0,
};
lastlen
}
async fn compare_files_changes(
ctx: &Arc<Mutex<Context>>,
inotifyrx: &mut Receiver<FileEvent>,
ipdatatx: &Sender<IpData>,
) {
let mut trustnets;
loop {
let modifiedfiles = inotifyrx.recv().await.unwrap();
let mut list: Vec<IpData> = vec![];
let mut ctx = ctx.lock().await;
trustnets = build_trustnets(&ctx.cfg.trustnets);
match modifiedfiles.inotifyevent.name {
Some(name) => {
let inotify_filename = name.to_str().unwrap();
for sak in &mut ctx.clone().sas.keys() {
let sa = &mut ctx.sas.get_mut(sak).unwrap();
if modifiedfiles.inotifyevent.wd == sa.wd {
let handle_filename: String;
if sa.filename.as_str() == "" {
handle_filename = format!("{}/{}", &sa.fullpath, inotify_filename);
} else if inotify_filename.starts_with(sa.filename.as_str()) {
handle_filename = sa.fullpath.to_owned();
} else {
continue;
}
let filesize =
get_last_file_size(&mut sa.watchedfiles, &handle_filename).await;
match read_lines(&handle_filename, filesize) {
Some(lines) => {
filter(
lines,
&mut list,
&trustnets,
&sa.regex,
&sa.set.src,
&modifiedfiles.date,
);
}
None => {}
};
break;
}
}
drop(ctx);
for ip in list {
ipdatatx.send(ip).await.unwrap();
}
}
None => {}
}
}
}

View File

@ -1,100 +0,0 @@
pub mod inc;
use crate::config::*;
use crate::firewall;
use crate::ip::*;
use crate::utils::*;
use crate::zmqcom::*;
use chrono::prelude::{DateTime, Local};
use nix::sys::inotify::InotifyEvent;
use std::sync::Arc;
use tokio::sync::mpsc::Sender;
use tokio::sync::Mutex;
pub struct FileEvent {
pub inotifyevent: InotifyEvent,
pub date: DateTime<Local>,
}
impl std::fmt::Debug for FileEvent {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{ie:?}", ie = self.inotifyevent)
}
}
async fn send_to_ipbl_zmq(reqsocket: &zmq::Socket, ip: &mut IpData) {
let msg = format!("{value}", value = serde_json::to_string(&ip).unwrap());
match reqsocket.send(&msg, 0) {
Ok(_) => {}
Err(e) => {
println!("{e:?}")
}
};
match reqsocket.recv_string(0) {
Ok(o) => match o {
Ok(_) => {}
Err(ee) => {
println!("{ee:?}")
}
},
Err(e) => {
println!("{e:?}")
}
};
}
async fn send_to_ipbl_ws(ctx: &Context, ip: &IpData, ret: &mut Vec<String>) {
ret.push(format!("host: {hostname}", hostname = ctx.hostname));
loop {
match push_ip(&ctx, &ip, ret).await {
Ok(_) => {
break;
}
Err(err) => {
println!("{err}");
sleep(1);
}
};
}
}
async fn listenpubsub(ctx: &Arc<Mutex<Context>>, txpubsub: Sender<IpData>, socket: zmq::Socket) {
let ctx = ctx.lock().await;
let prefix = format!(
"{subscription} ",
subscription = ctx.cfg.zmq.get("pubsub").unwrap().subscription
);
socket
.set_subscribe(ctx.cfg.zmq.get("pubsub").unwrap().subscription.as_bytes())
.expect("failed setting subscription");
drop(ctx);
tokio::spawn(async move {
loop {
let msgs: Option<String> = match socket.recv_string(0) {
Ok(s) => match s {
Ok(ss) => Some(ss),
Err(e) => {
println!("{e:?}");
None
}
},
Err(e) => {
println!("{e:?}");
None
}
};
match msgs {
Some(ss) => {
let msg = ss.strip_prefix(prefix.as_str()).unwrap();
let tosend: IpData = serde_json::from_str(msg).unwrap();
if tosend.hostname != gethostname(true) {
txpubsub.send(tosend).await.unwrap();
}
}
None => {}
};
}
});
}

View File

@ -1,17 +1,12 @@
mod config; mod config;
mod firewall; mod fw;
mod ip; mod ip;
mod ipblc; mod ipblc;
mod utils; mod utils;
mod zmqcom; mod zmqcom;
use config::Context;
use std::sync::Arc;
use tokio::sync::Mutex;
#[tokio::main] #[tokio::main]
pub async fn main() { pub async fn main() {
// Create a new context // Create a new context
let ctx = Arc::new(Mutex::new(Context::new().await)); ipblc::run().await;
ipblc::inc::process(&ctx).await;
} }

View File

@ -1,4 +1,3 @@
use ipnet::IpNet;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use nix::unistd; use nix::unistd;
use regex::Regex; use regex::Regex;
@ -34,21 +33,12 @@ pub fn _dedup<T: Ord + PartialOrd>(list: &mut Vec<T>) -> usize {
list.len() list.len()
} }
pub fn build_trustnets(cfgtrustnets: &Vec<String>) -> Vec<IpNet> { pub fn _sleep_ms(ms: u64) {
let mut trustnets: Vec<IpNet> = vec![]; std::thread::sleep(Duration::from_millis(ms));
for trustnet in cfgtrustnets {
match trustnet.parse() {
Ok(net) => trustnets.push(net),
Err(err) => {
println!("error parsing {trustnet}, error: {err}");
}
};
}
trustnets
} }
pub fn sleep(seconds: u64) { pub fn sleep_s(s: u64) {
std::thread::sleep(Duration::from_secs(seconds)); std::thread::sleep(Duration::from_secs(s));
} }
pub fn gethostname(show_fqdn: bool) -> String { pub fn gethostname(show_fqdn: bool) -> String {

View File

@ -1,13 +1,11 @@
use crate::config::ZMQ; use crate::config::ZMQ;
use zmq;
const ZMQPROTO: &str = "tcp"; const ZMQPROTO: &str = "tcp";
pub async fn zconnect(zmqcfg: &ZMQ, zmqtype: zmq::SocketType) -> Result<zmq::Socket, zmq::Error> { pub async fn zconnect(zmqcfg: &ZMQ, zmqtype: zmq::SocketType) -> Result<zmq::Socket, zmq::Error> {
let zctx = zmq::Context::new(); let zctx = zmq::Context::new();
let zmqhost = &zmqcfg.hostname; let zmqhost = &zmqcfg.hostname;
let zmqport = zmqcfg.port; let zmqport = &zmqcfg.port;
let socket = zctx.socket(zmqtype).unwrap(); let socket = zctx.socket(zmqtype).unwrap();
let connectstring = format!("{ZMQPROTO}://{zmqhost}:{zmqport}"); let connectstring = format!("{ZMQPROTO}://{zmqhost}:{zmqport}");
socket.connect(&connectstring.as_str())?; socket.connect(&connectstring.as_str())?;

View File

@ -1,4 +1,3 @@
use ipnet::Ipv4Net;
use nftnl::{nft_set, set::Set, Batch, FinalizedBatch, ProtoFamily, Table}; use nftnl::{nft_set, set::Set, Batch, FinalizedBatch, ProtoFamily, Table};
use std::{ffi::CString, io::*, net::Ipv4Addr}; use std::{ffi::CString, io::*, net::Ipv4Addr};