Compare commits

..
Author SHA1 Message Date
Ian 5c50344062 Rotate the service log daily with tracing-appender 2026-10-22 14:37:48 -04:00
Ian 9c85bd84e5 Free the parsed security descriptor on drop instead of through a closure 2026-10-22 14:17:11 -04:00
Ian 78172519f0 Use schannel for the root store 2026-10-22 14:03:26 -04:00
Ian 902afd031d Explain the data folder ACL and the root store arguments 2026-10-22 13:52:02 -04:00
Ian Graham Martinez 19d29f1ea6 Screen redirected registry traffic in a Windows service
Each registry host gets its own loopback address, where a LocalSystem
service serves mitm_service, connecting upstream through a resolver that
ignores the hosts file. It trusts its CA machine-wide and serves the empty
CRL that schannel needs.

The service writes the hosts-file block once it listens. Pausing it removes
the block and continuing rewrites it; a stop, crash or shutdown leaves it,
so a restart fails closed and picks up a changed host list.
2026-10-22 11:48:15 -04:00
7 changed files with 28 additions and 29 deletions

No files matched your search

-4
View File
@@ -32,10 +32,6 @@ path = "src/main.rs"
name = "firewall-service"
path = "src/bin/firewall-service.rs"
[[bin]]
name = "firewall-uninstall"
path = "src/bin/firewall-uninstall.rs"
[[example]]
name = "proxy-test"
path = "tests/proxy-test/main.rs"
-16
View File
@@ -1,16 +0,0 @@
//! Run as root by the macOS app's uninstall.
#[cfg(target_os = "macos")]
fn main() {
firewall::init_logging("info");
if let Err(e) = firewall::os::macos::uninstall() {
tracing::error!("could not uninstall: {e}");
firewall::telemetry::error("uninstall");
firewall::telemetry::flush();
std::process::exit(1)
}
}
/// Only macOS installs anything system-wide.
#[cfg(not(target_os = "macos"))]
fn main() {}
+13
View File
@@ -12,6 +12,10 @@ fn main() {
firewall::init_logging("info");
serve()
}
if matches.subcommand_matches("uninstall").is_some() {
firewall::init_logging("info");
uninstall()
}
let mut command = matches.get_many::<String>("COMMAND").unwrap().cloned();
let program = command.next().unwrap();
firewall::init_logging("warn");
@@ -40,6 +44,8 @@ fn options() -> Command {
Command::new("serve")
.about("Serve a local registry for package managers configured to use it"),
)
// Run as root by the macOS app's uninstall.
.subcommand(Command::new("uninstall").hide(true))
.arg(
Arg::new("COMMAND")
.help("A command to run with its package downloads screened")
@@ -70,6 +76,13 @@ fn serve() -> ! {
}
}
fn uninstall() -> ! {
match firewall::os::uninstall() {
Ok(()) => exit(0),
Err(e) => fail("uninstall", &format!("could not uninstall: {e}")),
}
}
fn run(invocation: Invocation) -> ! {
telemetry::set_mode("wrapper");
let command = &invocation.program;
+7 -1
View File
@@ -4,10 +4,16 @@ pub mod macos;
pub mod windows;
#[cfg(target_os = "macos")]
pub use macos::system_config;
pub use macos::{system_config, uninstall};
#[cfg(windows)]
pub use windows::system_config;
/// Elsewhere nothing is installed system-wide.
#[cfg(not(target_os = "macos"))]
pub fn uninstall() -> Result<(), rama::error::BoxError> {
Ok(())
}
#[cfg(not(any(target_os = "macos", windows)))]
pub fn system_config() -> Option<std::path::PathBuf> {
None
+3 -3
View File
@@ -280,10 +280,10 @@ final class FirewallModel: NSObject, ObservableObject {
return true
}
/// The extension wrote these as root, so the bundled firewall-uninstall removes them behind an admin prompt; returns what to report if it failed.
/// The extension wrote these as root, so the bundled CLI removes them behind an admin prompt; returns what to report if it failed.
private func removeStoredCA() -> String? {
let uninstaller = Bundle.main.path(forAuxiliaryExecutable: "firewall-uninstall") ?? ""
let script = "do shell script quoted form of \"\(uninstaller)\" with administrator privileges"
let cli = Bundle.main.path(forAuxiliaryExecutable: "firewall") ?? ""
let script = "do shell script quoted form of \"\(cli)\" & \" uninstall\" with administrator privileges"
var error: NSDictionary?
NSAppleScript(source: script)?.executeAndReturnError(&error)
if let error {
+1 -1
View File
@@ -55,7 +55,7 @@ sign() {
echo "==> Signing with $IDENTITY"
cp "$(profile_for $APP_ID)" "$APP/Contents/embedded.provisionprofile"
cp "$(profile_for $EXT_ID)" "$EXT/Contents/embedded.provisionprofile"
codesign --force --options runtime --timestamp -s "$IDENTITY" "$APP/Contents/MacOS/firewall-uninstall"
codesign --force --options runtime --timestamp -s "$IDENTITY" "$APP/Contents/MacOS/firewall"
codesign --force --options runtime --timestamp \
--entitlements Extension/Extension.entitlements -s "$IDENTITY" "$EXT"
codesign --force --options runtime --timestamp \
+4 -4
View File
@@ -118,14 +118,14 @@ targets:
- target: Extension
embed: true
codeSign: true
# Uninstall runs this as root to remove what the extension left.
# Uninstall runs the CLI as root to remove what the extension left.
postBuildScripts:
- name: Embed firewall-uninstall
- name: Embed the CLI
basedOnDependencyAnalysis: false
script: |
export PATH="$HOME/.cargo/bin:$PATH"
unset CC CXX CFLAGS CXXFLAGS
export SDKROOT="$(xcrun --sdk macosx --show-sdk-path)"
cd "$SRCROOT/../core"
cargo build --bin firewall-uninstall --target aarch64-apple-darwin $([ "$CONFIGURATION" = Debug ] || echo --release)
cp "target/aarch64-apple-darwin/$CARGO_PROFILE/firewall-uninstall" "$TARGET_BUILD_DIR/$EXECUTABLE_FOLDER_PATH/"
cargo build --bin firewall --target aarch64-apple-darwin $([ "$CONFIGURATION" = Debug ] || echo --release)
cp "target/aarch64-apple-darwin/$CARGO_PROFILE/firewall" "$TARGET_BUILD_DIR/$EXECUTABLE_FOLDER_PATH/"