Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 26 additions & 3 deletions .github/actions/package-archive/action.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
name: 'Package Release Archive'
description: >-
Stage a built rustnet binary with the services asset, README and LICENSE in
the release-archive layout and pack it as tar.gz or zip.
Stage a built rustnet binary with runtime assets, service examples,
documentation and LICENSE, then pack it as tar.gz or zip.

# The staging layout is a cross-job contract: package-installers, package-macos
# and package-windows in release.yml (and the Homebrew formula) unpack
# rustnet-<version>-<target>/{rustnet[.exe],assets/services,README.md,LICENSE},
# rustnet-<version>-<target>/{rustnet[.exe],assets/services,
# resources/packaging/<platform>,README.md,SERVICE*.md,LICENSE},
# so every release build must produce it through this action.

inputs:
Expand Down Expand Up @@ -45,6 +46,28 @@ runs:
cp "crates/rustnet-core/assets/services" "$staging/assets/"
fi

cp SERVICE.md SERVICE.zh-CN.md SERVICE.ja.md "$staging/"
case "${{ inputs.target }}" in
*-unknown-linux-*)
mkdir -p "$staging/resources/packaging/linux"
cp -R resources/packaging/linux/systemd "$staging/resources/packaging/linux/"
cp -R resources/packaging/linux/logrotate "$staging/resources/packaging/linux/"
cp compose.headless.yml "$staging/"
;;
*-apple-darwin)
mkdir -p "$staging/resources/packaging/macos"
cp -R resources/packaging/macos/launchd "$staging/resources/packaging/macos/"
;;
*-freebsd*)
mkdir -p "$staging/resources/packaging/freebsd"
cp -R resources/packaging/freebsd/rc.d "$staging/resources/packaging/freebsd/"
;;
*-windows-*)
# The MSI installs the native SCM definition. Raw archives include
# the service guide but do not mutate the host.
;;
esac

cp README.md "$staging/"
cp LICENSE "$staging/" 2>/dev/null || true

Expand Down
33 changes: 33 additions & 0 deletions .github/workflows/build-platforms.yml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,39 @@ jobs:
default-features: ${{ (contains(matrix.target, 'linux') || contains(matrix.target, 'apple')) && 'true' || 'false' }}
strip-symbols: ${{ inputs.strip-symbols && 'true' || 'false' }}

- name: Validate Windows MSI authoring
if: matrix.target == 'x86_64-pc-windows-msvc'
shell: powershell
run: |
$wixZip = "$env:RUNNER_TEMP\wix-binaries.zip"
$wixDir = "$env:RUNNER_TEMP\wix"
Invoke-WebRequest `
-Uri "https://github.com/wixtoolset/wix3/releases/download/wix3112rtm/wix311-binaries.zip" `
-OutFile $wixZip
$expected = "2c1888d5d1dba377fc7fa14444cf556963747ff9a0a289a3599cf09da03b9e2e"
$actual = (Get-FileHash $wixZip -Algorithm SHA256).Hash.ToLower()
if ($actual -ne $expected) {
throw "WiX zip checksum mismatch: expected $expected, got $actual"
}
Expand-Archive -LiteralPath $wixZip -DestinationPath $wixDir -Force

