├── .clog.toml ├── .github ├── FUNDING.yml └── workflows │ ├── ci.yml │ ├── lint.yml │ ├── release.yml │ ├── release_nightly.yml │ └── security_audit.yml ├── .gitignore ├── CHANGELOG.md ├── Cargo.lock ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── build.rs ├── rustfmt.toml └── src ├── cli.rs ├── error.rs ├── iptables.rs ├── iptables ├── chain.rs ├── counter.rs ├── metrics.rs ├── rule.rs └── table.rs ├── macros.rs ├── main.rs └── parse.rs /.clog.toml: -------------------------------------------------------------------------------- 1 | [clog] 2 | repository = "https://github.com/kbknapp/iptables_exporter" 3 | subtitle = "iptables_exporter Release" 4 | 5 | [sections] 6 | Documentation = ["docs", "doc"] 7 | Maintenance = ["maint"] 8 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: kbknapp 4 | patreon: kbknapp 5 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | --- 2 | on: 3 | push: 4 | branches: main 5 | pull_request: 6 | paths: 7 | - src/** 8 | - build.rs 9 | - Cargo.toml 10 | - Cargo.lock 11 | 12 | name: Continuous Integration 13 | 14 | jobs: 15 | ci: 16 | runs-on: ubuntu-latest 17 | strategy: 18 | matrix: 19 | rust: 20 | - stable 21 | - nightly 22 | - 1.74.1 # MSRV 23 | 24 | steps: 25 | - uses: actions/checkout@v2 26 | 27 | - uses: actions-rs/toolchain@v1 28 | with: 29 | profile: minimal 30 | toolchain: ${{ matrix.rust }} 31 | override: true 32 | 33 | - name: Install cc 34 | run: sudo apt-get update && sudo apt-get install --yes gcc 35 | 36 | - uses: actions-rs/cargo@v1 37 | with: 38 | command: build 39 | 40 | - uses: actions-rs/cargo@v1 41 | with: 42 | command: test 43 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | --- 2 | on: 3 | pull_request: 4 | paths: 5 | - src/**/*.rs 6 | - build.rs 7 | 8 | name: PR Lints 9 | jobs: 10 | lints: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v2 14 | 15 | - uses: actions-rs/toolchain@v1 16 | with: 17 | profile: minimal 18 | toolchain: nightly 19 | override: true 20 | components: clippy, rustfmt 21 | 22 | - uses: actions-rs/clippy-check@v1 23 | with: 24 | token: ${{ secrets.GITHUB_TOKEN }} 25 | args: --all-features 26 | 27 | - uses: actions-rs/cargo@v1 28 | with: 29 | command: fmt 30 | args: --all -- --check 31 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | --- 2 | on: 3 | push: 4 | tags: 5 | - 'v*.*.*' 6 | 7 | name: Create Release 8 | 9 | env: 10 | RELEASE_BIN: iptables_exporter 11 | RELEASE_ADDS: >- 12 | README.md 13 | LICENSE-MIT 14 | LICENSE-APACHE 15 | CHANGELOG.md 16 | 17 | jobs: 18 | release: 19 | name: Release 20 | 21 | runs-on: ubuntu-latest 22 | 23 | steps: 24 | - uses: actions/checkout@v2 25 | - uses: actions-rs/toolchain@v1 26 | with: 27 | profile: minimal 28 | toolchain: stable 29 | override: true 30 | target: x86_64-unknown-linux-musl 31 | 32 | - name: Get the version 33 | id: get_version 34 | run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//} 35 | 36 | - name: Install cc 37 | run: sudo apt-get update && sudo apt-get install --yes gcc 38 | 39 | - uses: actions-rs/cargo@v1 40 | with: 41 | command: build 42 | args: --release --target x86_64-unknown-linux-musl 43 | 44 | - name: Make artifacts dir 45 | run: mkdir -p artifacts/ 46 | 47 | - name: Copy all artifacts into dir 48 | run: cp target/x86_64-unknown-linux-musl/release/${{ env.RELEASE_BIN }} ${{ env.RELEASE_ADDS }} artifacts/ 49 | 50 | - name: Create archive for Linux 51 | run: cd artifacts/ && tar czf ../${{ env.RELEASE_BIN }}-${{ steps.get_version.outputs.VERSION }}-x86_64-linux-musl.tar.gz ./* 52 | 53 | - name: Release 54 | uses: softprops/action-gh-release@v1 55 | with: 56 | body_path: CHANGELOG.md 57 | files: | 58 | ${{ env.RELEASE_BIN }}-${{ steps.get_version.outputs.VERSION }}-x86_64-linux-musl.tar.gz 59 | env: 60 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 61 | GITHUB_REPOSITORY: kbknapp/iptables_exporter 62 | -------------------------------------------------------------------------------- /.github/workflows/release_nightly.yml: -------------------------------------------------------------------------------- 1 | --- 2 | on: 3 | push: 4 | branches: main 5 | 6 | name: Nightly Release 7 | 8 | env: 9 | RELEASE_BIN: iptables_exporter 10 | RELEASE_ADDS: >- 11 | LICENSE-APACHE 12 | LICENSE-MIT 13 | nightly-CHANGELOG.md 14 | README.md 15 | 16 | jobs: 17 | nightly-release: 18 | name: Nightly Release 19 | 20 | runs-on: ubuntu-latest 21 | 22 | steps: 23 | - uses: actions/checkout@v2 24 | - uses: actions-rs/toolchain@v1 25 | with: 26 | profile: minimal 27 | toolchain: nightly 28 | override: true 29 | target: x86_64-unknown-linux-musl 30 | 31 | - name: Install cc 32 | run: sudo apt-get update && sudo apt-get install --yes gcc 33 | 34 | - name: Compile 35 | uses: actions-rs/cargo@v1 36 | with: 37 | command: build 38 | args: --release --target x86_64-unknown-linux-musl 39 | 40 | - name: Install CLOG 41 | uses: actions-rs/cargo@v1 42 | with: 43 | command: install 44 | args: clog-cli 45 | 46 | - name: Generate Changelog 47 | run: clog -F -o nightly-CHANGELOG.md -i /dev/null 48 | 49 | - name: Make artifacts dir 50 | run: mkdir -p artifacts/ 51 | 52 | - name: Copy all artifacts into dir 53 | run: cp target/x86_64-unknown-linux-musl/release/${{ env.RELEASE_BIN }} ${{ env.RELEASE_ADDS }} artifacts/ 54 | 55 | - uses: benjlevesque/short-sha@v1.2 56 | id: short-sha 57 | 58 | - name: Create archive for Linux 59 | run: cd artifacts/ && tar czf ../${{ env.RELEASE_BIN }}-${{ env.SHA }}-x86_64-linux-musl.tar.gz ./* 60 | env: 61 | SHA: ${{ steps.short-sha.outputs.sha }} 62 | 63 | - name: Remove previous Nightly Release 64 | uses: dev-drprasad/delete-tag-and-release@v1.0.1 65 | with: 66 | delete_release: true 67 | tag_name: nightly 68 | repo: kbknapp/iptables_exporter 69 | env: 70 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 71 | 72 | - name: Create Nightly Release 73 | uses: softprops/action-gh-release@v1 74 | with: 75 | name: iptables_exporter Nightly (${{ env.SHA }}) 76 | tag_name: nightly 77 | prerelease: true 78 | body_path: nightly-CHANGELOG.md 79 | files: | 80 | ${{ env.RELEASE_BIN }}-${{ env.SHA }}-x86_64-linux-musl.tar.gz 81 | env: 82 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 83 | GITHUB_REPOSITORY: kbknapp/iptables_exporter 84 | SHA: ${{ steps.short-sha.outputs.sha }} 85 | -------------------------------------------------------------------------------- /.github/workflows/security_audit.yml: -------------------------------------------------------------------------------- 1 | --- 2 | on: 3 | push: 4 | paths: 5 | - '**/Cargo.toml' 6 | - '**/Cargo.lock' 7 | 8 | name: Security audit 9 | 10 | jobs: 11 | security_audit: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v1 15 | - uses: actions-rs/audit-check@v1 16 | with: 17 | token: ${{ secrets.GITHUB_TOKEN }} 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled files 2 | *.o 3 | *.so 4 | *.rlib 5 | *.dll 6 | 7 | # Executables 8 | *.exe 9 | 10 | # Generated by Cargo 11 | target/ 12 | 13 | # Temp files 14 | .*~ 15 | 16 | # Backup files 17 | *.bak 18 | *.bk 19 | *.orig 20 | 21 | # Project files 22 | .vscode/* 23 | .idea/* 24 | 25 | # ctags 26 | **/*.vi 27 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | ## v0.4.0 iptables_exporter Release (2024-03-29) 3 | 4 | #### Maintenance 5 | 6 | * bump MSRV to 1.74.1 ([f1761c6e](https://github.com/kbknapp/iptables_exporter/commit/f1761c6edae3f79e630ff2eda132ba64d3ac49c0)) 7 | * update deps to fix compiles ([29c0e7d7](https://github.com/kbknapp/iptables_exporter/commit/29c0e7d75b69eda9d83f996f7cb7978a343eb410)) 8 | 9 | 10 | ## 0.3.0 Initial Release (2023-02-07) 11 | 12 | ## Features 13 | 14 | * Add iptables rule comment metrics ([#8](https://github.com/kbknapp/iptables_exporter/pulls/8)) 15 | 16 | 17 | ## 0.2.0 Initial Release (2022-11-30) 18 | 19 | ### Features 20 | 21 | * Add support for iptables-legacy 22 | * add new --scrape-target/-t flag ([ffe390e](https://github.com/kbknapp/iptables_exporter/commit/ffe390e )) 23 | * add support for multiple scrape targets ([68bcd25](https://github.com/kbknapp/iptables_exporter/commit/68bcd25 ), [16197d2](https://github.com/kbknapp/iptables_exporter/commit/16197d2)) 24 | 25 | ### CI/Maintenance 26 | 27 | * update MSRV ([33f97f7](https://github.com/kbknapp/iptables_exporter/commit/33f97f7 )) 28 | * add rustfmt and run cargo fmt ([14851d7](https://github.com/kbknapp/iptables_exporter/commit/14851d7 )) 29 | * clippy fixes ([2859393](https://github.com/kbknapp/iptables_exporter/commit/2859393 )) 30 | * update clap syntax ([25edebd](https://github.com/kbknapp/iptables_exporter/commit/25edebd )) 31 | * update deps ([2a3fc2d](https://github.com/kbknapp/iptables_exporter/commit/2a3fc2d )) 32 | 33 | 34 | ## 0.1.1 (2021-05-11) 35 | 36 | ### Fixes 37 | 38 | * fix typo in metric name (scape->scrape) ([7c72305](https://github.com/kbknapp/iptables_exporter/commit/7c72305)) 39 | 40 | ### Docs 41 | 42 | * fixes typos in readme ([70975fe](https://github.com/kbknapp/iptables_exporter/commit/70975fe )) 43 | * adds releases page to installation ([b23b649](https://github.com/kbknapp/iptables_exporter/commit/b23b649 )) 44 | 45 | ### CI/Maintenance 46 | 47 | * Uses cross compilation to musl based libc in CI releases ([c6ebfd1](https://github.com/kbknapp/iptables_exporter/commit/c6ebfd1 )) 48 | * adds a step to remove previous nightly release in CI ([3788778 ](https://github.com/kbknapp/iptables_exporter/commit/3788778 )) 49 | 50 | 51 | ## 0.1.0 Initial Release (2021-04-30) 52 | 53 | * Initial Release 54 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "addr2line" 7 | version = "0.21.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" 10 | dependencies = [ 11 | "gimli", 12 | ] 13 | 14 | [[package]] 15 | name = "adler" 16 | version = "1.0.2" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" 19 | 20 | [[package]] 21 | name = "aho-corasick" 22 | version = "1.1.3" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" 25 | dependencies = [ 26 | "memchr", 27 | ] 28 | 29 | [[package]] 30 | name = "anstream" 31 | version = "0.6.13" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" 34 | dependencies = [ 35 | "anstyle", 36 | "anstyle-parse", 37 | "anstyle-query", 38 | "anstyle-wincon", 39 | "colorchoice", 40 | "utf8parse", 41 | ] 42 | 43 | [[package]] 44 | name = "anstyle" 45 | version = "1.0.6" 46 | source = "registry+https://github.com/rust-lang/crates.io-index" 47 | checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" 48 | 49 | [[package]] 50 | name = "anstyle-parse" 51 | version = "0.2.3" 52 | source = "registry+https://github.com/rust-lang/crates.io-index" 53 | checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" 54 | dependencies = [ 55 | "utf8parse", 56 | ] 57 | 58 | [[package]] 59 | name = "anstyle-query" 60 | version = "1.0.2" 61 | source = "registry+https://github.com/rust-lang/crates.io-index" 62 | checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" 63 | dependencies = [ 64 | "windows-sys 0.52.0", 65 | ] 66 | 67 | [[package]] 68 | name = "anstyle-wincon" 69 | version = "3.0.2" 70 | source = "registry+https://github.com/rust-lang/crates.io-index" 71 | checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" 72 | dependencies = [ 73 | "anstyle", 74 | "windows-sys 0.52.0", 75 | ] 76 | 77 | [[package]] 78 | name = "anyhow" 79 | version = "1.0.81" 80 | source = "registry+https://github.com/rust-lang/crates.io-index" 81 | checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" 82 | 83 | [[package]] 84 | name = "autocfg" 85 | version = "1.2.0" 86 | source = "registry+https://github.com/rust-lang/crates.io-index" 87 | checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" 88 | 89 | [[package]] 90 | name = "backtrace" 91 | version = "0.3.71" 92 | source = "registry+https://github.com/rust-lang/crates.io-index" 93 | checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" 94 | dependencies = [ 95 | "addr2line", 96 | "cc", 97 | "cfg-if", 98 | "libc", 99 | "miniz_oxide", 100 | "object", 101 | "rustc-demangle", 102 | ] 103 | 104 | [[package]] 105 | name = "bitflags" 106 | version = "1.3.2" 107 | source = "registry+https://github.com/rust-lang/crates.io-index" 108 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 109 | 110 | [[package]] 111 | name = "bitflags" 112 | version = "2.5.0" 113 | source = "registry+https://github.com/rust-lang/crates.io-index" 114 | checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" 115 | 116 | [[package]] 117 | name = "bytes" 118 | version = "1.6.0" 119 | source = "registry+https://github.com/rust-lang/crates.io-index" 120 | checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" 121 | 122 | [[package]] 123 | name = "cc" 124 | version = "1.0.90" 125 | source = "registry+https://github.com/rust-lang/crates.io-index" 126 | checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" 127 | 128 | [[package]] 129 | name = "cfg-if" 130 | version = "1.0.0" 131 | source = "registry+https://github.com/rust-lang/crates.io-index" 132 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 133 | 134 | [[package]] 135 | name = "clap" 136 | version = "4.5.4" 137 | source = "registry+https://github.com/rust-lang/crates.io-index" 138 | checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" 139 | dependencies = [ 140 | "clap_builder", 141 | "clap_derive", 142 | ] 143 | 144 | [[package]] 145 | name = "clap_builder" 146 | version = "4.5.2" 147 | source = "registry+https://github.com/rust-lang/crates.io-index" 148 | checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" 149 | dependencies = [ 150 | "anstream", 151 | "anstyle", 152 | "clap_lex", 153 | "strsim", 154 | "terminal_size", 155 | ] 156 | 157 | [[package]] 158 | name = "clap_derive" 159 | version = "4.5.4" 160 | source = "registry+https://github.com/rust-lang/crates.io-index" 161 | checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" 162 | dependencies = [ 163 | "heck 0.5.0", 164 | "proc-macro2", 165 | "quote", 166 | "syn 2.0.55", 167 | ] 168 | 169 | [[package]] 170 | name = "clap_lex" 171 | version = "0.7.0" 172 | source = "registry+https://github.com/rust-lang/crates.io-index" 173 | checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" 174 | 175 | [[package]] 176 | name = "colorchoice" 177 | version = "1.0.0" 178 | source = "registry+https://github.com/rust-lang/crates.io-index" 179 | checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" 180 | 181 | [[package]] 182 | name = "errno" 183 | version = "0.3.8" 184 | source = "registry+https://github.com/rust-lang/crates.io-index" 185 | checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" 186 | dependencies = [ 187 | "libc", 188 | "windows-sys 0.52.0", 189 | ] 190 | 191 | [[package]] 192 | name = "fnv" 193 | version = "1.0.7" 194 | source = "registry+https://github.com/rust-lang/crates.io-index" 195 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 196 | 197 | [[package]] 198 | name = "futures-channel" 199 | version = "0.3.30" 200 | source = "registry+https://github.com/rust-lang/crates.io-index" 201 | checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" 202 | dependencies = [ 203 | "futures-core", 204 | ] 205 | 206 | [[package]] 207 | name = "futures-core" 208 | version = "0.3.30" 209 | source = "registry+https://github.com/rust-lang/crates.io-index" 210 | checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" 211 | 212 | [[package]] 213 | name = "futures-task" 214 | version = "0.3.30" 215 | source = "registry+https://github.com/rust-lang/crates.io-index" 216 | checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" 217 | 218 | [[package]] 219 | name = "futures-util" 220 | version = "0.3.30" 221 | source = "registry+https://github.com/rust-lang/crates.io-index" 222 | checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" 223 | dependencies = [ 224 | "futures-core", 225 | "futures-task", 226 | "pin-project-lite", 227 | "pin-utils", 228 | ] 229 | 230 | [[package]] 231 | name = "gimli" 232 | version = "0.28.1" 233 | source = "registry+https://github.com/rust-lang/crates.io-index" 234 | checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" 235 | 236 | [[package]] 237 | name = "heck" 238 | version = "0.4.1" 239 | source = "registry+https://github.com/rust-lang/crates.io-index" 240 | checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" 241 | 242 | [[package]] 243 | name = "heck" 244 | version = "0.5.0" 245 | source = "registry+https://github.com/rust-lang/crates.io-index" 246 | checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" 247 | 248 | [[package]] 249 | name = "hermit-abi" 250 | version = "0.3.9" 251 | source = "registry+https://github.com/rust-lang/crates.io-index" 252 | checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" 253 | 254 | [[package]] 255 | name = "http" 256 | version = "0.2.12" 257 | source = "registry+https://github.com/rust-lang/crates.io-index" 258 | checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" 259 | dependencies = [ 260 | "bytes", 261 | "fnv", 262 | "itoa", 263 | ] 264 | 265 | [[package]] 266 | name = "http-body" 267 | version = "0.4.6" 268 | source = "registry+https://github.com/rust-lang/crates.io-index" 269 | checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" 270 | dependencies = [ 271 | "bytes", 272 | "http", 273 | "pin-project-lite", 274 | ] 275 | 276 | [[package]] 277 | name = "httparse" 278 | version = "1.8.0" 279 | source = "registry+https://github.com/rust-lang/crates.io-index" 280 | checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" 281 | 282 | [[package]] 283 | name = "httpdate" 284 | version = "1.0.3" 285 | source = "registry+https://github.com/rust-lang/crates.io-index" 286 | checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" 287 | 288 | [[package]] 289 | name = "hyper" 290 | version = "0.14.28" 291 | source = "registry+https://github.com/rust-lang/crates.io-index" 292 | checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" 293 | dependencies = [ 294 | "bytes", 295 | "futures-channel", 296 | "futures-core", 297 | "futures-util", 298 | "http", 299 | "http-body", 300 | "httparse", 301 | "httpdate", 302 | "itoa", 303 | "pin-project-lite", 304 | "socket2", 305 | "tokio", 306 | "tower-service", 307 | "tracing", 308 | "want", 309 | ] 310 | 311 | [[package]] 312 | name = "iptables_exporter" 313 | version = "0.4.0" 314 | dependencies = [ 315 | "anyhow", 316 | "clap", 317 | "once_cell", 318 | "prometheus", 319 | "prometheus-hyper", 320 | "regex", 321 | "strum", 322 | "thiserror", 323 | "tokio", 324 | "tracing", 325 | "tracing-subscriber", 326 | ] 327 | 328 | [[package]] 329 | name = "itoa" 330 | version = "1.0.11" 331 | source = "registry+https://github.com/rust-lang/crates.io-index" 332 | checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" 333 | 334 | [[package]] 335 | name = "lazy_static" 336 | version = "1.4.0" 337 | source = "registry+https://github.com/rust-lang/crates.io-index" 338 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 339 | 340 | [[package]] 341 | name = "libc" 342 | version = "0.2.153" 343 | source = "registry+https://github.com/rust-lang/crates.io-index" 344 | checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" 345 | 346 | [[package]] 347 | name = "linux-raw-sys" 348 | version = "0.4.13" 349 | source = "registry+https://github.com/rust-lang/crates.io-index" 350 | checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" 351 | 352 | [[package]] 353 | name = "lock_api" 354 | version = "0.4.11" 355 | source = "registry+https://github.com/rust-lang/crates.io-index" 356 | checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" 357 | dependencies = [ 358 | "autocfg", 359 | "scopeguard", 360 | ] 361 | 362 | [[package]] 363 | name = "log" 364 | version = "0.4.21" 365 | source = "registry+https://github.com/rust-lang/crates.io-index" 366 | checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" 367 | 368 | [[package]] 369 | name = "memchr" 370 | version = "2.7.2" 371 | source = "registry+https://github.com/rust-lang/crates.io-index" 372 | checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" 373 | 374 | [[package]] 375 | name = "miniz_oxide" 376 | version = "0.7.2" 377 | source = "registry+https://github.com/rust-lang/crates.io-index" 378 | checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" 379 | dependencies = [ 380 | "adler", 381 | ] 382 | 383 | [[package]] 384 | name = "mio" 385 | version = "0.8.11" 386 | source = "registry+https://github.com/rust-lang/crates.io-index" 387 | checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" 388 | dependencies = [ 389 | "libc", 390 | "wasi", 391 | "windows-sys 0.48.0", 392 | ] 393 | 394 | [[package]] 395 | name = "nu-ansi-term" 396 | version = "0.46.0" 397 | source = "registry+https://github.com/rust-lang/crates.io-index" 398 | checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" 399 | dependencies = [ 400 | "overload", 401 | "winapi", 402 | ] 403 | 404 | [[package]] 405 | name = "num_cpus" 406 | version = "1.16.0" 407 | source = "registry+https://github.com/rust-lang/crates.io-index" 408 | checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" 409 | dependencies = [ 410 | "hermit-abi", 411 | "libc", 412 | ] 413 | 414 | [[package]] 415 | name = "object" 416 | version = "0.32.2" 417 | source = "registry+https://github.com/rust-lang/crates.io-index" 418 | checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" 419 | dependencies = [ 420 | "memchr", 421 | ] 422 | 423 | [[package]] 424 | name = "once_cell" 425 | version = "1.19.0" 426 | source = "registry+https://github.com/rust-lang/crates.io-index" 427 | checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" 428 | 429 | [[package]] 430 | name = "overload" 431 | version = "0.1.1" 432 | source = "registry+https://github.com/rust-lang/crates.io-index" 433 | checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" 434 | 435 | [[package]] 436 | name = "parking_lot" 437 | version = "0.12.1" 438 | source = "registry+https://github.com/rust-lang/crates.io-index" 439 | checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" 440 | dependencies = [ 441 | "lock_api", 442 | "parking_lot_core", 443 | ] 444 | 445 | [[package]] 446 | name = "parking_lot_core" 447 | version = "0.9.9" 448 | source = "registry+https://github.com/rust-lang/crates.io-index" 449 | checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" 450 | dependencies = [ 451 | "cfg-if", 452 | "libc", 453 | "redox_syscall", 454 | "smallvec", 455 | "windows-targets 0.48.5", 456 | ] 457 | 458 | [[package]] 459 | name = "pin-project-lite" 460 | version = "0.2.13" 461 | source = "registry+https://github.com/rust-lang/crates.io-index" 462 | checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" 463 | 464 | [[package]] 465 | name = "pin-utils" 466 | version = "0.1.0" 467 | source = "registry+https://github.com/rust-lang/crates.io-index" 468 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 469 | 470 | [[package]] 471 | name = "proc-macro2" 472 | version = "1.0.79" 473 | source = "registry+https://github.com/rust-lang/crates.io-index" 474 | checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" 475 | dependencies = [ 476 | "unicode-ident", 477 | ] 478 | 479 | [[package]] 480 | name = "prometheus" 481 | version = "0.13.3" 482 | source = "registry+https://github.com/rust-lang/crates.io-index" 483 | checksum = "449811d15fbdf5ceb5c1144416066429cf82316e2ec8ce0c1f6f8a02e7bbcf8c" 484 | dependencies = [ 485 | "cfg-if", 486 | "fnv", 487 | "lazy_static", 488 | "memchr", 489 | "parking_lot", 490 | "protobuf", 491 | "thiserror", 492 | ] 493 | 494 | [[package]] 495 | name = "prometheus-hyper" 496 | version = "0.1.5" 497 | source = "registry+https://github.com/rust-lang/crates.io-index" 498 | checksum = "18fc98d5705a20b11f8b240c0857167b79852ba469f9faec6df0027e576e676e" 499 | dependencies = [ 500 | "hyper", 501 | "prometheus", 502 | "tokio", 503 | "tracing", 504 | ] 505 | 506 | [[package]] 507 | name = "protobuf" 508 | version = "2.28.0" 509 | source = "registry+https://github.com/rust-lang/crates.io-index" 510 | checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" 511 | 512 | [[package]] 513 | name = "quote" 514 | version = "1.0.35" 515 | source = "registry+https://github.com/rust-lang/crates.io-index" 516 | checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" 517 | dependencies = [ 518 | "proc-macro2", 519 | ] 520 | 521 | [[package]] 522 | name = "redox_syscall" 523 | version = "0.4.1" 524 | source = "registry+https://github.com/rust-lang/crates.io-index" 525 | checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" 526 | dependencies = [ 527 | "bitflags 1.3.2", 528 | ] 529 | 530 | [[package]] 531 | name = "regex" 532 | version = "1.10.4" 533 | source = "registry+https://github.com/rust-lang/crates.io-index" 534 | checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" 535 | dependencies = [ 536 | "aho-corasick", 537 | "memchr", 538 | "regex-automata", 539 | "regex-syntax", 540 | ] 541 | 542 | [[package]] 543 | name = "regex-automata" 544 | version = "0.4.6" 545 | source = "registry+https://github.com/rust-lang/crates.io-index" 546 | checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" 547 | dependencies = [ 548 | "aho-corasick", 549 | "memchr", 550 | "regex-syntax", 551 | ] 552 | 553 | [[package]] 554 | name = "regex-syntax" 555 | version = "0.8.3" 556 | source = "registry+https://github.com/rust-lang/crates.io-index" 557 | checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" 558 | 559 | [[package]] 560 | name = "rustc-demangle" 561 | version = "0.1.23" 562 | source = "registry+https://github.com/rust-lang/crates.io-index" 563 | checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" 564 | 565 | [[package]] 566 | name = "rustix" 567 | version = "0.38.32" 568 | source = "registry+https://github.com/rust-lang/crates.io-index" 569 | checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" 570 | dependencies = [ 571 | "bitflags 2.5.0", 572 | "errno", 573 | "libc", 574 | "linux-raw-sys", 575 | "windows-sys 0.52.0", 576 | ] 577 | 578 | [[package]] 579 | name = "rustversion" 580 | version = "1.0.14" 581 | source = "registry+https://github.com/rust-lang/crates.io-index" 582 | checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" 583 | 584 | [[package]] 585 | name = "scopeguard" 586 | version = "1.2.0" 587 | source = "registry+https://github.com/rust-lang/crates.io-index" 588 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 589 | 590 | [[package]] 591 | name = "sharded-slab" 592 | version = "0.1.7" 593 | source = "registry+https://github.com/rust-lang/crates.io-index" 594 | checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" 595 | dependencies = [ 596 | "lazy_static", 597 | ] 598 | 599 | [[package]] 600 | name = "signal-hook-registry" 601 | version = "1.4.1" 602 | source = "registry+https://github.com/rust-lang/crates.io-index" 603 | checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" 604 | dependencies = [ 605 | "libc", 606 | ] 607 | 608 | [[package]] 609 | name = "smallvec" 610 | version = "1.13.2" 611 | source = "registry+https://github.com/rust-lang/crates.io-index" 612 | checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" 613 | 614 | [[package]] 615 | name = "socket2" 616 | version = "0.5.6" 617 | source = "registry+https://github.com/rust-lang/crates.io-index" 618 | checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" 619 | dependencies = [ 620 | "libc", 621 | "windows-sys 0.52.0", 622 | ] 623 | 624 | [[package]] 625 | name = "strsim" 626 | version = "0.11.0" 627 | source = "registry+https://github.com/rust-lang/crates.io-index" 628 | checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" 629 | 630 | [[package]] 631 | name = "strum" 632 | version = "0.24.1" 633 | source = "registry+https://github.com/rust-lang/crates.io-index" 634 | checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" 635 | dependencies = [ 636 | "strum_macros", 637 | ] 638 | 639 | [[package]] 640 | name = "strum_macros" 641 | version = "0.24.3" 642 | source = "registry+https://github.com/rust-lang/crates.io-index" 643 | checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" 644 | dependencies = [ 645 | "heck 0.4.1", 646 | "proc-macro2", 647 | "quote", 648 | "rustversion", 649 | "syn 1.0.109", 650 | ] 651 | 652 | [[package]] 653 | name = "syn" 654 | version = "1.0.109" 655 | source = "registry+https://github.com/rust-lang/crates.io-index" 656 | checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" 657 | dependencies = [ 658 | "proc-macro2", 659 | "quote", 660 | "unicode-ident", 661 | ] 662 | 663 | [[package]] 664 | name = "syn" 665 | version = "2.0.55" 666 | source = "registry+https://github.com/rust-lang/crates.io-index" 667 | checksum = "002a1b3dbf967edfafc32655d0f377ab0bb7b994aa1d32c8cc7e9b8bf3ebb8f0" 668 | dependencies = [ 669 | "proc-macro2", 670 | "quote", 671 | "unicode-ident", 672 | ] 673 | 674 | [[package]] 675 | name = "terminal_size" 676 | version = "0.3.0" 677 | source = "registry+https://github.com/rust-lang/crates.io-index" 678 | checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7" 679 | dependencies = [ 680 | "rustix", 681 | "windows-sys 0.48.0", 682 | ] 683 | 684 | [[package]] 685 | name = "thiserror" 686 | version = "1.0.58" 687 | source = "registry+https://github.com/rust-lang/crates.io-index" 688 | checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" 689 | dependencies = [ 690 | "thiserror-impl", 691 | ] 692 | 693 | [[package]] 694 | name = "thiserror-impl" 695 | version = "1.0.58" 696 | source = "registry+https://github.com/rust-lang/crates.io-index" 697 | checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" 698 | dependencies = [ 699 | "proc-macro2", 700 | "quote", 701 | "syn 2.0.55", 702 | ] 703 | 704 | [[package]] 705 | name = "thread_local" 706 | version = "1.1.8" 707 | source = "registry+https://github.com/rust-lang/crates.io-index" 708 | checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" 709 | dependencies = [ 710 | "cfg-if", 711 | "once_cell", 712 | ] 713 | 714 | [[package]] 715 | name = "tokio" 716 | version = "1.37.0" 717 | source = "registry+https://github.com/rust-lang/crates.io-index" 718 | checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" 719 | dependencies = [ 720 | "backtrace", 721 | "bytes", 722 | "libc", 723 | "mio", 724 | "num_cpus", 725 | "parking_lot", 726 | "pin-project-lite", 727 | "signal-hook-registry", 728 | "socket2", 729 | "tokio-macros", 730 | "windows-sys 0.48.0", 731 | ] 732 | 733 | [[package]] 734 | name = "tokio-macros" 735 | version = "2.2.0" 736 | source = "registry+https://github.com/rust-lang/crates.io-index" 737 | checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" 738 | dependencies = [ 739 | "proc-macro2", 740 | "quote", 741 | "syn 2.0.55", 742 | ] 743 | 744 | [[package]] 745 | name = "tower-service" 746 | version = "0.3.2" 747 | source = "registry+https://github.com/rust-lang/crates.io-index" 748 | checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" 749 | 750 | [[package]] 751 | name = "tracing" 752 | version = "0.1.40" 753 | source = "registry+https://github.com/rust-lang/crates.io-index" 754 | checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" 755 | dependencies = [ 756 | "pin-project-lite", 757 | "tracing-attributes", 758 | "tracing-core", 759 | ] 760 | 761 | [[package]] 762 | name = "tracing-attributes" 763 | version = "0.1.27" 764 | source = "registry+https://github.com/rust-lang/crates.io-index" 765 | checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" 766 | dependencies = [ 767 | "proc-macro2", 768 | "quote", 769 | "syn 2.0.55", 770 | ] 771 | 772 | [[package]] 773 | name = "tracing-core" 774 | version = "0.1.32" 775 | source = "registry+https://github.com/rust-lang/crates.io-index" 776 | checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" 777 | dependencies = [ 778 | "once_cell", 779 | "valuable", 780 | ] 781 | 782 | [[package]] 783 | name = "tracing-log" 784 | version = "0.2.0" 785 | source = "registry+https://github.com/rust-lang/crates.io-index" 786 | checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" 787 | dependencies = [ 788 | "log", 789 | "once_cell", 790 | "tracing-core", 791 | ] 792 | 793 | [[package]] 794 | name = "tracing-subscriber" 795 | version = "0.3.18" 796 | source = "registry+https://github.com/rust-lang/crates.io-index" 797 | checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" 798 | dependencies = [ 799 | "nu-ansi-term", 800 | "sharded-slab", 801 | "smallvec", 802 | "thread_local", 803 | "tracing-core", 804 | "tracing-log", 805 | ] 806 | 807 | [[package]] 808 | name = "try-lock" 809 | version = "0.2.5" 810 | source = "registry+https://github.com/rust-lang/crates.io-index" 811 | checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" 812 | 813 | [[package]] 814 | name = "unicode-ident" 815 | version = "1.0.12" 816 | source = "registry+https://github.com/rust-lang/crates.io-index" 817 | checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" 818 | 819 | [[package]] 820 | name = "utf8parse" 821 | version = "0.2.1" 822 | source = "registry+https://github.com/rust-lang/crates.io-index" 823 | checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" 824 | 825 | [[package]] 826 | name = "valuable" 827 | version = "0.1.0" 828 | source = "registry+https://github.com/rust-lang/crates.io-index" 829 | checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" 830 | 831 | [[package]] 832 | name = "want" 833 | version = "0.3.1" 834 | source = "registry+https://github.com/rust-lang/crates.io-index" 835 | checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" 836 | dependencies = [ 837 | "try-lock", 838 | ] 839 | 840 | [[package]] 841 | name = "wasi" 842 | version = "0.11.0+wasi-snapshot-preview1" 843 | source = "registry+https://github.com/rust-lang/crates.io-index" 844 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 845 | 846 | [[package]] 847 | name = "winapi" 848 | version = "0.3.9" 849 | source = "registry+https://github.com/rust-lang/crates.io-index" 850 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 851 | dependencies = [ 852 | "winapi-i686-pc-windows-gnu", 853 | "winapi-x86_64-pc-windows-gnu", 854 | ] 855 | 856 | [[package]] 857 | name = "winapi-i686-pc-windows-gnu" 858 | version = "0.4.0" 859 | source = "registry+https://github.com/rust-lang/crates.io-index" 860 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 861 | 862 | [[package]] 863 | name = "winapi-x86_64-pc-windows-gnu" 864 | version = "0.4.0" 865 | source = "registry+https://github.com/rust-lang/crates.io-index" 866 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 867 | 868 | [[package]] 869 | name = "windows-sys" 870 | version = "0.48.0" 871 | source = "registry+https://github.com/rust-lang/crates.io-index" 872 | checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" 873 | dependencies = [ 874 | "windows-targets 0.48.5", 875 | ] 876 | 877 | [[package]] 878 | name = "windows-sys" 879 | version = "0.52.0" 880 | source = "registry+https://github.com/rust-lang/crates.io-index" 881 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 882 | dependencies = [ 883 | "windows-targets 0.52.4", 884 | ] 885 | 886 | [[package]] 887 | name = "windows-targets" 888 | version = "0.48.5" 889 | source = "registry+https://github.com/rust-lang/crates.io-index" 890 | checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" 891 | dependencies = [ 892 | "windows_aarch64_gnullvm 0.48.5", 893 | "windows_aarch64_msvc 0.48.5", 894 | "windows_i686_gnu 0.48.5", 895 | "windows_i686_msvc 0.48.5", 896 | "windows_x86_64_gnu 0.48.5", 897 | "windows_x86_64_gnullvm 0.48.5", 898 | "windows_x86_64_msvc 0.48.5", 899 | ] 900 | 901 | [[package]] 902 | name = "windows-targets" 903 | version = "0.52.4" 904 | source = "registry+https://github.com/rust-lang/crates.io-index" 905 | checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" 906 | dependencies = [ 907 | "windows_aarch64_gnullvm 0.52.4", 908 | "windows_aarch64_msvc 0.52.4", 909 | "windows_i686_gnu 0.52.4", 910 | "windows_i686_msvc 0.52.4", 911 | "windows_x86_64_gnu 0.52.4", 912 | "windows_x86_64_gnullvm 0.52.4", 913 | "windows_x86_64_msvc 0.52.4", 914 | ] 915 | 916 | [[package]] 917 | name = "windows_aarch64_gnullvm" 918 | version = "0.48.5" 919 | source = "registry+https://github.com/rust-lang/crates.io-index" 920 | checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" 921 | 922 | [[package]] 923 | name = "windows_aarch64_gnullvm" 924 | version = "0.52.4" 925 | source = "registry+https://github.com/rust-lang/crates.io-index" 926 | checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" 927 | 928 | [[package]] 929 | name = "windows_aarch64_msvc" 930 | version = "0.48.5" 931 | source = "registry+https://github.com/rust-lang/crates.io-index" 932 | checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" 933 | 934 | [[package]] 935 | name = "windows_aarch64_msvc" 936 | version = "0.52.4" 937 | source = "registry+https://github.com/rust-lang/crates.io-index" 938 | checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" 939 | 940 | [[package]] 941 | name = "windows_i686_gnu" 942 | version = "0.48.5" 943 | source = "registry+https://github.com/rust-lang/crates.io-index" 944 | checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" 945 | 946 | [[package]] 947 | name = "windows_i686_gnu" 948 | version = "0.52.4" 949 | source = "registry+https://github.com/rust-lang/crates.io-index" 950 | checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" 951 | 952 | [[package]] 953 | name = "windows_i686_msvc" 954 | version = "0.48.5" 955 | source = "registry+https://github.com/rust-lang/crates.io-index" 956 | checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" 957 | 958 | [[package]] 959 | name = "windows_i686_msvc" 960 | version = "0.52.4" 961 | source = "registry+https://github.com/rust-lang/crates.io-index" 962 | checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" 963 | 964 | [[package]] 965 | name = "windows_x86_64_gnu" 966 | version = "0.48.5" 967 | source = "registry+https://github.com/rust-lang/crates.io-index" 968 | checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" 969 | 970 | [[package]] 971 | name = "windows_x86_64_gnu" 972 | version = "0.52.4" 973 | source = "registry+https://github.com/rust-lang/crates.io-index" 974 | checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" 975 | 976 | [[package]] 977 | name = "windows_x86_64_gnullvm" 978 | version = "0.48.5" 979 | source = "registry+https://github.com/rust-lang/crates.io-index" 980 | checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" 981 | 982 | [[package]] 983 | name = "windows_x86_64_gnullvm" 984 | version = "0.52.4" 985 | source = "registry+https://github.com/rust-lang/crates.io-index" 986 | checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" 987 | 988 | [[package]] 989 | name = "windows_x86_64_msvc" 990 | version = "0.48.5" 991 | source = "registry+https://github.com/rust-lang/crates.io-index" 992 | checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" 993 | 994 | [[package]] 995 | name = "windows_x86_64_msvc" 996 | version = "0.52.4" 997 | source = "registry+https://github.com/rust-lang/crates.io-index" 998 | checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" 999 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "iptables_exporter" 3 | version = "0.4.0" 4 | edition = "2021" 5 | authors = [ 6 | "Kevin K. ", 7 | ] 8 | description = "A Prometheus exporter for iptables" 9 | repository = "https://github.com/kbknapp/iptables_exporter" 10 | keywords = [ 11 | "prometheus", 12 | "iptables", 13 | "exporter", 14 | "prometheus_exporter", 15 | ] 16 | categories = ["command-line-utilities"] 17 | license = "MIT OR Apache-2.0" 18 | readme = "README.md" 19 | rust-version = "1.74.1" # MSRV 20 | 21 | [badges] 22 | is-it-maintained-issue-resolution = { repository = "kbknapp/iptables_exporter" } 23 | is-it-maintained-open-issues = { repository = "kbknapp/iptables_exporter" } 24 | maintenance = {status = "actively-developed"} 25 | 26 | [dependencies] 27 | anyhow = "1.0.40" 28 | clap = {version= "4.0.0", features = ["derive", "cargo", "wrap_help"]} 29 | once_cell = "1.17.0" 30 | prometheus = "0.13.3" 31 | prometheus-hyper = "0.1.2" 32 | regex = "1.7.1" 33 | strum = { version = "0.24.1", features = ["derive"] } 34 | thiserror = "1.0.24" 35 | tokio = { version = "1.5.0", features = ["full"] } 36 | tracing = "0.1.25" 37 | tracing-subscriber = "0.3.16" 38 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015-2016 Kevin B. Knapp 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # `iptables_exporter` 2 | 3 | 4 | An asynchronous Prometheus exporter for `iptables` 5 | 6 | `iptables_exporter` runs one of several backend "scrape targets" such as 7 | `iptables-save --counter` and scrapes the output to build Prometheus metrics. 8 | Because these scrape targets require `root` privileges, this tool must be run as 9 | `root` (or via `sudo`) or with the following capabilities in both the ambient 10 | and bounding set: 11 | 12 | - CAP_DAC_READ_SEARCH 13 | - CAP_NET_ADMIN 14 | - CAP_NET_RAW 15 | 16 | # Metrics Provided 17 | 18 | - Total number of bytes per chain/table/policy 19 | - Total number of bytes matched per rule/chain/table 20 | - Total number of packets per chain/table/policy 21 | - Total number of packets matched per rule/chain/table 22 | - Total number of rules per chain/table 23 | - Total number of chains per table 24 | - Scrape duration in milliseconds 25 | - Scrape success 26 | 27 | # Scrape Targets Supported 28 | 29 | - `iptables-save` 30 | - `ip6tables-save` 31 | - `iptables-legacy-save` 32 | - `ip6tables-legacy-save` 33 | 34 | Multiple scrape targets can be enabled at once by using the 35 | `-t|--scrape-targets` flag multiple times. Such as: 36 | 37 | ``` 38 | $ iptables_exporter -t iptables -t iptables-legacy -t ip6tables 39 | ``` 40 | 41 | By default only `iptables` is enabled. 42 | 43 | The metrics provided will be prefixed with the various scrape targets, such as 44 | `iptables_*`, `iptables_legacy_*`, etc. 45 | 46 | # Installation 47 | 48 | `iptables_exporter` is a single binary that must be placed somewhere in your 49 | `$PATH`. One can either download 64-bit Linux binaries from [the Release Page](https://github.com/kbknapp/iptables_exporter/releases) 50 | or one can also compile from source. 51 | 52 | ## Compile from Source 53 | 54 | Ensure you have a [Rust toolchain installed](https://rustup.rs). Some of the 55 | dependencies also require `gcc` to be installed. 56 | 57 | ``` 58 | $ git clone https://github.com/kbknapp/iptables_exporter 59 | $ cd iptables_exporter 60 | $ cargo build --release 61 | $ sudo cp target/release/iptables_exporter /usr/local/bin/ 62 | ``` 63 | 64 | # Usage 65 | 66 | ## Command Line Interface 67 | 68 | ``` 69 | Usage: iptables_exporter [OPTIONS] 70 | 71 | Options: 72 | --collect-interval 73 | How often metrics are gathered 74 | 75 | [default: 5] 76 | 77 | -p, --listen-port 78 | The listen port for scraping metrics 79 | 80 | [default: 9455] 81 | 82 | -l, --listen-address 83 | The listen address scraping metrics 84 | 85 | [default: 0.0.0.0] 86 | 87 | -t, --scrape-targets 88 | Which backends to scrape for metrics, multiple targets can be enabled at 89 | once by using this flag multiple times 90 | 91 | [default: iptables] 92 | [aliases: scrape-target] 93 | 94 | Possible values: 95 | - iptables: enable 'iptables-save' for metrics 96 | - ip6tables: enable 'ip6tables-save' for metrics 97 | - iptables-legacy: enable 'iptables-legacy-save' for metrics 98 | - ip6tables-legacy: enable 'ip6tables-legacy-save' for metrics 99 | 100 | -v, --verbose... 101 | Show verbose output at a level or higher. -v: DEBUG, -vv: TRACE 102 | 103 | -q, --quiet... 104 | Supress output at a level or lower. -q: INFO, -qq: WARN, -qqq: ERROR (i.e. 105 | everything) 106 | 107 | -h, --help 108 | Print help information (use `-h` for a summary) 109 | 110 | -V, --version 111 | Print version information 112 | ``` 113 | 114 | To run with the default options, and the binary is installed somewhere in your 115 | `$PATH`: 116 | 117 | ``` 118 | $ sudo iptables_exporter 119 | ``` 120 | 121 | # Prometheus Configuration 122 | 123 | You can add the following scrape configs to Prometheus: 124 | 125 | ```yaml 126 | scrape_configs: 127 | - job_name: 'iptables' 128 | static_configs: 129 | - targets: 130 | - 'localhost:9455' 131 | - 'other_host:9455' 132 | 133 | relabel_configs: 134 | - source_labels: [ '__address__' ] 135 | regex: '(.*):\d+' 136 | target_label: instance 137 | ``` 138 | 139 | # Example Metrics 140 | 141 | ``` 142 | # HELP iptables_chain_bytes_total Total bytes flowing through a given chain 143 | # TYPE iptables_chain_bytes_total counter 144 | iptables_chain_bytes_total{chain="DOCKER",policy="ACCEPT",table="filter"} 0 145 | iptables_chain_bytes_total{chain="DOCKER",policy="ACCEPT",table="nat"} 0 146 | iptables_chain_bytes_total{chain="DOCKER-ISOLATION-STAGE-1",policy="ACCEPT",table="filter"} 0 147 | iptables_chain_bytes_total{chain="DOCKER-ISOLATION-STAGE-2",policy="ACCEPT",table="filter"} 0 148 | iptables_chain_bytes_total{chain="DOCKER-USER",policy="ACCEPT",table="filter"} 0 149 | iptables_chain_bytes_total{chain="FORWARD",policy="ACCEPT",table="filter"} 0 150 | iptables_chain_bytes_total{chain="INPUT",policy="ACCEPT",table="filter"} 98893683 151 | iptables_chain_bytes_total{chain="INPUT",policy="ACCEPT",table="nat"} 0 152 | iptables_chain_bytes_total{chain="OUTPUT",policy="ACCEPT",table="filter"} 196455 153 | iptables_chain_bytes_total{chain="OUTPUT",policy="ACCEPT",table="nat"} 0 154 | iptables_chain_bytes_total{chain="POSTROUTING",policy="ACCEPT",table="nat"} 0 155 | iptables_chain_bytes_total{chain="PREROUTING",policy="ACCEPT",table="nat"} 0 156 | iptables_chain_bytes_total{chain="ts-forward",policy="ACCEPT",table="filter"} 0 157 | iptables_chain_bytes_total{chain="ts-input",policy="ACCEPT",table="filter"} 0 158 | iptables_chain_bytes_total{chain="ts-postrouting",policy="ACCEPT",table="nat"} 0 159 | iptables_chain_bytes_total{chain="ufw-after-forward",policy="ACCEPT",table="filter"} 0 160 | iptables_chain_bytes_total{chain="ufw-after-input",policy="ACCEPT",table="filter"} 0 161 | iptables_chain_bytes_total{chain="ufw-after-logging-forward",policy="ACCEPT",table="filter"} 0 162 | iptables_chain_bytes_total{chain="ufw-after-logging-input",policy="ACCEPT",table="filter"} 0 163 | iptables_chain_bytes_total{chain="ufw-after-logging-output",policy="ACCEPT",table="filter"} 0 164 | iptables_chain_bytes_total{chain="ufw-after-output",policy="ACCEPT",table="filter"} 0 165 | iptables_chain_bytes_total{chain="ufw-before-forward",policy="ACCEPT",table="filter"} 0 166 | iptables_chain_bytes_total{chain="ufw-before-input",policy="ACCEPT",table="filter"} 0 167 | iptables_chain_bytes_total{chain="ufw-before-logging-forward",policy="ACCEPT",table="filter"} 0 168 | iptables_chain_bytes_total{chain="ufw-before-logging-input",policy="ACCEPT",table="filter"} 0 169 | iptables_chain_bytes_total{chain="ufw-before-logging-output",policy="ACCEPT",table="filter"} 0 170 | iptables_chain_bytes_total{chain="ufw-before-output",policy="ACCEPT",table="filter"} 0 171 | iptables_chain_bytes_total{chain="ufw-logging-allow",policy="ACCEPT",table="filter"} 0 172 | iptables_chain_bytes_total{chain="ufw-logging-deny",policy="ACCEPT",table="filter"} 0 173 | iptables_chain_bytes_total{chain="ufw-not-local",policy="ACCEPT",table="filter"} 0 174 | iptables_chain_bytes_total{chain="ufw-reject-forward",policy="ACCEPT",table="filter"} 0 175 | iptables_chain_bytes_total{chain="ufw-reject-input",policy="ACCEPT",table="filter"} 0 176 | iptables_chain_bytes_total{chain="ufw-reject-output",policy="ACCEPT",table="filter"} 0 177 | iptables_chain_bytes_total{chain="ufw-skip-to-policy-forward",policy="ACCEPT",table="filter"} 0 178 | iptables_chain_bytes_total{chain="ufw-skip-to-policy-input",policy="ACCEPT",table="filter"} 0 179 | iptables_chain_bytes_total{chain="ufw-skip-to-policy-output",policy="ACCEPT",table="filter"} 0 180 | iptables_chain_bytes_total{chain="ufw-track-forward",policy="ACCEPT",table="filter"} 0 181 | iptables_chain_bytes_total{chain="ufw-track-input",policy="ACCEPT",table="filter"} 0 182 | iptables_chain_bytes_total{chain="ufw-track-output",policy="ACCEPT",table="filter"} 0 183 | iptables_chain_bytes_total{chain="ufw-user-forward",policy="ACCEPT",table="filter"} 0 184 | iptables_chain_bytes_total{chain="ufw-user-input",policy="ACCEPT",table="filter"} 0 185 | iptables_chain_bytes_total{chain="ufw-user-limit",policy="ACCEPT",table="filter"} 0 186 | iptables_chain_bytes_total{chain="ufw-user-limit-accept",policy="ACCEPT",table="filter"} 0 187 | iptables_chain_bytes_total{chain="ufw-user-logging-forward",policy="ACCEPT",table="filter"} 0 188 | iptables_chain_bytes_total{chain="ufw-user-logging-input",policy="ACCEPT",table="filter"} 0 189 | iptables_chain_bytes_total{chain="ufw-user-logging-output",policy="ACCEPT",table="filter"} 0 190 | iptables_chain_bytes_total{chain="ufw-user-output",policy="ACCEPT",table="filter"} 0 191 | # HELP iptables_chain_packets_total Total packets flowing through a given chain 192 | # TYPE iptables_chain_packets_total counter 193 | iptables_chain_packets_total{chain="DOCKER",policy="ACCEPT",table="filter"} 0 194 | iptables_chain_packets_total{chain="DOCKER",policy="ACCEPT",table="nat"} 0 195 | iptables_chain_packets_total{chain="DOCKER-ISOLATION-STAGE-1",policy="ACCEPT",table="filter"} 0 196 | iptables_chain_packets_total{chain="DOCKER-ISOLATION-STAGE-2",policy="ACCEPT",table="filter"} 0 197 | iptables_chain_packets_total{chain="DOCKER-USER",policy="ACCEPT",table="filter"} 0 198 | iptables_chain_packets_total{chain="FORWARD",policy="ACCEPT",table="filter"} 0 199 | iptables_chain_packets_total{chain="INPUT",policy="ACCEPT",table="filter"} 1036441 200 | iptables_chain_packets_total{chain="INPUT",policy="ACCEPT",table="nat"} 0 201 | iptables_chain_packets_total{chain="OUTPUT",policy="ACCEPT",table="filter"} 2498 202 | iptables_chain_packets_total{chain="OUTPUT",policy="ACCEPT",table="nat"} 0 203 | iptables_chain_packets_total{chain="POSTROUTING",policy="ACCEPT",table="nat"} 0 204 | iptables_chain_packets_total{chain="PREROUTING",policy="ACCEPT",table="nat"} 0 205 | iptables_chain_packets_total{chain="ts-forward",policy="ACCEPT",table="filter"} 0 206 | iptables_chain_packets_total{chain="ts-input",policy="ACCEPT",table="filter"} 0 207 | iptables_chain_packets_total{chain="ts-postrouting",policy="ACCEPT",table="nat"} 0 208 | iptables_chain_packets_total{chain="ufw-after-forward",policy="ACCEPT",table="filter"} 0 209 | iptables_chain_packets_total{chain="ufw-after-input",policy="ACCEPT",table="filter"} 0 210 | iptables_chain_packets_total{chain="ufw-after-logging-forward",policy="ACCEPT",table="filter"} 0 211 | iptables_chain_packets_total{chain="ufw-after-logging-input",policy="ACCEPT",table="filter"} 0 212 | iptables_chain_packets_total{chain="ufw-after-logging-output",policy="ACCEPT",table="filter"} 0 213 | iptables_chain_packets_total{chain="ufw-after-output",policy="ACCEPT",table="filter"} 0 214 | iptables_chain_packets_total{chain="ufw-before-forward",policy="ACCEPT",table="filter"} 0 215 | iptables_chain_packets_total{chain="ufw-before-input",policy="ACCEPT",table="filter"} 0 216 | iptables_chain_packets_total{chain="ufw-before-logging-forward",policy="ACCEPT",table="filter"} 0 217 | iptables_chain_packets_total{chain="ufw-before-logging-input",policy="ACCEPT",table="filter"} 0 218 | iptables_chain_packets_total{chain="ufw-before-logging-output",policy="ACCEPT",table="filter"} 0 219 | iptables_chain_packets_total{chain="ufw-before-output",policy="ACCEPT",table="filter"} 0 220 | iptables_chain_packets_total{chain="ufw-logging-allow",policy="ACCEPT",table="filter"} 0 221 | iptables_chain_packets_total{chain="ufw-logging-deny",policy="ACCEPT",table="filter"} 0 222 | iptables_chain_packets_total{chain="ufw-not-local",policy="ACCEPT",table="filter"} 0 223 | iptables_chain_packets_total{chain="ufw-reject-forward",policy="ACCEPT",table="filter"} 0 224 | iptables_chain_packets_total{chain="ufw-reject-input",policy="ACCEPT",table="filter"} 0 225 | iptables_chain_packets_total{chain="ufw-reject-output",policy="ACCEPT",table="filter"} 0 226 | iptables_chain_packets_total{chain="ufw-skip-to-policy-forward",policy="ACCEPT",table="filter"} 0 227 | iptables_chain_packets_total{chain="ufw-skip-to-policy-input",policy="ACCEPT",table="filter"} 0 228 | iptables_chain_packets_total{chain="ufw-skip-to-policy-output",policy="ACCEPT",table="filter"} 0 229 | iptables_chain_packets_total{chain="ufw-track-forward",policy="ACCEPT",table="filter"} 0 230 | iptables_chain_packets_total{chain="ufw-track-input",policy="ACCEPT",table="filter"} 0 231 | iptables_chain_packets_total{chain="ufw-track-output",policy="ACCEPT",table="filter"} 0 232 | iptables_chain_packets_total{chain="ufw-user-forward",policy="ACCEPT",table="filter"} 0 233 | iptables_chain_packets_total{chain="ufw-user-input",policy="ACCEPT",table="filter"} 0 234 | iptables_chain_packets_total{chain="ufw-user-limit",policy="ACCEPT",table="filter"} 0 235 | iptables_chain_packets_total{chain="ufw-user-limit-accept",policy="ACCEPT",table="filter"} 0 236 | iptables_chain_packets_total{chain="ufw-user-logging-forward",policy="ACCEPT",table="filter"} 0 237 | iptables_chain_packets_total{chain="ufw-user-logging-input",policy="ACCEPT",table="filter"} 0 238 | iptables_chain_packets_total{chain="ufw-user-logging-output",policy="ACCEPT",table="filter"} 0 239 | iptables_chain_packets_total{chain="ufw-user-output",policy="ACCEPT",table="filter"} 0 240 | # HELP iptables_chains_total Total number of chains in a table 241 | # TYPE iptables_chains_total gauge 242 | iptables_chains_total{table="filter"} 41 243 | iptables_chains_total{table="nat"} 6 244 | # HELP iptables_comment_bytes_total Total bytes matching a given comment inside a rule 245 | # TYPE iptables_comment_bytes_total counter 246 | iptables_comment_bytes_total{chain="ufw-user-input",comment="\\'dapp_Nginx%20Full\\'",table="filter"} 0 247 | iptables_comment_bytes_total{chain="ufw-user-input",comment="\\'dapp_OpenSSH\\'",table="filter"} 0 248 | # HELP iptables_comment_packets_total Total packets matching a given comment inside a rule 249 | # TYPE iptables_comment_packets_total counter 250 | iptables_comment_packets_total{chain="ufw-user-input",comment="\\'dapp_Nginx%20Full\\'",table="filter"} 0 251 | iptables_comment_packets_total{chain="ufw-user-input",comment="\\'dapp_OpenSSH\\'",table="filter"} 0 252 | # HELP iptables_rule_bytes_total Total bytes matching a given rule 253 | # TYPE iptables_rule_bytes_total counter 254 | iptables_rule_bytes_total{chain="DOCKER",rule="! -i br-6379b058093a -p tcp -m tcp --dport 3000 -j DNAT --to-destination 172.18.0.3:3000",table="nat"} 103564 255 | iptables_rule_bytes_total{chain="DOCKER",rule="-d 127.0.0.1/32 ! -i br-6379b058093a -p tcp -m tcp --dport 3022 -j DNAT --to-destination 172.18.0.3:22",table="nat"} 0 256 | iptables_rule_bytes_total{chain="DOCKER",rule="-d 172.18.0.3/32 ! -i br-6379b058093a -o br-6379b058093a -p tcp -m tcp --dport 22 -j ACCEPT",table="filter"} 0 257 | iptables_rule_bytes_total{chain="DOCKER",rule="-d 172.18.0.3/32 ! -i br-6379b058093a -o br-6379b058093a -p tcp -m tcp --dport 3000 -j ACCEPT",table="filter"} 103564 258 | iptables_rule_bytes_total{chain="DOCKER",rule="-i br-6379b058093a -j RETURN",table="nat"} 4056 259 | iptables_rule_bytes_total{chain="DOCKER",rule="-i docker0 -j RETURN",table="nat"} 0 260 | iptables_rule_bytes_total{chain="DOCKER-ISOLATION-STAGE-1",rule="-i br-6379b058093a ! -o br-6379b058093a -j DOCKER-ISOLATION-STAGE-2",table="filter"} 84363279 261 | iptables_rule_bytes_total{chain="DOCKER-ISOLATION-STAGE-1",rule="-i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2",table="filter"} 0 262 | iptables_rule_bytes_total{chain="DOCKER-ISOLATION-STAGE-1",rule="-j RETURN",table="filter"} 70219112923 263 | iptables_rule_bytes_total{chain="DOCKER-ISOLATION-STAGE-2",rule="-j RETURN",table="filter"} 84363279 264 | iptables_rule_bytes_total{chain="DOCKER-ISOLATION-STAGE-2",rule="-o br-6379b058093a -j DROP",table="filter"} 0 265 | iptables_rule_bytes_total{chain="DOCKER-ISOLATION-STAGE-2",rule="-o docker0 -j DROP",table="filter"} 0 266 | iptables_rule_bytes_total{chain="DOCKER-USER",rule="-j RETURN",table="filter"} 106189380614 267 | iptables_rule_bytes_total{chain="FORWARD",rule="-i br-6379b058093a ! -o br-6379b058093a -j ACCEPT",table="filter"} 96793557 268 | iptables_rule_bytes_total{chain="FORWARD",rule="-i br-6379b058093a -o br-6379b058093a -j ACCEPT",table="filter"} 38645160 269 | iptables_rule_bytes_total{chain="FORWARD",rule="-i docker0 ! -o docker0 -j ACCEPT",table="filter"} 0 270 | iptables_rule_bytes_total{chain="FORWARD",rule="-i docker0 -o docker0 -j ACCEPT",table="filter"} 0 271 | iptables_rule_bytes_total{chain="FORWARD",rule="-j DOCKER-ISOLATION-STAGE-1",table="filter"} 70219112923 272 | iptables_rule_bytes_total{chain="FORWARD",rule="-j DOCKER-USER",table="filter"} 70219112923 273 | iptables_rule_bytes_total{chain="FORWARD",rule="-j ts-forward",table="filter"} 70248886353 274 | iptables_rule_bytes_total{chain="FORWARD",rule="-j ufw-after-forward",table="filter"} 0 275 | iptables_rule_bytes_total{chain="FORWARD",rule="-j ufw-after-logging-forward",table="filter"} 0 276 | iptables_rule_bytes_total{chain="FORWARD",rule="-j ufw-before-forward",table="filter"} 0 277 | iptables_rule_bytes_total{chain="FORWARD",rule="-j ufw-before-logging-forward",table="filter"} 0 278 | iptables_rule_bytes_total{chain="FORWARD",rule="-j ufw-reject-forward",table="filter"} 0 279 | iptables_rule_bytes_total{chain="FORWARD",rule="-j ufw-track-forward",table="filter"} 0 280 | iptables_rule_bytes_total{chain="FORWARD",rule="-o br-6379b058093a -j DOCKER",table="filter"} 38800448 281 | iptables_rule_bytes_total{chain="FORWARD",rule="-o br-6379b058093a -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT",table="filter"} 106053786609 282 | iptables_rule_bytes_total{chain="FORWARD",rule="-o docker0 -j DOCKER",table="filter"} 0 283 | iptables_rule_bytes_total{chain="FORWARD",rule="-o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT",table="filter"} 0 284 | iptables_rule_bytes_total{chain="INPUT",rule="-j ts-input",table="filter"} 144722461078 285 | iptables_rule_bytes_total{chain="INPUT",rule="-j ufw-after-input",table="filter"} 99431756 286 | iptables_rule_bytes_total{chain="INPUT",rule="-j ufw-after-logging-input",table="filter"} 98893683 287 | iptables_rule_bytes_total{chain="INPUT",rule="-j ufw-before-input",table="filter"} 223670038486 288 | iptables_rule_bytes_total{chain="INPUT",rule="-j ufw-before-logging-input",table="filter"} 223670038486 289 | iptables_rule_bytes_total{chain="INPUT",rule="-j ufw-reject-input",table="filter"} 98893683 290 | iptables_rule_bytes_total{chain="INPUT",rule="-j ufw-track-input",table="filter"} 98893683 291 | iptables_rule_bytes_total{chain="OUTPUT",rule="! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER",table="nat"} 48072 292 | iptables_rule_bytes_total{chain="OUTPUT",rule="-j ufw-after-logging-output",table="filter"} 114847240 293 | iptables_rule_bytes_total{chain="OUTPUT",rule="-j ufw-after-output",table="filter"} 114847240 294 | iptables_rule_bytes_total{chain="OUTPUT",rule="-j ufw-before-logging-output",table="filter"} 133420557102 295 | iptables_rule_bytes_total{chain="OUTPUT",rule="-j ufw-before-output",table="filter"} 133420557102 296 | iptables_rule_bytes_total{chain="OUTPUT",rule="-j ufw-reject-output",table="filter"} 114847240 297 | iptables_rule_bytes_total{chain="OUTPUT",rule="-j ufw-track-output",table="filter"} 114847240 298 | iptables_rule_bytes_total{chain="POSTROUTING",rule="-j MASQUERADE",table="nat"} 138400621 299 | iptables_rule_bytes_total{chain="POSTROUTING",rule="-j ts-postrouting",table="nat"} 142259622 300 | iptables_rule_bytes_total{chain="POSTROUTING",rule="-s 172.17.0.0/16 ! -o docker0 -j MASQUERADE",table="nat"} 15808 301 | iptables_rule_bytes_total{chain="POSTROUTING",rule="-s 172.18.0.0/16 ! -o br-6379b058093a -j MASQUERADE",table="nat"} 5766232 302 | iptables_rule_bytes_total{chain="POSTROUTING",rule="-s 172.18.0.3/32 -d 172.18.0.3/32 -p tcp -m tcp --dport 22 -j MASQUERADE",table="nat"} 0 303 | iptables_rule_bytes_total{chain="POSTROUTING",rule="-s 172.18.0.3/32 -d 172.18.0.3/32 -p tcp -m tcp --dport 3000 -j MASQUERADE",table="nat"} 0 304 | iptables_rule_bytes_total{chain="PREROUTING",rule="-m addrtype --dst-type LOCAL -j DOCKER",table="nat"} 125651037 305 | iptables_rule_bytes_total{chain="ts-forward",rule="-i tailscale0 -j MARK --set-xmark 0x40000/0xff0000",table="filter"} 27766129 306 | iptables_rule_bytes_total{chain="ts-forward",rule="-m mark --mark 0x40000/0xff0000 -j ACCEPT",table="filter"} 27766129 307 | iptables_rule_bytes_total{chain="ts-forward",rule="-o tailscale0 -j ACCEPT",table="filter"} 5600284 308 | iptables_rule_bytes_total{chain="ts-postrouting",rule="-m mark --mark 0x40000/0xff0000 -j MASQUERADE",table="nat"} 0 309 | iptables_rule_bytes_total{chain="ufw-after-input",rule="-m addrtype --dst-type BROADCAST -j ufw-skip-to-policy-input",table="filter"} 0 310 | iptables_rule_bytes_total{chain="ufw-after-input",rule="-p tcp -m tcp --dport 139 -j ufw-skip-to-policy-input",table="filter"} 31348 311 | iptables_rule_bytes_total{chain="ufw-after-input",rule="-p tcp -m tcp --dport 445 -j ufw-skip-to-policy-input",table="filter"} 461276 312 | iptables_rule_bytes_total{chain="ufw-after-input",rule="-p udp -m udp --dport 137 -j ufw-skip-to-policy-input",table="filter"} 43685 313 | iptables_rule_bytes_total{chain="ufw-after-input",rule="-p udp -m udp --dport 138 -j ufw-skip-to-policy-input",table="filter"} 392 314 | iptables_rule_bytes_total{chain="ufw-after-input",rule="-p udp -m udp --dport 67 -j ufw-skip-to-policy-input",table="filter"} 980 315 | iptables_rule_bytes_total{chain="ufw-after-input",rule="-p udp -m udp --dport 68 -j ufw-skip-to-policy-input",table="filter"} 392 316 | iptables_rule_bytes_total{chain="ufw-after-logging-forward",rule="-m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix \"[UFW BLOCK] \"",table="filter"} 0 317 | iptables_rule_bytes_total{chain="ufw-after-logging-input",rule="-m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix \"[UFW BLOCK] \"",table="filter"} 14484045 318 | iptables_rule_bytes_total{chain="ufw-before-forward",rule="-j ufw-user-forward",table="filter"} 0 319 | iptables_rule_bytes_total{chain="ufw-before-forward",rule="-m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT",table="filter"} 0 320 | iptables_rule_bytes_total{chain="ufw-before-forward",rule="-p icmp -m icmp --icmp-type 11 -j ACCEPT",table="filter"} 0 321 | iptables_rule_bytes_total{chain="ufw-before-forward",rule="-p icmp -m icmp --icmp-type 12 -j ACCEPT",table="filter"} 0 322 | iptables_rule_bytes_total{chain="ufw-before-forward",rule="-p icmp -m icmp --icmp-type 3 -j ACCEPT",table="filter"} 0 323 | iptables_rule_bytes_total{chain="ufw-before-forward",rule="-p icmp -m icmp --icmp-type 8 -j ACCEPT",table="filter"} 0 324 | iptables_rule_bytes_total{chain="ufw-before-input",rule="-d 224.0.0.251/32 -p udp -m udp --dport 5353 -j ACCEPT",table="filter"} 0 325 | iptables_rule_bytes_total{chain="ufw-before-input",rule="-d 239.255.255.250/32 -p udp -m udp --dport 1900 -j ACCEPT",table="filter"} 0 326 | iptables_rule_bytes_total{chain="ufw-before-input",rule="-i lo -j ACCEPT",table="filter"} 109905406104 327 | iptables_rule_bytes_total{chain="ufw-before-input",rule="-j ufw-not-local",table="filter"} 139808177 328 | iptables_rule_bytes_total{chain="ufw-before-input",rule="-j ufw-user-input",table="filter"} 139808177 329 | iptables_rule_bytes_total{chain="ufw-before-input",rule="-m conntrack --ctstate INVALID -j DROP",table="filter"} 12630859 330 | iptables_rule_bytes_total{chain="ufw-before-input",rule="-m conntrack --ctstate INVALID -j ufw-logging-deny",table="filter"} 12630859 331 | iptables_rule_bytes_total{chain="ufw-before-input",rule="-m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT",table="filter"} 113600086803 332 | iptables_rule_bytes_total{chain="ufw-before-input",rule="-p icmp -m icmp --icmp-type 11 -j ACCEPT",table="filter"} 0 333 | iptables_rule_bytes_total{chain="ufw-before-input",rule="-p icmp -m icmp --icmp-type 12 -j ACCEPT",table="filter"} 0 334 | iptables_rule_bytes_total{chain="ufw-before-input",rule="-p icmp -m icmp --icmp-type 3 -j ACCEPT",table="filter"} 0 335 | iptables_rule_bytes_total{chain="ufw-before-input",rule="-p icmp -m icmp --icmp-type 8 -j ACCEPT",table="filter"} 12106543 336 | iptables_rule_bytes_total{chain="ufw-before-input",rule="-p udp -m udp --sport 67 --dport 68 -j ACCEPT",table="filter"} 0 337 | iptables_rule_bytes_total{chain="ufw-before-output",rule="-j ufw-user-output",table="filter"} 114847240 338 | iptables_rule_bytes_total{chain="ufw-before-output",rule="-m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT",table="filter"} 23400303758 339 | iptables_rule_bytes_total{chain="ufw-before-output",rule="-o lo -j ACCEPT",table="filter"} 109905406104 340 | iptables_rule_bytes_total{chain="ufw-logging-allow",rule="-m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix \"[UFW ALLOW] \"",table="filter"} 0 341 | iptables_rule_bytes_total{chain="ufw-logging-deny",rule="-m conntrack --ctstate INVALID -m limit --limit 3/min --limit-burst 10 -j RETURN",table="filter"} 12553133 342 | iptables_rule_bytes_total{chain="ufw-logging-deny",rule="-m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix \"[UFW BLOCK] \"",table="filter"} 23494 343 | iptables_rule_bytes_total{chain="ufw-not-local",rule="-j DROP",table="filter"} 0 344 | iptables_rule_bytes_total{chain="ufw-not-local",rule="-m addrtype --dst-type BROADCAST -j RETURN",table="filter"} 0 345 | iptables_rule_bytes_total{chain="ufw-not-local",rule="-m addrtype --dst-type LOCAL -j RETURN",table="filter"} 139808177 346 | iptables_rule_bytes_total{chain="ufw-not-local",rule="-m addrtype --dst-type MULTICAST -j RETURN",table="filter"} 0 347 | iptables_rule_bytes_total{chain="ufw-not-local",rule="-m limit --limit 3/min --limit-burst 10 -j ufw-logging-deny",table="filter"} 0 348 | iptables_rule_bytes_total{chain="ufw-skip-to-policy-forward",rule="-j DROP",table="filter"} 0 349 | iptables_rule_bytes_total{chain="ufw-skip-to-policy-input",rule="-j DROP",table="filter"} 538073 350 | iptables_rule_bytes_total{chain="ufw-skip-to-policy-output",rule="-j ACCEPT",table="filter"} 0 351 | iptables_rule_bytes_total{chain="ufw-track-output",rule="-p tcp -m conntrack --ctstate NEW -j ACCEPT",table="filter"} 71823344 352 | iptables_rule_bytes_total{chain="ufw-track-output",rule="-p udp -m conntrack --ctstate NEW -j ACCEPT",table="filter"} 42827441 353 | iptables_rule_bytes_total{chain="ufw-user-input",rule="-p tcp -m multiport --dports 80,443 -j ACCEPT",table="filter"} 22646850 354 | iptables_rule_bytes_total{chain="ufw-user-input",rule="-p tcp -m tcp --dport 1022 -j ACCEPT",table="filter"} 4572 355 | iptables_rule_bytes_total{chain="ufw-user-input",rule="-p tcp -m tcp --dport 110 -j DROP",table="filter"} 53612 356 | iptables_rule_bytes_total{chain="ufw-user-input",rule="-p tcp -m tcp --dport 22 -j ACCEPT",table="filter"} 17335109 357 | iptables_rule_bytes_total{chain="ufw-user-input",rule="-p tcp -m tcp --dport 25 -j DROP",table="filter"} 199380 358 | iptables_rule_bytes_total{chain="ufw-user-input",rule="-p tcp -m tcp --dport 30000 -j ACCEPT",table="filter"} 0 359 | iptables_rule_bytes_total{chain="ufw-user-input",rule="-p tcp -m tcp --dport 51820 -j ACCEPT",table="filter"} 0 360 | iptables_rule_bytes_total{chain="ufw-user-input",rule="-p tcp -m tcp --dport 587 -j DROP",table="filter"} 56064 361 | iptables_rule_bytes_total{chain="ufw-user-input",rule="-p tcp -m tcp --dport 9001 -j DROP",table="filter"} 24844 362 | iptables_rule_bytes_total{chain="ufw-user-input",rule="-p tcp -m tcp --dport 993 -j DROP",table="filter"} 52200 363 | iptables_rule_bytes_total{chain="ufw-user-input",rule="-p udp -m udp --dport 110 -j DROP",table="filter"} 58 364 | iptables_rule_bytes_total{chain="ufw-user-input",rule="-p udp -m udp --dport 25 -j DROP",table="filter"} 2397 365 | iptables_rule_bytes_total{chain="ufw-user-input",rule="-p udp -m udp --dport 30000 -j ACCEPT",table="filter"} 0 366 | iptables_rule_bytes_total{chain="ufw-user-input",rule="-p udp -m udp --dport 51820 -j ACCEPT",table="filter"} 0 367 | iptables_rule_bytes_total{chain="ufw-user-input",rule="-p udp -m udp --dport 587 -j DROP",table="filter"} 196 368 | iptables_rule_bytes_total{chain="ufw-user-input",rule="-p udp -m udp --dport 993 -j DROP",table="filter"} 254 369 | iptables_rule_bytes_total{chain="ufw-user-limit",rule="-j REJECT --reject-with icmp-port-unreachable",table="filter"} 0 370 | iptables_rule_bytes_total{chain="ufw-user-limit",rule="-m limit --limit 3/min -j LOG --log-prefix \"[UFW LIMIT BLOCK] \"",table="filter"} 0 371 | iptables_rule_bytes_total{chain="ufw-user-limit-accept",rule="-j ACCEPT",table="filter"} 0 372 | # HELP iptables_rule_packets_total Total packets matching a given rule 373 | # TYPE iptables_rule_packets_total counter 374 | iptables_rule_packets_total{chain="DOCKER",rule="! -i br-6379b058093a -p tcp -m tcp --dport 3000 -j DNAT --to-destination 172.18.0.3:3000",table="nat"} 1880 375 | iptables_rule_packets_total{chain="DOCKER",rule="-d 127.0.0.1/32 ! -i br-6379b058093a -p tcp -m tcp --dport 3022 -j DNAT --to-destination 172.18.0.3:22",table="nat"} 0 376 | iptables_rule_packets_total{chain="DOCKER",rule="-d 172.18.0.3/32 ! -i br-6379b058093a -o br-6379b058093a -p tcp -m tcp --dport 22 -j ACCEPT",table="filter"} 0 377 | iptables_rule_packets_total{chain="DOCKER",rule="-d 172.18.0.3/32 ! -i br-6379b058093a -o br-6379b058093a -p tcp -m tcp --dport 3000 -j ACCEPT",table="filter"} 1880 378 | iptables_rule_packets_total{chain="DOCKER",rule="-i br-6379b058093a -j RETURN",table="nat"} 8 379 | iptables_rule_packets_total{chain="DOCKER",rule="-i docker0 -j RETURN",table="nat"} 0 380 | iptables_rule_packets_total{chain="DOCKER-ISOLATION-STAGE-1",rule="-i br-6379b058093a ! -o br-6379b058093a -j DOCKER-ISOLATION-STAGE-2",table="filter"} 195813 381 | iptables_rule_packets_total{chain="DOCKER-ISOLATION-STAGE-1",rule="-i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2",table="filter"} 0 382 | iptables_rule_packets_total{chain="DOCKER-ISOLATION-STAGE-1",rule="-j RETURN",table="filter"} 140281499 383 | iptables_rule_packets_total{chain="DOCKER-ISOLATION-STAGE-2",rule="-j RETURN",table="filter"} 195813 384 | iptables_rule_packets_total{chain="DOCKER-ISOLATION-STAGE-2",rule="-o br-6379b058093a -j DROP",table="filter"} 0 385 | iptables_rule_packets_total{chain="DOCKER-ISOLATION-STAGE-2",rule="-o docker0 -j DROP",table="filter"} 0 386 | iptables_rule_packets_total{chain="DOCKER-USER",rule="-j RETURN",table="filter"} 212747854 387 | iptables_rule_packets_total{chain="FORWARD",rule="-i br-6379b058093a ! -o br-6379b058093a -j ACCEPT",table="filter"} 286249 388 | iptables_rule_packets_total{chain="FORWARD",rule="-i br-6379b058093a -o br-6379b058093a -j ACCEPT",table="filter"} 644086 389 | iptables_rule_packets_total{chain="FORWARD",rule="-i docker0 ! -o docker0 -j ACCEPT",table="filter"} 0 390 | iptables_rule_packets_total{chain="FORWARD",rule="-i docker0 -o docker0 -j ACCEPT",table="filter"} 0 391 | iptables_rule_packets_total{chain="FORWARD",rule="-j DOCKER-ISOLATION-STAGE-1",table="filter"} 140281499 392 | iptables_rule_packets_total{chain="FORWARD",rule="-j DOCKER-USER",table="filter"} 140281499 393 | iptables_rule_packets_total{chain="FORWARD",rule="-j ts-forward",table="filter"} 140534327 394 | iptables_rule_packets_total{chain="FORWARD",rule="-j ufw-after-forward",table="filter"} 0 395 | iptables_rule_packets_total{chain="FORWARD",rule="-j ufw-after-logging-forward",table="filter"} 0 396 | iptables_rule_packets_total{chain="FORWARD",rule="-j ufw-before-forward",table="filter"} 0 397 | iptables_rule_packets_total{chain="FORWARD",rule="-j ufw-before-logging-forward",table="filter"} 0 398 | iptables_rule_packets_total{chain="FORWARD",rule="-j ufw-reject-forward",table="filter"} 0 399 | iptables_rule_packets_total{chain="FORWARD",rule="-j ufw-track-forward",table="filter"} 0 400 | iptables_rule_packets_total{chain="FORWARD",rule="-o br-6379b058093a -j DOCKER",table="filter"} 646949 401 | iptables_rule_packets_total{chain="FORWARD",rule="-o br-6379b058093a -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT",table="filter"} 211814656 402 | iptables_rule_packets_total{chain="FORWARD",rule="-o docker0 -j DOCKER",table="filter"} 0 403 | iptables_rule_packets_total{chain="FORWARD",rule="-o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT",table="filter"} 0 404 | iptables_rule_packets_total{chain="INPUT",rule="-j ts-input",table="filter"} 28446758 405 | iptables_rule_packets_total{chain="INPUT",rule="-j ufw-after-input",table="filter"} 1047231 406 | iptables_rule_packets_total{chain="INPUT",rule="-j ufw-after-logging-input",table="filter"} 1036441 407 | iptables_rule_packets_total{chain="INPUT",rule="-j ufw-before-input",table="filter"} 41402627 408 | iptables_rule_packets_total{chain="INPUT",rule="-j ufw-before-logging-input",table="filter"} 41402627 409 | iptables_rule_packets_total{chain="INPUT",rule="-j ufw-reject-input",table="filter"} 1036441 410 | iptables_rule_packets_total{chain="INPUT",rule="-j ufw-track-input",table="filter"} 1036441 411 | iptables_rule_packets_total{chain="OUTPUT",rule="! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER",table="nat"} 450 412 | iptables_rule_packets_total{chain="OUTPUT",rule="-j ufw-after-logging-output",table="filter"} 1843105 413 | iptables_rule_packets_total{chain="OUTPUT",rule="-j ufw-after-output",table="filter"} 1843105 414 | iptables_rule_packets_total{chain="OUTPUT",rule="-j ufw-before-logging-output",table="filter"} 39955411 415 | iptables_rule_packets_total{chain="OUTPUT",rule="-j ufw-before-output",table="filter"} 39955411 416 | iptables_rule_packets_total{chain="OUTPUT",rule="-j ufw-reject-output",table="filter"} 1843105 417 | iptables_rule_packets_total{chain="OUTPUT",rule="-j ufw-track-output",table="filter"} 1843105 418 | iptables_rule_packets_total{chain="POSTROUTING",rule="-j MASQUERADE",table="nat"} 2279040 419 | iptables_rule_packets_total{chain="POSTROUTING",rule="-j ts-postrouting",table="nat"} 2344043 420 | iptables_rule_packets_total{chain="POSTROUTING",rule="-s 172.17.0.0/16 ! -o docker0 -j MASQUERADE",table="nat"} 104 421 | iptables_rule_packets_total{chain="POSTROUTING",rule="-s 172.18.0.0/16 ! -o br-6379b058093a -j MASQUERADE",table="nat"} 97464 422 | iptables_rule_packets_total{chain="POSTROUTING",rule="-s 172.18.0.3/32 -d 172.18.0.3/32 -p tcp -m tcp --dport 22 -j MASQUERADE",table="nat"} 0 423 | iptables_rule_packets_total{chain="POSTROUTING",rule="-s 172.18.0.3/32 -d 172.18.0.3/32 -p tcp -m tcp --dport 3000 -j MASQUERADE",table="nat"} 0 424 | iptables_rule_packets_total{chain="PREROUTING",rule="-m addrtype --dst-type LOCAL -j DOCKER",table="nat"} 1518992 425 | iptables_rule_packets_total{chain="ts-forward",rule="-i tailscale0 -j MARK --set-xmark 0x40000/0xff0000",table="filter"} 134257 426 | iptables_rule_packets_total{chain="ts-forward",rule="-m mark --mark 0x40000/0xff0000 -j ACCEPT",table="filter"} 134257 427 | iptables_rule_packets_total{chain="ts-forward",rule="-o tailscale0 -j ACCEPT",table="filter"} 126295 428 | iptables_rule_packets_total{chain="ts-postrouting",rule="-m mark --mark 0x40000/0xff0000 -j MASQUERADE",table="nat"} 0 429 | iptables_rule_packets_total{chain="ufw-after-input",rule="-m addrtype --dst-type BROADCAST -j ufw-skip-to-policy-input",table="filter"} 0 430 | iptables_rule_packets_total{chain="ufw-after-input",rule="-p tcp -m tcp --dport 139 -j ufw-skip-to-policy-input",table="filter"} 741 431 | iptables_rule_packets_total{chain="ufw-after-input",rule="-p tcp -m tcp --dport 445 -j ufw-skip-to-policy-input",table="filter"} 9444 432 | iptables_rule_packets_total{chain="ufw-after-input",rule="-p udp -m udp --dport 137 -j ufw-skip-to-policy-input",table="filter"} 560 433 | iptables_rule_packets_total{chain="ufw-after-input",rule="-p udp -m udp --dport 138 -j ufw-skip-to-policy-input",table="filter"} 14 434 | iptables_rule_packets_total{chain="ufw-after-input",rule="-p udp -m udp --dport 67 -j ufw-skip-to-policy-input",table="filter"} 17 435 | iptables_rule_packets_total{chain="ufw-after-input",rule="-p udp -m udp --dport 68 -j ufw-skip-to-policy-input",table="filter"} 14 436 | iptables_rule_packets_total{chain="ufw-after-logging-forward",rule="-m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix \"[UFW BLOCK] \"",table="filter"} 0 437 | iptables_rule_packets_total{chain="ufw-after-logging-input",rule="-m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix \"[UFW BLOCK] \"",table="filter"} 315837 438 | iptables_rule_packets_total{chain="ufw-before-forward",rule="-j ufw-user-forward",table="filter"} 0 439 | iptables_rule_packets_total{chain="ufw-before-forward",rule="-m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT",table="filter"} 0 440 | iptables_rule_packets_total{chain="ufw-before-forward",rule="-p icmp -m icmp --icmp-type 11 -j ACCEPT",table="filter"} 0 441 | iptables_rule_packets_total{chain="ufw-before-forward",rule="-p icmp -m icmp --icmp-type 12 -j ACCEPT",table="filter"} 0 442 | iptables_rule_packets_total{chain="ufw-before-forward",rule="-p icmp -m icmp --icmp-type 3 -j ACCEPT",table="filter"} 0 443 | iptables_rule_packets_total{chain="ufw-before-forward",rule="-p icmp -m icmp --icmp-type 8 -j ACCEPT",table="filter"} 0 444 | iptables_rule_packets_total{chain="ufw-before-input",rule="-d 224.0.0.251/32 -p udp -m udp --dport 5353 -j ACCEPT",table="filter"} 0 445 | iptables_rule_packets_total{chain="ufw-before-input",rule="-d 239.255.255.250/32 -p udp -m udp --dport 1900 -j ACCEPT",table="filter"} 0 446 | iptables_rule_packets_total{chain="ufw-before-input",rule="-i lo -j ACCEPT",table="filter"} 15985056 447 | iptables_rule_packets_total{chain="ufw-before-input",rule="-j ufw-not-local",table="filter"} 1733486 448 | iptables_rule_packets_total{chain="ufw-before-input",rule="-j ufw-user-input",table="filter"} 1733486 449 | iptables_rule_packets_total{chain="ufw-before-input",rule="-m conntrack --ctstate INVALID -j DROP",table="filter"} 32617 450 | iptables_rule_packets_total{chain="ufw-before-input",rule="-m conntrack --ctstate INVALID -j ufw-logging-deny",table="filter"} 32617 451 | iptables_rule_packets_total{chain="ufw-before-input",rule="-m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT",table="filter"} 23334141 452 | iptables_rule_packets_total{chain="ufw-before-input",rule="-p icmp -m icmp --icmp-type 11 -j ACCEPT",table="filter"} 0 453 | iptables_rule_packets_total{chain="ufw-before-input",rule="-p icmp -m icmp --icmp-type 12 -j ACCEPT",table="filter"} 0 454 | iptables_rule_packets_total{chain="ufw-before-input",rule="-p icmp -m icmp --icmp-type 3 -j ACCEPT",table="filter"} 0 455 | iptables_rule_packets_total{chain="ufw-before-input",rule="-p icmp -m icmp --icmp-type 8 -j ACCEPT",table="filter"} 317327 456 | iptables_rule_packets_total{chain="ufw-before-input",rule="-p udp -m udp --sport 67 --dport 68 -j ACCEPT",table="filter"} 0 457 | iptables_rule_packets_total{chain="ufw-before-output",rule="-j ufw-user-output",table="filter"} 1843105 458 | iptables_rule_packets_total{chain="ufw-before-output",rule="-m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT",table="filter"} 22127250 459 | iptables_rule_packets_total{chain="ufw-before-output",rule="-o lo -j ACCEPT",table="filter"} 15985056 460 | iptables_rule_packets_total{chain="ufw-logging-allow",rule="-m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix \"[UFW ALLOW] \"",table="filter"} 0 461 | iptables_rule_packets_total{chain="ufw-logging-deny",rule="-m conntrack --ctstate INVALID -m limit --limit 3/min --limit-burst 10 -j RETURN",table="filter"} 31777 462 | iptables_rule_packets_total{chain="ufw-logging-deny",rule="-m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix \"[UFW BLOCK] \"",table="filter"} 133 463 | iptables_rule_packets_total{chain="ufw-not-local",rule="-j DROP",table="filter"} 0 464 | iptables_rule_packets_total{chain="ufw-not-local",rule="-m addrtype --dst-type BROADCAST -j RETURN",table="filter"} 0 465 | iptables_rule_packets_total{chain="ufw-not-local",rule="-m addrtype --dst-type LOCAL -j RETURN",table="filter"} 1733486 466 | iptables_rule_packets_total{chain="ufw-not-local",rule="-m addrtype --dst-type MULTICAST -j RETURN",table="filter"} 0 467 | iptables_rule_packets_total{chain="ufw-not-local",rule="-m limit --limit 3/min --limit-burst 10 -j ufw-logging-deny",table="filter"} 0 468 | iptables_rule_packets_total{chain="ufw-skip-to-policy-forward",rule="-j DROP",table="filter"} 0 469 | iptables_rule_packets_total{chain="ufw-skip-to-policy-input",rule="-j DROP",table="filter"} 10790 470 | iptables_rule_packets_total{chain="ufw-skip-to-policy-output",rule="-j ACCEPT",table="filter"} 0 471 | iptables_rule_packets_total{chain="ufw-track-output",rule="-p tcp -m conntrack --ctstate NEW -j ACCEPT",table="filter"} 1197023 472 | iptables_rule_packets_total{chain="ufw-track-output",rule="-p udp -m conntrack --ctstate NEW -j ACCEPT",table="filter"} 643584 473 | iptables_rule_packets_total{chain="ufw-user-input",rule="-p tcp -m multiport --dports 80,443 -j ACCEPT",table="filter"} 384990 474 | iptables_rule_packets_total{chain="ufw-user-input",rule="-p tcp -m tcp --dport 1022 -j ACCEPT",table="filter"} 109 475 | iptables_rule_packets_total{chain="ufw-user-input",rule="-p tcp -m tcp --dport 110 -j DROP",table="filter"} 1299 476 | iptables_rule_packets_total{chain="ufw-user-input",rule="-p tcp -m tcp --dport 22 -j ACCEPT",table="filter"} 292613 477 | iptables_rule_packets_total{chain="ufw-user-input",rule="-p tcp -m tcp --dport 25 -j DROP",table="filter"} 3939 478 | iptables_rule_packets_total{chain="ufw-user-input",rule="-p tcp -m tcp --dport 30000 -j ACCEPT",table="filter"} 0 479 | iptables_rule_packets_total{chain="ufw-user-input",rule="-p tcp -m tcp --dport 51820 -j ACCEPT",table="filter"} 0 480 | iptables_rule_packets_total{chain="ufw-user-input",rule="-p tcp -m tcp --dport 587 -j DROP",table="filter"} 1351 481 | iptables_rule_packets_total{chain="ufw-user-input",rule="-p tcp -m tcp --dport 9001 -j DROP",table="filter"} 608 482 | iptables_rule_packets_total{chain="ufw-user-input",rule="-p tcp -m tcp --dport 993 -j DROP",table="filter"} 1281 483 | iptables_rule_packets_total{chain="ufw-user-input",rule="-p udp -m udp --dport 110 -j DROP",table="filter"} 1 484 | iptables_rule_packets_total{chain="ufw-user-input",rule="-p udp -m udp --dport 25 -j DROP",table="filter"} 47 485 | iptables_rule_packets_total{chain="ufw-user-input",rule="-p udp -m udp --dport 30000 -j ACCEPT",table="filter"} 0 486 | iptables_rule_packets_total{chain="ufw-user-input",rule="-p udp -m udp --dport 51820 -j ACCEPT",table="filter"} 0 487 | iptables_rule_packets_total{chain="ufw-user-input",rule="-p udp -m udp --dport 587 -j DROP",table="filter"} 7 488 | iptables_rule_packets_total{chain="ufw-user-input",rule="-p udp -m udp --dport 993 -j DROP",table="filter"} 8 489 | iptables_rule_packets_total{chain="ufw-user-limit",rule="-j REJECT --reject-with icmp-port-unreachable",table="filter"} 0 490 | iptables_rule_packets_total{chain="ufw-user-limit",rule="-m limit --limit 3/min -j LOG --log-prefix \"[UFW LIMIT BLOCK] \"",table="filter"} 0 491 | iptables_rule_packets_total{chain="ufw-user-limit-accept",rule="-j ACCEPT",table="filter"} 0 492 | # HELP iptables_rules_total Total number of rules in a chain in a table 493 | # TYPE iptables_rules_total gauge 494 | iptables_rules_total{chain="DOCKER",table="filter"} 2 495 | iptables_rules_total{chain="DOCKER",table="nat"} 4 496 | iptables_rules_total{chain="DOCKER-ISOLATION-STAGE-1",table="filter"} 3 497 | iptables_rules_total{chain="DOCKER-ISOLATION-STAGE-2",table="filter"} 3 498 | iptables_rules_total{chain="DOCKER-USER",table="filter"} 1 499 | iptables_rules_total{chain="FORWARD",table="filter"} 17 500 | iptables_rules_total{chain="INPUT",table="filter"} 7 501 | iptables_rules_total{chain="INPUT",table="nat"} 0 502 | iptables_rules_total{chain="OUTPUT",table="filter"} 6 503 | iptables_rules_total{chain="OUTPUT",table="nat"} 1 504 | iptables_rules_total{chain="POSTROUTING",table="nat"} 6 505 | iptables_rules_total{chain="PREROUTING",table="nat"} 3 506 | iptables_rules_total{chain="ts-forward",table="filter"} 4 507 | iptables_rules_total{chain="ts-input",table="filter"} 3 508 | iptables_rules_total{chain="ts-postrouting",table="nat"} 1 509 | iptables_rules_total{chain="ufw-after-forward",table="filter"} 0 510 | iptables_rules_total{chain="ufw-after-input",table="filter"} 7 511 | iptables_rules_total{chain="ufw-after-logging-forward",table="filter"} 1 512 | iptables_rules_total{chain="ufw-after-logging-input",table="filter"} 1 513 | iptables_rules_total{chain="ufw-after-logging-output",table="filter"} 0 514 | iptables_rules_total{chain="ufw-after-output",table="filter"} 0 515 | iptables_rules_total{chain="ufw-before-forward",table="filter"} 6 516 | iptables_rules_total{chain="ufw-before-input",table="filter"} 13 517 | iptables_rules_total{chain="ufw-before-logging-forward",table="filter"} 0 518 | iptables_rules_total{chain="ufw-before-logging-input",table="filter"} 0 519 | iptables_rules_total{chain="ufw-before-logging-output",table="filter"} 0 520 | iptables_rules_total{chain="ufw-before-output",table="filter"} 3 521 | iptables_rules_total{chain="ufw-logging-allow",table="filter"} 1 522 | iptables_rules_total{chain="ufw-logging-deny",table="filter"} 2 523 | iptables_rules_total{chain="ufw-not-local",table="filter"} 5 524 | iptables_rules_total{chain="ufw-reject-forward",table="filter"} 0 525 | iptables_rules_total{chain="ufw-reject-input",table="filter"} 0 526 | iptables_rules_total{chain="ufw-reject-output",table="filter"} 0 527 | iptables_rules_total{chain="ufw-skip-to-policy-forward",table="filter"} 1 528 | iptables_rules_total{chain="ufw-skip-to-policy-input",table="filter"} 1 529 | iptables_rules_total{chain="ufw-skip-to-policy-output",table="filter"} 1 530 | iptables_rules_total{chain="ufw-track-forward",table="filter"} 0 531 | iptables_rules_total{chain="ufw-track-input",table="filter"} 0 532 | iptables_rules_total{chain="ufw-track-output",table="filter"} 2 533 | iptables_rules_total{chain="ufw-user-forward",table="filter"} 0 534 | iptables_rules_total{chain="ufw-user-input",table="filter"} 17 535 | iptables_rules_total{chain="ufw-user-limit",table="filter"} 2 536 | iptables_rules_total{chain="ufw-user-limit-accept",table="filter"} 1 537 | iptables_rules_total{chain="ufw-user-logging-forward",table="filter"} 0 538 | iptables_rules_total{chain="ufw-user-logging-input",table="filter"} 0 539 | iptables_rules_total{chain="ufw-user-logging-output",table="filter"} 0 540 | iptables_rules_total{chain="ufw-user-output",table="filter"} 0 541 | # HELP iptables_scrape_duration_milliseconds Duration in milliseconds of the scrape 542 | # TYPE iptables_scrape_duration_milliseconds gauge 543 | iptables_scrape_duration_milliseconds 6 544 | # HELP iptables_scrape_success If the scrape was a success 545 | # TYPE iptables_scrape_success gauge 546 | iptables_scrape_success 1 547 | # HELP prometheus_exporter_request_duration_seconds HTTP request durations in seconds 548 | # TYPE prometheus_exporter_request_duration_seconds histogram 549 | prometheus_exporter_request_duration_seconds_bucket{le="0.005"} 4 550 | prometheus_exporter_request_duration_seconds_bucket{le="0.01"} 4 551 | prometheus_exporter_request_duration_seconds_bucket{le="0.025"} 4 552 | prometheus_exporter_request_duration_seconds_bucket{le="0.05"} 4 553 | prometheus_exporter_request_duration_seconds_bucket{le="0.1"} 4 554 | prometheus_exporter_request_duration_seconds_bucket{le="0.25"} 4 555 | prometheus_exporter_request_duration_seconds_bucket{le="0.5"} 4 556 | prometheus_exporter_request_duration_seconds_bucket{le="1"} 4 557 | prometheus_exporter_request_duration_seconds_bucket{le="2.5"} 4 558 | prometheus_exporter_request_duration_seconds_bucket{le="5"} 4 559 | prometheus_exporter_request_duration_seconds_bucket{le="10"} 4 560 | prometheus_exporter_request_duration_seconds_bucket{le="+Inf"} 4 561 | prometheus_exporter_request_duration_seconds_sum 0.006526718000000001 562 | prometheus_exporter_request_duration_seconds_count 4 563 | # HELP prometheus_exporter_requests_total HTTP requests received 564 | # TYPE prometheus_exporter_requests_total counter 565 | prometheus_exporter_requests_total 5 566 | # HELP prometheus_exporter_response_size_bytes HTTP response sizes in bytes 567 | # TYPE prometheus_exporter_response_size_bytes gauge 568 | prometheus_exporter_response_size_bytes 43102 569 | ``` 570 | 571 | # License 572 | 573 | This project is dual licensed under the terms of either the MIT or Apache 2.0 574 | at your option. 575 | -------------------------------------------------------------------------------- /build.rs: -------------------------------------------------------------------------------- 1 | use std::process::Command; 2 | 3 | fn main() { 4 | let output = Command::new("git") 5 | .args(["rev-parse", "HEAD"]) 6 | .output() 7 | .unwrap(); 8 | let git_hash = String::from_utf8(output.stdout).unwrap(); 9 | println!( 10 | "cargo:rustc-env=VERSION_WITH_GIT_HASH=v{} ({})", 11 | env!("CARGO_PKG_VERSION"), 12 | &git_hash[..10] 13 | ); 14 | } 15 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | # https://rust-lang.github.io/rustfmt/?version=master&search=#edition 2 | edition = "2021" 3 | # https://rust-lang.github.io/rustfmt/?version=master&search=#fn_single_line 4 | fn_single_line = true 5 | # https://rust-lang.github.io/rustfmt/?version=master&search=#format_code_in_doc_comments 6 | format_code_in_doc_comments = true 7 | # https://rust-lang.github.io/rustfmt/?version=master&search=#format_macro_matchers 8 | format_macro_matchers = true 9 | # https://rust-lang.github.io/rustfmt/?version=master&search=#imports_granularity 10 | imports_granularity = "Crate" 11 | # https://rust-lang.github.io/rustfmt/?version=master&search=#normalize_comments 12 | normalize_comments = true 13 | # https://rust-lang.github.io/rustfmt/?version=master&search=#reorder_impl_items 14 | reorder_impl_items = true 15 | # https://rust-lang.github.io/rustfmt/?version=master&search=#unstable_features 16 | unstable_features = true 17 | # https://rust-lang.github.io/rustfmt/?version=master&search=#use_field_init_shorthand 18 | use_field_init_shorthand = true 19 | # https://rust-lang.github.io/rustfmt/?version=master&search=#use_try_shorthand 20 | use_try_shorthand = true 21 | # https://rust-lang.github.io/rustfmt/?version=master&search=#wrap_comments 22 | wrap_comments = true 23 | -------------------------------------------------------------------------------- /src/cli.rs: -------------------------------------------------------------------------------- 1 | use std::{env, net::IpAddr}; 2 | 3 | use clap::{crate_authors, ArgAction, Parser}; 4 | 5 | static VERSION: &str = env!("VERSION_WITH_GIT_HASH"); 6 | static AUTHORS: &str = crate_authors!(); 7 | 8 | /// A Prometheus exporter for iptables 9 | #[derive(Parser)] 10 | #[command(author = AUTHORS, version = VERSION)] 11 | pub(crate) struct Args { 12 | /// How often metrics are gathered 13 | #[arg(long, default_value = "5", value_name = "SECS")] 14 | pub(crate) collect_interval: u64, 15 | /// The listen port for scraping metrics 16 | #[arg(short = 'p', long, default_value = "9455", value_name = "PORT")] 17 | pub(crate) listen_port: u16, 18 | /// The listen address scraping metrics 19 | #[arg(short, long, default_value = "0.0.0.0", value_name = "ADDR")] 20 | pub(crate) listen_address: IpAddr, 21 | /// Which backends to scrape for metrics, multiple targets can be enabled at 22 | /// once by using this flag multiple times 23 | #[arg(short = 't', long, visible_alias = "scrape-target", default_value = "iptables", action = ArgAction::Append, value_enum, value_name = "TARGET")] 24 | pub(crate) scrape_targets: Vec, 25 | /// Show verbose output at a level or higher. -v: DEBUG, -vv: TRACE 26 | #[arg(long, short, action = ArgAction::Count)] 27 | pub(crate) verbose: u8, 28 | /// Supress output at a level or lower. -q: INFO, -qq: WARN, -qqq: ERROR 29 | /// (i.e. everything) 30 | #[arg(long, short, overrides_with = "verbose", action = ArgAction::Count)] 31 | pub(crate) quiet: u8, 32 | } 33 | 34 | #[derive(clap::ValueEnum, PartialEq, Eq, Copy, Clone, Debug, strum::AsRefStr, strum::Display)] 35 | pub(crate) enum ScrapeTarget { 36 | /// enable 'iptables-save' for metrics 37 | #[strum(serialize = "iptables")] 38 | Iptables, 39 | /// enable 'ip6tables-save' for metrics 40 | #[strum(serialize = "ip6tables")] 41 | Ip6tables, 42 | /// enable 'iptables-legacy-save' for metrics 43 | #[strum(serialize = "iptables-legacy")] 44 | IptablesLegacy, 45 | /// enable 'ip6tables-legacy-save' for metrics 46 | #[strum(serialize = "ip6tables-legacy")] 47 | Ip6tablesLegacy, 48 | } 49 | -------------------------------------------------------------------------------- /src/error.rs: -------------------------------------------------------------------------------- 1 | use thiserror::Error; 2 | 3 | #[derive(Debug, Error)] 4 | pub(crate) enum IptablesError { 5 | #[error("Invalid policy {0}. Choices are ACCEPT or DROP")] 6 | InvalidPolicy(String), 7 | } 8 | -------------------------------------------------------------------------------- /src/iptables.rs: -------------------------------------------------------------------------------- 1 | mod chain; 2 | mod counter; 3 | mod metrics; 4 | mod rule; 5 | mod table; 6 | 7 | pub(crate) use chain::Chain; 8 | pub(crate) use counter::Counter; 9 | pub(crate) use metrics::Metrics; 10 | pub(crate) use rule::Rule; 11 | pub(crate) use table::Table; 12 | 13 | use std::{result::Result as StdResult, str::FromStr}; 14 | 15 | use anyhow::{Context, Result}; 16 | use tokio::process::Command; 17 | 18 | use crate::{cli::ScrapeTarget, error::IptablesError}; 19 | 20 | pub(crate) async fn iptables_save(tgt: ScrapeTarget) -> Result { 21 | let cmd = format!("{tgt}-save"); 22 | 23 | String::from_utf8( 24 | Command::new(&cmd) 25 | .arg("-c") 26 | .output() 27 | .await 28 | .with_context(|| format!("Failed to run {cmd}"))? 29 | .stdout, 30 | ) 31 | .with_context(|| format!("Failed {cmd} output to valid UTF-8")) 32 | } 33 | 34 | #[allow(dead_code)] 35 | #[derive(Copy, Clone, PartialEq, Debug)] 36 | enum Policy { 37 | Accept, 38 | Drop, 39 | } 40 | 41 | impl FromStr for Policy { 42 | type Err = IptablesError; 43 | 44 | fn from_str(s: &str) -> StdResult { 45 | match s { 46 | "Accept" | "ACCEPT" | "accept" => Ok(Self::Accept), 47 | "Drop" | "DROP" | "drop" => Ok(Self::Accept), 48 | _ => Err(IptablesError::InvalidPolicy(s.into())), 49 | } 50 | } 51 | } 52 | 53 | #[derive(Debug)] 54 | pub(crate) struct IptablesState { 55 | tables: Vec, 56 | } 57 | 58 | impl IptablesState { 59 | pub(crate) fn new() -> Self { Self { tables: Vec::new() } } 60 | 61 | pub(crate) async fn parse>(&mut self, out: S) -> Result<()> { 62 | let mut table: Option
= None; 63 | let out = out.as_ref(); 64 | for line in out.lines() { 65 | match &line.as_bytes()[0] { 66 | b'#' => continue, // Comment 67 | b'*' => { 68 | table = Some(Table::new(&line[1..])); 69 | } // table 70 | b':' => { 71 | if let Some(ref mut t) = table { 72 | t.parse_chain(line)?; 73 | } 74 | } // chain 75 | b'[' => { 76 | if let Some(ref mut t) = table { 77 | t.parse_rule(line)?; 78 | } 79 | } // rule 80 | b'C' => { 81 | if let Some(table) = table.clone() { 82 | self.tables.push(table); // End of table ('COMMIT') 83 | } 84 | } 85 | _ => unreachable!(), 86 | } 87 | } 88 | 89 | Ok(()) 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/iptables/chain.rs: -------------------------------------------------------------------------------- 1 | use anyhow::Result; 2 | 3 | use crate::{ 4 | error::IptablesError, 5 | iptables::{Counter, Policy, Rule}, 6 | parse::idx_after, 7 | }; 8 | 9 | #[derive(Clone, PartialEq, Debug)] 10 | pub(crate) struct Chain { 11 | pub(crate) name: String, 12 | pub(crate) counter: Counter, 13 | // Technically we could use policy to determine if it's builtin or not 14 | builtin: bool, 15 | policy: Option, 16 | pub(crate) rules: Vec, 17 | } 18 | 19 | impl Chain { 20 | pub(crate) fn new>(name: S) -> Self { 21 | Self { 22 | name: name.into(), 23 | counter: Counter::default(), 24 | builtin: true, 25 | policy: None, 26 | rules: Vec::new(), 27 | } 28 | } 29 | 30 | // :POSTROUTING ACCEPT [3907:262379] 31 | // ^ ^ ^ Bytes 32 | // ^ ^ Packets 33 | // ^ Policy 34 | // 35 | // :DOCKER-ISOLATION - [0:0] 36 | // ^ Custom 37 | pub(crate) fn parse_chain>(line: S) -> Result { 38 | let line = line.as_ref(); 39 | let len = line.len(); 40 | 41 | let name_start = idx_after(0, line, ':').unwrap_or(0); 42 | let name_end = idx_after(name_start, line, ' ').unwrap_or(len - 2); // -2 for name_end + 2 below 43 | 44 | let mut chain = Chain::new(line[name_start + 1..name_end].trim()); 45 | 46 | match line[name_end..name_end + 2].trim() { 47 | "-" => chain.builtin = false, 48 | _ => { 49 | let policy_start = name_end; 50 | let policy_end = idx_after(policy_start + 1, line, ' ').unwrap_or(len); 51 | 52 | let policy = line[policy_start..policy_end].trim(); 53 | chain.policy = Some( 54 | policy 55 | .parse::() 56 | .map_err(|_| IptablesError::InvalidPolicy(policy.into()))?, 57 | ); 58 | } 59 | } 60 | 61 | chain.counter = Counter::parse_counter(line); 62 | 63 | Ok(chain) 64 | } 65 | 66 | pub(crate) fn policy(&self) -> &str { 67 | match self.policy { 68 | Some(Policy::Drop) => "DROP", 69 | Some(Policy::Accept) | None => "ACCEPT", 70 | } 71 | } 72 | } 73 | 74 | #[cfg(test)] 75 | mod test { 76 | use super::*; 77 | 78 | #[test] 79 | fn chain_parse_builtin() { 80 | assert_eq!( 81 | Chain::parse_chain(":POSTROUTING ACCEPT [3907:262379]").unwrap(), 82 | Chain { 83 | name: "POSTROUTING".into(), 84 | builtin: true, 85 | policy: Some(Policy::Accept), 86 | counter: Counter { 87 | packets: 3907, 88 | bytes: 262379 89 | }, 90 | rules: Vec::new(), 91 | } 92 | ); 93 | } 94 | 95 | #[test] 96 | fn chain_parse_custom() { 97 | assert_eq!( 98 | Chain::parse_chain(":DOCKER-ISOLATION - [0:0]").unwrap(), 99 | Chain { 100 | name: "DOCKER-ISOLATION".into(), 101 | builtin: false, 102 | policy: None, 103 | counter: Counter { 104 | packets: 0, 105 | bytes: 0, 106 | }, 107 | rules: Vec::new(), 108 | } 109 | ); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/iptables/counter.rs: -------------------------------------------------------------------------------- 1 | use crate::parse::idx_after; 2 | 3 | #[derive(PartialEq, Debug, Copy, Clone, Default)] 4 | pub(crate) struct Counter { 5 | pub(crate) packets: u64, 6 | pub(crate) bytes: u64, 7 | } 8 | 9 | impl Counter { 10 | // ... [3907:262379] 11 | // ^ ^ Bytes 12 | // ^ Packets 13 | pub(crate) fn parse_counter>(line: S) -> Self { 14 | let line = line.as_ref(); 15 | let len = line.len(); 16 | let packet_start = idx_after(0, line, '[').unwrap_or(0); 17 | let packet_end = idx_after(packet_start + 1, line, ':').unwrap_or(len); 18 | 19 | let bytes_start = packet_end + 1; 20 | let bytes_end = idx_after(bytes_start, line, ']').unwrap_or(len); 21 | 22 | Self { 23 | packets: line[packet_start + 1..packet_end].parse().unwrap_or(0), 24 | bytes: line[bytes_start..bytes_end].parse().unwrap_or(0), 25 | } 26 | } 27 | 28 | #[inline] 29 | pub(crate) fn bytes(&self) -> u64 { self.bytes } 30 | 31 | #[inline] 32 | pub(crate) fn packets(&self) -> u64 { self.packets } 33 | } 34 | 35 | #[cfg(test)] 36 | mod test { 37 | use super::*; 38 | 39 | #[test] 40 | fn counter_parse_base() { 41 | assert_eq!( 42 | Counter::parse_counter("... [3907:262379]"), 43 | Counter { 44 | packets: 3907, 45 | bytes: 262379 46 | } 47 | ); 48 | } 49 | 50 | #[test] 51 | fn counter_parse_rule_0() { 52 | assert_eq!( 53 | Counter::parse_counter( 54 | "[0:0] -A LIBVIRT_OUT -o virbr0 -p tcp -m tcp --dport 68 -j ACCEPT" 55 | ), 56 | Counter { 57 | packets: 0, 58 | bytes: 0, 59 | } 60 | ); 61 | } 62 | 63 | #[test] 64 | fn counter_parse_rule() { 65 | assert_eq!( 66 | Counter::parse_counter("[607533:364542212] -A OUTPUT -j LIBVIRT_OUT"), 67 | Counter { 68 | packets: 607533, 69 | bytes: 364542212, 70 | } 71 | ); 72 | } 73 | 74 | #[test] 75 | fn counter_parse_chain_0() { 76 | assert_eq!( 77 | Counter::parse_counter(":LIBVIRT_OUT - [0:0]"), 78 | Counter { 79 | packets: 0, 80 | bytes: 0, 81 | } 82 | ); 83 | } 84 | 85 | #[test] 86 | fn counter_parse_chain() { 87 | assert_eq!( 88 | Counter::parse_counter(":FORWARD ACCEPT [3:156]"), 89 | Counter { 90 | packets: 3, 91 | bytes: 156, 92 | } 93 | ); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/iptables/metrics.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | use anyhow::Result; 4 | use prometheus::{IntCounterVec, IntGaugeVec, Opts, Registry}; 5 | use tracing::{debug, trace}; 6 | 7 | use crate::{cli::ScrapeTarget, iptables::IptablesState}; 8 | 9 | pub(crate) struct TargetMetrics { 10 | chains_total: IntGaugeVec, 11 | rules_total: IntGaugeVec, 12 | chain_bytes_total: IntCounterVec, 13 | chain_packets_total: IntCounterVec, 14 | comment_bytes_total: IntCounterVec, 15 | comment_packets_total: IntCounterVec, 16 | rule_bytes_total: IntCounterVec, 17 | rule_packets_total: IntCounterVec, 18 | } 19 | 20 | impl TargetMetrics { 21 | fn update(&mut self, state: &IptablesState) { 22 | for t in &state.tables { 23 | let ct = self.chains_total.with_label_values(&[&t.name]); 24 | ct.set(t.chains.len() as i64); 25 | 26 | for (_, c) in t.chains.iter() { 27 | let cbt = self 28 | .chain_bytes_total 29 | .with_label_values(&[&t.name, &c.name, c.policy()]); 30 | let diff = c.counter.bytes() - cbt.get(); 31 | cbt.inc_by(diff); 32 | 33 | let cpt = 34 | self.chain_packets_total 35 | .with_label_values(&[&t.name, &c.name, c.policy()]); 36 | let diff = c.counter.packets() - cpt.get(); 37 | cpt.inc_by(diff); 38 | 39 | let rt = self.rules_total.with_label_values(&[&t.name, &c.name]); 40 | rt.set(c.rules.len() as i64); 41 | 42 | for r in &c.rules { 43 | let rpt = self 44 | .rule_packets_total 45 | .with_label_values(&[&t.name, &c.name, &r.rule]); 46 | let diff = r.counter.packets() - rpt.get(); 47 | rpt.inc_by(diff); 48 | 49 | let rbt = self 50 | .rule_bytes_total 51 | .with_label_values(&[&t.name, &c.name, &r.rule]); 52 | let diff = r.counter.bytes() - rbt.get(); 53 | rbt.inc_by(diff); 54 | 55 | if let Some(cmt) = &r.comment { 56 | let cpt = self.comment_packets_total.with_label_values(&[ 57 | &t.name, 58 | &c.name, 59 | &cmt.comment, 60 | ]); 61 | let diff = cmt.counter.packets() - cpt.get(); 62 | cpt.inc_by(diff); 63 | 64 | let cbt = self.comment_bytes_total.with_label_values(&[ 65 | &t.name, 66 | &c.name, 67 | &cmt.comment, 68 | ]); 69 | let diff = cmt.counter.packets() - cbt.get(); 70 | cbt.inc_by(diff); 71 | } 72 | } 73 | } 74 | } 75 | } 76 | } 77 | 78 | pub(crate) struct Metrics { 79 | map: HashMap, 80 | } 81 | 82 | impl Metrics { 83 | pub(crate) fn new(targets: &[ScrapeTarget], r: &Registry) -> Result { 84 | trace!("Metrics::new"); 85 | 86 | let mut map = HashMap::new(); 87 | for tgt in targets { 88 | let prefix = tgt.as_ref().replace('-', "_"); 89 | 90 | let chains_total = IntGaugeVec::new( 91 | Opts::new( 92 | &format!("{prefix}_chains_total"), 93 | "Total number of chains in a table", 94 | ), 95 | &["table"], 96 | )?; 97 | 98 | let rules_total = IntGaugeVec::new( 99 | Opts::new( 100 | &format!("{prefix}_rules_total"), 101 | "Total number of rules in a chain in a table", 102 | ), 103 | &["table", "chain"], 104 | )?; 105 | 106 | let chain_bytes_total = IntCounterVec::new( 107 | Opts::new( 108 | &format!("{prefix}_chain_bytes_total"), 109 | "Total bytes flowing through a given chain", 110 | ), 111 | &["table", "chain", "policy"], 112 | )?; 113 | 114 | let chain_packets_total = IntCounterVec::new( 115 | Opts::new( 116 | &format!("{prefix}_chain_packets_total"), 117 | "Total packets flowing through a given chain", 118 | ), 119 | &["table", "chain", "policy"], 120 | )?; 121 | 122 | let rule_bytes_total = IntCounterVec::new( 123 | Opts::new( 124 | &format!("{prefix}_rule_bytes_total"), 125 | "Total bytes matching a given rule", 126 | ), 127 | &["table", "chain", "rule"], 128 | )?; 129 | 130 | let rule_packets_total = IntCounterVec::new( 131 | Opts::new( 132 | &format!("{prefix}_rule_packets_total"), 133 | "Total packets matching a given rule", 134 | ), 135 | &["table", "chain", "rule"], 136 | )?; 137 | 138 | let comment_bytes_total = IntCounterVec::new( 139 | Opts::new( 140 | &format!("{prefix}_comment_bytes_total"), 141 | "Total bytes matching a given comment inside a rule", 142 | ), 143 | &["table", "chain", "comment"], 144 | )?; 145 | 146 | let comment_packets_total = IntCounterVec::new( 147 | Opts::new( 148 | &format!("{prefix}_comment_packets_total"), 149 | "Total packets matching a given comment inside a rule", 150 | ), 151 | &["table", "chain", "comment"], 152 | )?; 153 | 154 | debug!("Registering {prefix} metrics"); 155 | r.register(Box::new(chain_bytes_total.clone()))?; 156 | r.register(Box::new(chain_packets_total.clone()))?; 157 | r.register(Box::new(comment_bytes_total.clone()))?; 158 | r.register(Box::new(comment_packets_total.clone()))?; 159 | r.register(Box::new(rule_bytes_total.clone()))?; 160 | r.register(Box::new(rule_packets_total.clone()))?; 161 | r.register(Box::new(rules_total.clone()))?; 162 | r.register(Box::new(chains_total.clone()))?; 163 | map.insert( 164 | tgt.to_string(), 165 | TargetMetrics { 166 | chains_total, 167 | rules_total, 168 | chain_bytes_total, 169 | chain_packets_total, 170 | comment_bytes_total, 171 | comment_packets_total, 172 | rule_bytes_total, 173 | rule_packets_total, 174 | }, 175 | ); 176 | } 177 | 178 | Ok(Self { map }) 179 | } 180 | 181 | pub(crate) fn update(&mut self, tgt: ScrapeTarget, state: &IptablesState) { 182 | if let Some(tgt_metrics) = self.map.get_mut(tgt.as_ref()) { 183 | tgt_metrics.update(state); 184 | } 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /src/iptables/rule.rs: -------------------------------------------------------------------------------- 1 | use crate::{iptables::Counter, parse::idx_after}; 2 | 3 | use anyhow::Result; 4 | 5 | macro_rules! regex { 6 | ($re:literal $(,)?) => {{ 7 | static RE: once_cell::sync::OnceCell = once_cell::sync::OnceCell::new(); 8 | RE.get_or_init(|| regex::Regex::new($re).unwrap()) 9 | }}; 10 | } 11 | 12 | #[derive(Clone, Debug, PartialEq)] 13 | pub(crate) struct Comment { 14 | pub(crate) comment: String, 15 | pub(crate) counter: Counter, 16 | } 17 | 18 | impl Comment { 19 | pub(crate) fn new>(c: S) -> Self { 20 | Self { 21 | comment: c.into(), 22 | counter: Counter::default(), 23 | } 24 | } 25 | } 26 | 27 | #[derive(Clone, Debug, PartialEq)] 28 | pub(crate) struct Rule { 29 | pub(crate) rule: String, 30 | pub(crate) counter: Counter, 31 | pub(crate) comment: Option, 32 | } 33 | 34 | impl Rule { 35 | pub(crate) fn parse_rule>(line: S) -> Result<(String, Self)> { 36 | let line = line.as_ref(); 37 | let counter = Counter::parse_counter(line); 38 | let counter_end = idx_after(0, line, ']').unwrap_or(0); 39 | let flag = idx_after(counter_end, line, 'A').unwrap_or(0); 40 | let chain_start = idx_after(flag, line, ' ').unwrap_or(0); 41 | let chain_end = idx_after(chain_start + 2, line, ' ').unwrap_or(line.len()); 42 | let chain = line[chain_start..chain_end].trim().into(); 43 | let after_chain = line[chain_end..].trim(); 44 | let re = regex!(r#"--comment +"((?:[^"\\]|\\.)*)""#); 45 | let re_no_quotes = regex!(r#"--comment +((?:[^ "\\]|\\.)*)"#); 46 | let re_rm = regex!(r#"-m +comment +--comment +"?(?:[^"\\]|\\.)*"?"#); 47 | let comment = if let Some(caps) = re.captures(after_chain) { 48 | caps.get(1).map(|m| m.as_str().to_owned()) 49 | } else if let Some(caps) = re_no_quotes.captures(after_chain) { 50 | caps.get(1).map(|m| m.as_str().to_owned()) 51 | } else { 52 | None 53 | }; 54 | 55 | Ok(( 56 | chain, 57 | Self { 58 | rule: re_rm.replace(line[chain_end..].trim(), "").trim().into(), 59 | comment: comment.map(Comment::new), 60 | counter, 61 | }, 62 | )) 63 | } 64 | } 65 | 66 | #[cfg(test)] 67 | mod test { 68 | use super::*; 69 | 70 | #[test] 71 | fn rule_parse_no_traffic() { 72 | assert_eq!( 73 | Rule::parse_rule("[0:0] -A LIBVIRT_PRT -s 192.168.122.0/24 ! -d 192.168.122.0/24 -p tcp -j MASQUERADE --to-ports 1024-65535").unwrap(), 74 | ("LIBVIRT_PRT".into(), 75 | Rule { 76 | rule: "-s 192.168.122.0/24 ! -d 192.168.122.0/24 -p tcp -j MASQUERADE --to-ports 1024-65535".into(), 77 | comment: None, 78 | counter: Counter { 79 | packets: 0, 80 | bytes: 0, 81 | }, 82 | }) 83 | ); 84 | } 85 | 86 | #[test] 87 | fn rule_parse_traffic() { 88 | assert_eq!( 89 | Rule::parse_rule("[607613:364557889] -A POSTROUTING -j LIBVIRT_PRT").unwrap(), 90 | ( 91 | "POSTROUTING".into(), 92 | Rule { 93 | rule: "-j LIBVIRT_PRT".into(), 94 | comment: None, 95 | counter: Counter { 96 | packets: 607613, 97 | bytes: 364557889, 98 | }, 99 | } 100 | ) 101 | ); 102 | } 103 | 104 | #[test] 105 | fn rule_parse_comment() { 106 | assert_eq!( 107 | Rule::parse_rule("[607613:364557889] -A POSTROUTING -j LIBVIRT_PRT -m comment --comment \"test comment\"").unwrap(), 108 | ( 109 | "POSTROUTING".into(), 110 | Rule { 111 | rule: "-j LIBVIRT_PRT".into(), 112 | comment: Some(Comment::new("test comment")), 113 | counter: Counter { 114 | packets: 607613, 115 | bytes: 364557889, 116 | }, 117 | } 118 | ) 119 | ); 120 | } 121 | 122 | #[test] 123 | fn rule_parse_comment_escapes() { 124 | assert_eq!( 125 | Rule::parse_rule( 126 | "[0:0] -A POSTROUTING -m comment --comment \"test 'foo' \\\"comment\"" 127 | ) 128 | .unwrap(), 129 | ( 130 | "POSTROUTING".into(), 131 | Rule { 132 | rule: "".into(), 133 | comment: Some(Comment::new("test 'foo' \\\"comment")), 134 | counter: Counter::default() 135 | } 136 | ) 137 | ); 138 | } 139 | 140 | #[test] 141 | fn rule_parse_comment_no_quote() { 142 | assert_eq!( 143 | Rule::parse_rule("[0:0] -A POSTROUTING -m comment --comment TEST-COMMENT").unwrap(), 144 | ( 145 | "POSTROUTING".into(), 146 | Rule { 147 | rule: "".into(), 148 | comment: Some(Comment::new("TEST-COMMENT")), 149 | counter: Counter::default(), 150 | } 151 | ) 152 | ); 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /src/iptables/table.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | use anyhow::Result; 4 | 5 | use crate::iptables::{Chain, Rule}; 6 | 7 | #[derive(Clone, Debug)] 8 | pub(crate) struct Table { 9 | pub(crate) name: String, 10 | pub(crate) chains: HashMap, 11 | } 12 | 13 | impl Table { 14 | pub(crate) fn new>(name: S) -> Self { 15 | Self { 16 | name: name.into(), 17 | chains: HashMap::new(), 18 | } 19 | } 20 | 21 | pub(crate) fn parse_chain>(&mut self, line: S) -> Result<()> { 22 | let chain = Chain::parse_chain(line)?; 23 | self.chains.insert(chain.name.clone(), chain); 24 | Ok(()) 25 | } 26 | 27 | pub(crate) fn parse_rule>(&mut self, line: S) -> Result<()> { 28 | let (chain, rule) = Rule::parse_rule(line)?; 29 | let chain = self 30 | .chains 31 | .entry(chain.clone()) 32 | .or_insert_with(|| Chain::new(chain)); 33 | 34 | chain.rules.push(rule); 35 | Ok(()) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/macros.rs: -------------------------------------------------------------------------------- 1 | macro_rules! unwrap_or_exit { 2 | ($e:expr) => {{ 3 | use std::process; 4 | use tracing::error; 5 | ($e).map_err(|e| { 6 | error!("{}", e); 7 | eprintln!("error: {}", e); 8 | process::exit(1); 9 | }) 10 | .unwrap() 11 | }}; 12 | } 13 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | mod macros; 3 | mod cli; 4 | mod error; 5 | mod iptables; 6 | mod parse; 7 | 8 | use std::{ 9 | collections::HashMap, 10 | env, 11 | net::SocketAddr, 12 | sync::{ 13 | atomic::{AtomicBool, Ordering}, 14 | Arc, Mutex, 15 | }, 16 | }; 17 | 18 | use clap::Parser; 19 | use prometheus::{IntGauge, Registry}; 20 | use prometheus_hyper::Server; 21 | use tokio::time::{Duration, Instant}; 22 | use tracing::{debug, info}; 23 | 24 | use crate::iptables::{iptables_save, IptablesState, Metrics}; 25 | 26 | #[tokio::main(flavor = "current_thread")] 27 | async fn main() { 28 | let args = cli::Args::parse(); 29 | 30 | match args.verbose { 31 | 0 => match args.quiet { 32 | 0 => env::set_var("RUST_LOG", "iptables_exporter=info"), 33 | 1 => env::set_var("RUST_LOG", "iptables_exporter=warn"), 34 | 2 => env::set_var("RUST_LOG", "iptables_exporter=error"), 35 | _ => env::set_var("RUST_LOG", "iptables_exporter=off"), 36 | }, 37 | 1 => env::set_var("RUST_LOG", "iptables_exporter=debug"), 38 | _ => env::set_var("RUST_LOG", "iptables_exporter=trace"), 39 | } 40 | 41 | tracing_subscriber::fmt::init(); 42 | 43 | let running = Arc::new(AtomicBool::new(true)); 44 | 45 | info!("Registering metrics..."); 46 | let registry = Arc::new(Registry::new()); 47 | let metrics = Arc::new(Mutex::new(unwrap_or_exit!(Metrics::new( 48 | &args.scrape_targets, 49 | ®istry 50 | )))); 51 | 52 | let mut scrape_durations = HashMap::new(); 53 | let mut scrape_successes = HashMap::new(); 54 | for tgt in &args.scrape_targets { 55 | let tgt_str = tgt.to_string(); 56 | let prefix = tgt_str.replace('-', "_"); 57 | let d = unwrap_or_exit!(IntGauge::new( 58 | &format!("{prefix}_scrape_duration_milliseconds"), 59 | "Duration in milliseconds of the scrape", 60 | )); 61 | let s = unwrap_or_exit!(IntGauge::new( 62 | &format!("{prefix}_scrape_success"), 63 | "If the scrape was a success" 64 | )); 65 | scrape_durations.insert(tgt_str.clone(), d.clone()); 66 | scrape_successes.insert(tgt_str.clone(), s.clone()); 67 | debug!("Registering {tgt_str} scrape metrics..."); 68 | unwrap_or_exit!(registry.register(Box::new(d))); 69 | unwrap_or_exit!(registry.register(Box::new(s))); 70 | } 71 | 72 | let scrape_durations = Arc::new(Mutex::new(scrape_durations)); 73 | let scrape_successes = Arc::new(Mutex::new(scrape_successes)); 74 | 75 | info!("Spawning server..."); 76 | tokio::spawn(Server::run( 77 | Arc::clone(®istry), 78 | SocketAddr::new(args.listen_address, args.listen_port), 79 | shutdown_signal(Arc::clone(&running)), 80 | )); 81 | 82 | let mut collect_int = tokio::time::interval(Duration::from_secs(args.collect_interval)); 83 | while running.load(Ordering::Relaxed) { 84 | // .cloned() required becuase of async move 85 | #[allow(clippy::unnecessary_to_owned)] 86 | for tgt in args.scrape_targets.iter().cloned() { 87 | let scrape_durations = scrape_durations.clone(); 88 | let scrape_successes = scrape_successes.clone(); 89 | let metrics = metrics.clone(); 90 | tokio::task::spawn(async move { 91 | info!("Collecting {tgt} metrics..."); 92 | let before = Instant::now(); 93 | let out = unwrap_or_exit!(iptables_save(tgt).await); 94 | 95 | let mut state = IptablesState::new(); 96 | unwrap_or_exit!(state.parse(&*out).await); 97 | 98 | debug!("Updating {tgt} metrics..."); 99 | if let Ok(mut guard) = metrics.lock() { 100 | guard.update(tgt, &state); 101 | }; 102 | let after = Instant::now(); 103 | 104 | let elapsed = after.duration_since(before); 105 | if let Ok(mut guard) = scrape_durations.lock() { 106 | let guage = guard.get_mut(&tgt.to_string()).unwrap(); 107 | guage.set((elapsed.as_secs() * 1000 + elapsed.subsec_millis() as u64) as i64); 108 | } 109 | if let Ok(mut guard) = scrape_successes.lock() { 110 | let guage = guard.get_mut(&tgt.to_string()).unwrap(); 111 | guage.set(1); 112 | } 113 | }); 114 | } 115 | debug!("Sleeping..."); 116 | collect_int.tick().await; 117 | } 118 | info!("Stopped the exporter"); 119 | } 120 | 121 | async fn shutdown_signal(running: Arc) { 122 | // Wait for the CTRL+C Signal 123 | tokio::signal::ctrl_c() 124 | .await 125 | .expect("Failed to install CTRL+C signal handler"); 126 | running.store(false, Ordering::Relaxed); 127 | } 128 | -------------------------------------------------------------------------------- /src/parse.rs: -------------------------------------------------------------------------------- 1 | pub(crate) fn idx_after(start: usize, haystack: &str, needle: char) -> Option { 2 | haystack[start..].find(needle).map(|i| i + start) 3 | } 4 | --------------------------------------------------------------------------------