-
Notifications
You must be signed in to change notification settings - Fork 63
[LXC] Enforce the deny-all-except-proxy network policy (model 2) #798
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Darren Hoehna (dhoehna)
wants to merge
69
commits into
main
Choose a base branch
from
user/dahoehna/lxc-network-model2
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
69 commits
Select commit
Hold shift + click to select a range
d0705a0
[LXC] Scrub and apply proxy env vars through the shared helper
dhoehna b74f5bf
Correct the LXC client note: the integration is planned, not wired
dhoehna 40514a6
[LXC] Pin the proxy hostname instead of rewriting the URL host
dhoehna 764900b
Drop a dead bracket guard and document why unbracketing is load-bearing
dhoehna bf37b12
[LXC] Make an unpinnable proxy address unrepresentable
dhoehna 445ea2e
[LXC] Update proxy address spec for the unpinnable-address fix
dhoehna 91b3760
[LXC] Fail closed when firewall rules cannot be scoped to the container
dhoehna a3d82c0
[LXC] Spec the fail-closed contract for unscopeable firewall rules
dhoehna 47e00a9
[LXC] Hook the firewall chain onto the bridge port so it actually fil…
dhoehna 3a05f6a
[LXC] Spec the FORWARD hook contract and assert enforcement end to end
dhoehna 792d1ae
[LXC] Make deny rules win over allow rules and fail closed on an unre…
dhoehna 988b609
[LXC] Spec deny precedence and assert an overlapping allow cannot def…
dhoehna 8595d5d
[LXC] Correct the network policy docs and make the E2E suite gate in CI
dhoehna 4ed9d4d
[LXC] Set FORWARD to ACCEPT in CI so only MXC rules can block
dhoehna 76eb242
Keep Bubblewrap startable when no veth exists to scope the chain to
dhoehna 3dd4196
Cover the Bubblewrap veth declaration so deleting it fails a test
dhoehna c098239
Pin the negative case of the missing-veth accessor
dhoehna 76c4c51
[LXC] Admit network.proxy for LXC and reject the forms it cannot reach
dhoehna d1da5d3
[LXC] Let a caller force lxc-attach to clear the inherited environment
dhoehna de6c96a
[LXC] Wire the proxy-env scrub into the production execution path
dhoehna 8c6fa72
[LXC] Restrict egress to the proxy endpoint when one is configured
dhoehna a46ad0a
[LXC] Pin the proxy host inside the container before running the script
dhoehna 8dd810d
[LXC] Add the deny-all-except-proxy integration test
dhoehna 63974b7
[LXC] Document the cooperative-proxy posture
dhoehna f397020
[LXC] Scope the integration test's DNS claims to what FORWARD can see
dhoehna daac8ab
[LXC] Require a firewall enforcement mode for network.proxy
dhoehna cfd062c
[LXC] Fail closed when an allow rule can outrank an unresolvable deny
dhoehna aafb0de
[LXC] Claim FORWARD hooks before installing them, not after
dhoehna 19ac107
[LXC] Clear a stale proxy host pin when a run pins nothing
dhoehna edb9d38
Merge remote-tracking branch 'origin/main' into user/dahoehna/lxc-net…
dhoehna c3d133f
[LXC] Derive the chain name in the specs instead of hard-coding it
dhoehna c7c6142
[LXC] Narrow the deny-precedence failure to a catch-all allow
dhoehna 130b1c9
[LXC] Reject proxy URLs that carry credentials
dhoehna 3de0f5b
[LXC] Stop staging /etc/hosts through a predictable /tmp file
dhoehna c00f941
[LXC] Fail closed on a proxy the enforcement mode will not enforce
dhoehna 8e1cf62
[LXC] Carry the reply path for allowed outbound connections
dhoehna 739d23f
[LXC] Run the E2E suite under the forward policy production has
dhoehna d983827
Revert "[LXC] Run the E2E suite under the forward policy production has"
dhoehna d93bf12
[LXC] Enforce the no-credential proxy invariant at the runner boundary
dhoehna 221f8d1
[LXC] Redact the proxy URL in the diagnostics that run before the guard
dhoehna 628b0b4
Treat an unreadable sysfs as bridged instead of as directly routed
dhoehna 12eb8e9
Do not read a dangling interface symlink as directly routed
dhoehna 97ff4b1
Pin the metadata asymmetry with dangling-symlink tests
dhoehna b657fc7
Find proxy credentials in an opaque URL, not just an authority one
dhoehna dad5aeb
Stop rewriting /etc/hosts when the read that feeds it failed
dhoehna 9595b58
Cover the credentialed-proxy rejection from outside the process
dhoehna bfcbc82
Close three holes an independent review found in the credential guard
dhoehna 7a9948b
Stop reading a port separator as a URL scheme
dhoehna b67f7ec
Refuse to rewrite /etc/hosts through a symbolic link
dhoehna d26d826
Stop the credential test from publishing the secret it guards
dhoehna 6392ea0
[LXC] Stop leading whitespace from hiding a proxy credential
dhoehna 5c057c6
[LXC] Stop the drift guard from printing the credentials it guards
dhoehna aef66b5
[LXC] Stop a backslash from hiding a proxy credential, and pin the gu…
dhoehna 6309789
[LXC] Correct the return-path rule's safety claim with a measurement
dhoehna a4613e3
Judge a proxy URL by what can leak, not only by what a parser sees
dhoehna 82e8b0e
Fix two E2E scripts that asserted on chain names that can never exist
dhoehna cdc8cf6
Describe what the code does in comments, not how it got there
dhoehna 0184689
Say what the data is, not how the code uses it
dhoehna a7ccd08
Say why the test is `!= DirectlyRouted`
dhoehna dba2f73
Put in doc comments what the code cannot say
dhoehna 19be524
Correct two claims review showed were false
dhoehna 0c93721
Fix hook ownership stranding, empty failure reasons, and add live pro…
dhoehna 967f798
Add end-to-end coverage for pin lifetime, preserved policy, and the b…
dhoehna 6ce453b
Stop clobbering caller proxy settings, and widen two guards past LXC
dhoehna c80ae1e
Refuse blockedHosts under a proxy, and pin only what the run pinned
dhoehna 069194d
Write the two address families once, and bound the proxy answer
dhoehna e8bd2c7
Give the network scripts one chain-name helper
dhoehna ab5202b
Format three files rustfmt was rejecting
dhoehna a35fed0
Remove a return rule whose insert reported failure
dhoehna File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,139 @@ | ||
| name: LXC E2E Tests | ||
|
|
||
| on: | ||
| push: | ||
| branches: [main] | ||
| pull_request: | ||
| branches: [main] | ||
| workflow_dispatch: | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| jobs: | ||
| lxc-e2e: | ||
| name: LXC-Exec Container and Network Policy | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 45 | ||
|
|
||
| steps: | ||
| - uses: actions/checkout@v6 | ||
|
|
||
| - name: Setup Rust toolchain | ||
| run: rustup update stable | ||
|
|
||
| - name: Point cargo at the MxcDependencies feed | ||
| uses: ./.github/actions/setup-cargo-feed | ||
|
|
||
| - name: Cache Rust build artifacts | ||
| uses: Swatinem/rust-cache@v2 | ||
| with: | ||
| workspaces: src | ||
|
|
||
| - name: Install LXC and firewall tooling | ||
| run: | | ||
| sudo apt-get update | ||
| sudo DEBIAN_FRONTEND=noninteractive apt-get install -y \ | ||
| lxc lxc-templates lxc-utils iptables debootstrap uidmap bridge-utils | ||
|
|
||
| # A bridged veth only reaches the FORWARD chain while br_netfilter is | ||
| # delivering bridged packets to iptables. Without it the firewall rules | ||
| # install cleanly and never fire, so the network policy tests would pass | ||
| # against a firewall that filters nothing. | ||
| - name: Enable bridge netfilter | ||
| run: | | ||
| sudo modprobe br_netfilter | ||
| sudo sysctl -w net.bridge.bridge-nf-call-iptables=1 | ||
| sudo sysctl -w net.bridge.bridge-nf-call-ip6tables=1 | ||
|
|
||
| # GitHub-hosted runners ship Docker, and Docker sets the IPv4 FORWARD | ||
| # policy to DROP. That breaks these tests twice over. | ||
| # | ||
| # First, it breaks them outright. MXC hooks its chain on traffic leaving | ||
| # the container (`-i <veth>` / `--physdev-in <veth>`), so an allowed | ||
| # request is accepted on the way out -- but the reply arrives in the | ||
| # opposite direction, matches no MXC rule, falls through to the policy, | ||
| # and is dropped. The connection times out and an explicitly allowed | ||
| # destination looks unreachable. Observed exactly that: DNS resolved, | ||
| # because dnsmasq on lxcbr0 is host-local and never traverses FORWARD, | ||
| # and then `wget: can't connect to remote host (140.82.116.5)`. | ||
| # | ||
| # Second, and worse, it would make the deny cases meaningless. Under a | ||
| # DROP policy a container with NO working MXC hook at all is also | ||
| # unreachable, so the enforcement and deny-precedence tests would report | ||
| # success against a firewall that filters nothing -- which is the precise | ||
| # bug this suite exists to detect, and the reason these tests carry | ||
| # positive controls. | ||
| # | ||
| # Setting the policy to ACCEPT restores the condition the tests were | ||
| # written for: the host forwards by default, so the ONLY thing that can | ||
| # block container traffic is a rule MXC installed. A missing hook then | ||
| # shows up as an unexpected success and fails the deny case loudly. | ||
| # A narrower conntrack RELATED,ESTABLISHED rule is not an alternative | ||
| # here. The chain already carries return rules in both the interface and | ||
| # the physdev form, and both were measured inert on this bridged | ||
| # topology: a reply is routed toward lxcbr0, so the bridge port is not | ||
| # selected when FORWARD runs and neither form matches. Scoping the return | ||
| # direction by the container's address is the fix, and it is deferred -- | ||
| # it needs the address plumbed through to the manager and a live bridged | ||
| # measurement, not another untested rule. | ||
| - name: Let the host forward, so only MXC rules can block | ||
| run: | | ||
| sudo iptables -P FORWARD ACCEPT | ||
| sudo ip6tables -P FORWARD ACCEPT | ||
| sudo iptables -S FORWARD | head -5 | ||
|
|
||
| - name: Report the environment these tests depend on | ||
| run: | | ||
| echo "--- kernel ---" | ||
| uname -a | ||
| echo "--- lxc ---" | ||
| lxc-create --version || echo "MISSING lxc-create" | ||
| echo "--- iptables ---" | ||
| sudo iptables --version || echo "MISSING iptables" | ||
| sudo ip6tables --version || echo "MISSING ip6tables" | ||
| echo "--- forward policy (must be ACCEPT, or deny cases pass vacuously) ---" | ||
| sudo iptables -S FORWARD | head -1 | ||
| sudo ip6tables -S FORWARD | head -1 | ||
| echo "--- bridge netfilter ---" | ||
| cat /proc/sys/net/bridge/bridge-nf-call-iptables || echo "MISSING bridge-nf-call-iptables" | ||
| cat /proc/sys/net/bridge/bridge-nf-call-ip6tables || echo "MISSING bridge-nf-call-ip6tables" | ||
| echo "--- host ipv6 ---" | ||
| cat /proc/net/if_inet6 || echo "no /proc/net/if_inet6 (IPv6 disabled)" | ||
|
|
||
| - name: Build lxc-exec | ||
| working-directory: src | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| run: cargo build --release -p lxc --bin lxc-exec | ||
|
|
||
| # MXC_LXC_TESTS_REQUIRE_EXECUTION turns an honest skip into a failure. | ||
| # On a developer box a missing ip6tables is a reason to run what you can. | ||
| # Here the runner is provisioned specifically to execute this suite, so a | ||
| # skip means a prerequisite disappeared and the gate would go green while | ||
| # testing nothing. | ||
| - name: Run LXC E2E suite | ||
| env: | ||
| MXC_LXC_TESTS_REQUIRE_EXECUTION: "1" | ||
| run: sudo --preserve-env=MXC_LXC_TESTS_REQUIRE_EXECUTION bash tests/scripts/run_lxc_all_tests.sh | ||
|
|
||
| - name: Show leftover firewall state on failure | ||
| if: failure() | ||
| run: | | ||
| echo "--- FORWARD chain ---" | ||
| sudo iptables -S FORWARD || true | ||
| sudo ip6tables -S FORWARD || true | ||
| echo "--- MXC chains ---" | ||
| sudo iptables -S | grep -E '^-N MXC-' || echo "none" | ||
| sudo ip6tables -S | grep -E '^-N MXC-' || echo "none" | ||
|
|
||
| - name: Upload logs on failure | ||
| if: failure() || cancelled() | ||
| uses: actions/upload-artifact@v6 | ||
| with: | ||
| name: lxc-e2e-logs-${{ github.event.pull_request.number || github.run_number }} | ||
| retention-days: 7 | ||
| path: | | ||
| logs/ | ||
| **/*.log |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.