New-Item -ItemType Directory -Path assets -Force | Out-Null
Copy-Item crates\rustnet-core\assets\services assets\services -Force
$outputDir = "target\wix-validation"
New-Item -ItemType Directory -Path $outputDir -Force | Out-Null
$binDir = "target\${{ matrix.target }}\release"
& "$wixDir\candle.exe" -nologo -arch x64 `
"-dCargoTargetBinDir=$binDir" `
"-dVersion=1.6.0" `
"-dPlatform=x64" `
-out "$outputDir\main.wixobj" `
resources\packaging\windows\wix\main.wxs
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
& "$wixDir\light.exe" -nologo `
-out "$outputDir\Rustnet.msi" `
"$outputDir\main.wixobj"
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }

- name: Run tests
if: matrix.run-tests
run: cargo test --verbose
Expand Down
5 changes: 4 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -359,13 +359,16 @@ jobs:
sed -i'.bak' -e "s/0\.0\.0/${VERSION}/g" -e "s/fffffff/${GITHUB_SHA:0:7}/g" resources/packaging/macos/Info.plist

# Create app bundle
mkdir -p "Rustnet.app/Contents/"{MacOS,Resources/assets}
mkdir -p "Rustnet.app/Contents/"{MacOS,Resources/assets,Resources/service/launchd}
cp resources/packaging/macos/Info.plist "Rustnet.app/Contents/"
cp resources/packaging/macos/graphics/rustnet.icns "Rustnet.app/Contents/Resources/"
cp "rustnet-${RELEASE_TAG}-${{ matrix.target }}/rustnet" "Rustnet.app/Contents/MacOS/"
cp resources/packaging/macos/wrapper.sh "Rustnet.app/Contents/MacOS/"
cp "rustnet-${RELEASE_TAG}-${{ matrix.target }}/assets/services" "Rustnet.app/Contents/Resources/assets/"
cp resources/packaging/macos/launchd/* "Rustnet.app/Contents/Resources/service/launchd/"
cp SERVICE.md SERVICE.zh-CN.md SERVICE.ja.md "Rustnet.app/Contents/Resources/service/"
chmod +x "Rustnet.app/Contents/MacOS/"{rustnet,wrapper.sh}
chmod +x "Rustnet.app/Contents/Resources/service/launchd/install-rustnet-headless.sh"

- name: Code sign and notarize app bundle
env:
Expand Down
13 changes: 13 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ on:
- 'build.rs'
- 'benches/**'
- 'Dockerfile'
- 'compose.headless.yml'
- 'resources/packaging/**'
- 'scripts/check-service-packaging.sh'
- '.cargo/audit.toml'
- '.github/workflows/rust.yml'
pull_request:
Expand All @@ -23,6 +26,9 @@ on:
- 'build.rs'
- 'benches/**'
- 'Dockerfile'
- 'compose.headless.yml'
- 'resources/packaging/**'
- 'scripts/check-service-packaging.sh'
- '.cargo/audit.toml'
- '.github/workflows/rust.yml'
workflow_dispatch:
Expand All @@ -43,6 +49,8 @@ jobs:
uses: ./.github/actions/setup-linux-deps
- name: Check formatting
run: cargo fmt --check
- name: Validate service packaging
run: scripts/check-service-packaging.sh
- name: Validate dependency lockfile
run: cargo check --locked --workspace --all-targets --all-features
- name: Check without default features
Expand Down Expand Up @@ -81,3 +89,8 @@ jobs:
tags: rustnet:ci-test
- name: Verify Docker image
run: docker run --rm rustnet:ci-test --version
- name: Verify headless Docker startup
run: |
docker run --rm --network host --cap-add NET_RAW \
rustnet:ci-test --headless --duration 1 --output json >/tmp/rustnet-headless.json
test -s /tmp/rustnet-headless.json
11 changes: 9 additions & 2 deletions .github/workflows/test-platform-builds.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ on:
- 'Cross.toml'
- 'src/**'
- 'crates/**'
- 'Dockerfile'
- 'compose.headless.yml'
- 'resources/packaging/**'
- 'scripts/check-service-packaging.sh'
- '.github/workflows/test-platform-builds.yml'
- '.github/workflows/build-platforms.yml'
- '.github/actions/**'
Expand All @@ -30,7 +34,7 @@ jobs:
build:
uses: ./.github/workflows/build-platforms.yml
with:
create-archives: ${{ inputs.create-archives || false }}
create-archives: ${{ github.event_name == 'pull_request' || inputs.create-archives || false }}
strip-symbols: false
version: test-${{ github.run_id }}

Expand All @@ -48,7 +52,10 @@ jobs:
release: '14.2'
usesh: true
prepare: pkg install -y curl libpcap rust
run: cargo build --locked --verbose --release --no-default-features
run: |
sh -n resources/packaging/freebsd/rc.d/rustnet_headless
sh -n resources/packaging/freebsd/rc.d/install-rustnet-headless.sh
cargo build --locked --verbose --release --no-default-features

trigger-freebsd-build:
name: trigger-freebsd-build
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]

### Added
- **Opt-in Headless Services**: inactive service definitions for systemd,
launchd, Windows SCM, FreeBSD rc.d, and Docker Compose use explicit headless
commands and a 5000 ms refresh interval. `--output-file` securely writes
JSONL by appending or one final JSON snapshot by replacement
- **Headless Mode**: `--headless` runs without the TUI, with optional
`--duration` and shared `--filter` syntax. Versioned snapshots stream as
JSONL by default, while `--output json` emits one final snapshot. Stdout is
Expand Down
30 changes: 29 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ windows = { workspace = true, features = [
"Win32_System_Console",
"Win32_System_JobObjects",
"Win32_System_LibraryLoader",
"Win32_System_Services",
"Win32_System_SystemInformation",
"Win32_System_Threading",
] }
Expand Down Expand Up @@ -188,6 +189,7 @@ Features:
depends = "libpcap0.8, libelf1"
section = "net"
priority = "optional"
maintainer-scripts = "debian"
assets = [
[
"target/release/rustnet",
Expand All @@ -214,16 +216,42 @@ assets = [
"usr/share/applications/",
"644",
],
[
"resources/packaging/linux/systemd/rustnet-headless.service",
"usr/lib/systemd/system/rustnet-headless.service",
"644",
],
[
"resources/packaging/linux/systemd/rustnet-headless.env",
"etc/default/rustnet-headless",
"644",
],
[
"resources/packaging/linux/logrotate/rustnet-headless",
"etc/logrotate.d/rustnet-headless",
"644",
],
[
"SERVICE.md",
"usr/share/doc/rustnet-monitor/",
"644",
],
]
conf-files = []

[package.metadata.generate-rpm]
post_install_script = "resources/packaging/linux/rpm/post_install.sh"
pre_uninstall_script = "resources/packaging/linux/rpm/pre_uninstall.sh"
post_uninstall_script = "resources/packaging/linux/rpm/post_uninstall.sh"
assets = [
{ source = "target/release/rustnet", dest = "/usr/bin/rustnet", mode = "755" },
{ source = "README.md", dest = "/usr/share/doc/rustnet-monitor/README.md", mode = "644" },
{ source = "crates/rustnet-core/assets/services", dest = "/usr/share/rustnet-monitor/services", mode = "644" },
{ source = "resources/packaging/linux/graphics/rustnet.png", dest = "/usr/share/icons/hicolor/256x256/apps/rustnet.png", mode = "644" },
{ source = "resources/packaging/linux/rustnet.desktop", dest = "/usr/share/applications/rustnet.desktop", mode = "644" },
{ source = "resources/packaging/linux/systemd/rustnet-headless.service", dest = "/usr/lib/systemd/system/rustnet-headless.service", mode = "644" },
{ source = "resources/packaging/linux/systemd/rustnet-headless.env", dest = "/etc/default/rustnet-headless", mode = "644", config = "noreplace" },
{ source = "resources/packaging/linux/logrotate/rustnet-headless", dest = "/etc/logrotate.d/rustnet-headless", mode = "644", config = "noreplace" },
{ source = "SERVICE.md", dest = "/usr/share/doc/rustnet-monitor/SERVICE.md", mode = "644", doc = true },
]
[package.metadata.generate-rpm.requires]
libpcap = "*"
Expand Down
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -108,4 +108,5 @@ LABEL org.opencontainers.image.licenses="Apache License, Version 2.0"
# /proc-based process detection.
# CAP_NET_ADMIN is NOT required (read-only, non-promiscuous capture).
USER rustnet
STOPSIGNAL SIGTERM
ENTRYPOINT ["rustnet"]
4 changes: 3 additions & 1 deletion README.ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,10 @@ rustnet --pcapng-export capture.pcapng # 注釈付き PCAPNG を出力
rustnet --headless # JSONL スナップショットをストリーミング出力
rustnet --headless --duration 30 --output json # 最終スナップショットを 1 件出力
rustnet --headless --filter 'process:curl app:https' # 接続フィルターを適用
rustnet --headless --output-file snapshots.jsonl # 非公開ファイルへ JSONL を追記
```

