├── .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 |
--------------------------------------------------------------------------------