ヘッドレスモードの既定は `--output jsonl` で、設定された更新間隔ごとにバージョン付きスナップショットを出力します。`--output json` は監視終了時にバージョン付きの最終スナップショットを 1 件出力します。`--duration` は指定した秒数後にキャプチャを停止し、`--filter` は TUI と同じ構文を受け付けます。ヘッドレスモードでは stdout に機械可読の出力だけを書き込みます。キャプチャの起動に失敗した場合は、ゼロ以外の終了ステータスを返します。
ヘッドレスモードの既定は `--output jsonl` で、設定された更新間隔ごとにバージョン付きスナップショットを出力します。`--output json` は監視終了時にバージョン付きの最終スナップショットを 1 件出力します。`--duration` は指定した秒数後にキャプチャを停止し、`--filter` は TUI と同じ構文を受け付けます。`--output-file` は stdout の代わりに非公開ファイルへ直接書き込み、JSONL は追記、JSON は置換します。ヘッドレスモードでは stdout に機械可読の出力だけを書き込みます。キャプチャの起動に失敗した場合は、ゼロ以外の終了ステータスを返します。systemd、launchd、Windows、FreeBSD、Docker Compose での明示的な有効化方法は [SERVICE.ja.md](SERVICE.ja.md) を参照してください

テーマと各色の上書きは `~/.config/rustnet/config.toml` でも設定できます(`--theme` が優先)。詳細は [USAGE.md](USAGE.md#--theme-preset) を参照してください。

Expand Down Expand Up @@ -152,6 +153,7 @@ RustNet は非プロミスキャスな読み取り専用キャプチャを行い

- [INSTALL.md](INSTALL.md): 詳細なインストール、権限設定、トラブルシューティング
- [USAGE.md](USAGE.md): 詳細な使用方法
- [SERVICE.ja.md](SERVICE.ja.md): ヘッドレスサービスの有効化、運用、セキュリティ、出力保持
- [ARCHITECTURE.md](ARCHITECTURE.md): 設計とプラットフォーム別実装
- [CONTRIBUTING.md](CONTRIBUTING.md): コントリビューションガイド

Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,9 +201,10 @@ The TUI remains the default. For scripts and services, use headless mode:
rustnet --headless # Stream JSONL snapshots
rustnet --headless --duration 30 --output json # Emit one final snapshot
rustnet --headless --filter 'process:curl app:https' # Apply a connection filter
rustnet --headless --output-file snapshots.jsonl # Append JSONL to a private file
```

`--output jsonl` is the headless default and streams versioned snapshots at the configured refresh interval. `--output json` emits one final versioned snapshot when monitoring stops. `--duration` stops capture after the requested number of seconds, and `--filter` accepts the same syntax as the TUI. In headless mode, stdout contains machine-readable output only. Capture startup failures exit with a nonzero status.
`--output jsonl` is the headless default and streams versioned snapshots at the configured refresh interval. `--output json` emits one final versioned snapshot when monitoring stops. `--duration` stops capture after the requested number of seconds, and `--filter` accepts the same syntax as the TUI. `--output-file` writes directly to a private file instead of stdout, appending JSONL or replacing JSON. In headless mode, stdout contains machine-readable output only. Capture startup failures exit with a nonzero status. See [SERVICE.md](SERVICE.md) for opt-in systemd, launchd, Windows, FreeBSD, and Docker Compose operation.

The theme and per-color overrides can also be set in `~/.config/rustnet/config.toml`; `--theme` takes precedence. See [USAGE.md](USAGE.md#--theme-preset) for the schema.

Expand Down Expand Up @@ -322,6 +323,7 @@ See [USAGE.md](USAGE.md) for complete timeout details.

- **[INSTALL.md](INSTALL.md)** - Detailed installation instructions for all platforms, permission setup, and troubleshooting
- **[USAGE.md](USAGE.md)** - Complete usage guide including command-line options, filtering, sorting, and logging
- **[SERVICE.md](SERVICE.md)** - Opt-in headless service setup, operation, security, and output retention
- **[SECURITY.md](SECURITY.md)** - Security features including Landlock sandboxing and privilege management
- **[ARCHITECTURE.md](ARCHITECTURE.md)** - Technical architecture, platform implementations, and performance details
- **[CONTRIBUTING.md](CONTRIBUTING.md)** - Contribution workflow, quality requirements, and project guidelines
Expand Down
4 changes: 3 additions & 1 deletion README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,9 +201,10 @@ rustnet --pcapng-export capture.pcapng # 导出带注释的 PCAPNG
rustnet --headless # 流式输出 JSONL 快照
rustnet --headless --duration 30 --output json # 输出一份最终快照
rustnet --headless --filter 'process:curl app:https' # 应用连接过滤器
rustnet --headless --output-file snapshots.jsonl # 将 JSONL 追加到私有文件
```

无界面模式默认使用 `--output jsonl`,按配置的刷新间隔流式输出带版本号的快照。`--output json` 会在监控停止时输出一份带版本号的最终快照。`--duration` 会在指定秒数后停止抓包,`--filter` 接受与 TUI 相同的语法。无界面模式的 stdout 仅包含机器可读输出。抓包启动失败时,程序会以非零状态退出。
无界面模式默认使用 `--output jsonl`,按配置的刷新间隔流式输出带版本号的快照。`--output json` 会在监控停止时输出一份带版本号的最终快照。`--duration` 会在指定秒数后停止抓包,`--filter` 接受与 TUI 相同的语法。`--output-file` 会直接写入私有文件而不是 stdout,JSONL 会追加,JSON 会替换。无界面模式的 stdout 仅包含机器可读输出。抓包启动失败时,程序会以非零状态退出。systemd、launchd、Windows、FreeBSD 与 Docker Compose 的显式启用方法见 [SERVICE.zh-CN.md](SERVICE.zh-CN.md)

主题及各颜色的覆盖也可在 `~/.config/rustnet/config.toml` 中设置;`--theme` 优先。配置格式见 [USAGE.zh-CN.md](USAGE.zh-CN.md#--theme-preset)。

Expand Down Expand Up @@ -320,6 +321,7 @@ RustNet 在移除连接前会先通过智能超时机制与视觉提示给出预

- **[INSTALL.zh-CN.md](INSTALL.zh-CN.md)** —— 各平台的详细安装说明、权限配置与排障
- **[USAGE.zh-CN.md](USAGE.zh-CN.md)** —— 完整使用手册,涵盖命令行参数、过滤、排序与日志
- **[SERVICE.zh-CN.md](SERVICE.zh-CN.md)**:无界面服务的显式启用、运行、安全与输出保留
- **[SECURITY.zh-CN.md](SECURITY.zh-CN.md)** —— 安全特性,包括 Landlock 沙箱与权限管理
- **[ARCHITECTURE.zh-CN.md](ARCHITECTURE.zh-CN.md)** —— 技术架构、各平台实现与性能细节
- **[CONTRIBUTING.zh-CN.md](CONTRIBUTING.zh-CN.md)** —— 贡献指南,包括工作流、质量要求与 AI 辅助贡献规范
Expand Down
Loading