Skip to content

fix(gvproxy)!: apply allow_net to the host alias IP - #1106

Merged
DorianZheng merged 1 commit into
mainfrom
fix/allow-net-host-alias
Jul 31, 2026
Merged

fix(gvproxy)!: apply allow_net to the host alias IP#1106
DorianZheng merged 1 commit into
mainfrom
fix/allow-net-host-alias

Conversation

@ltstriker

@ltstriker ltstriker commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Summary

192.168.127.254 — the built-in host alias that gvproxy NATs to host loopback — was exempt from allow_net, so a box with a restrictive allowlist could still reach every service bound to 127.0.0.1 on the host, over both TCP and UDP. It is now an ordinary egress destination.

Changes

  • Drop config.HostIP from the filter's always-allow set. The alias is a NAT to host loopback, not a virtual-network endpoint like the gateway and guest addresses, so it belongs under policy.
  • Build the filter through a single newAllowNetFilter(config). The Go test harness previously duplicated the argument list, which is why a one-line policy change was invisible to go test; all test construction now routes through the production helper.
  • Resolution is unchanged: the built-in DNS record for host.boxlite.internal is still served unconditionally — resolving the alias is not egress. Reaching it requires listing "192.168.127.254" or a covering CIDR.
  • Tests: tap-level reproducers for both transports plus a routing guard that pins pre-NAT policy matching against post-NAT dialing; the four Rust integration cases now cover blocked-and-listed on both TCP and UDP.
  • Docs: four sites stated the alias was not governed by allow_net.

How to verify

make test:unit:gvproxy FILTER='HostAlias'
make test:integration:rust FILTER='host_alias'

Manually: start a box with allow_net: ["example.com"], then wget http://host.boxlite.internal:<port>/ against a host loopback listener — the connection is refused while nslookup host.boxlite.internal still returns 192.168.127.254. Adding "192.168.127.254" to allow_net restores it.

Risks / rollout

Breaking change. Existing callers that set a non-empty allow_net and rely on host.boxlite.internal must add "192.168.127.254". Boxes with an empty or omitted allow_net are unaffected.

Granularity is address-level: allowing the alias opens every port bound to host loopback. allow_net has no port dimension, so this is not expressible more narrowly today.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Host-loopback access now consistently follows allow_net rules for UDP and HTTP traffic.
    • Restrictive allowlists block access through host.boxlite.internal unless 192.168.127.254 is explicitly included.
    • Empty or omitted allowlists continue to permit host-loopback access.
    • DNS resolution for host.boxlite.internal remains available regardless of access permissions.
  • Documentation

    • Updated networking FAQs, guides, and reference documentation to clarify host-loopback addressing, allowlist behavior, and access requirements.

@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 040b565a-ec6f-43fa-a425-7412c6ba04d8

📥 Commits

Reviewing files that changed from the base of the PR and between 8010d5b and ef82970.

📒 Files selected for processing (10)
  • docs/faq.md
  • docs/guides/README.md
  • docs/reference/README.md
  • src/boxlite/src/net/constants.rs
  • src/boxlite/tests/network_spec.rs
  • src/deps/libgvproxy-sys/gvproxy-bridge/allow_net_filter_test.go
  • src/deps/libgvproxy-sys/gvproxy-bridge/forked_tcp_test.go
  • src/deps/libgvproxy-sys/gvproxy-bridge/forked_udp_test.go
  • src/deps/libgvproxy-sys/gvproxy-bridge/main.go
  • src/deps/libgvproxy-sys/gvproxy-bridge/udp_filter_test.go
🚧 Files skipped from review as they are similar to previous changes (10)
  • src/deps/libgvproxy-sys/gvproxy-bridge/forked_tcp_test.go
  • docs/guides/README.md
  • src/deps/libgvproxy-sys/gvproxy-bridge/main.go
  • docs/faq.md
  • src/boxlite/tests/network_spec.rs
  • src/boxlite/src/net/constants.rs
  • docs/reference/README.md
  • src/deps/libgvproxy-sys/gvproxy-bridge/forked_udp_test.go
  • src/deps/libgvproxy-sys/gvproxy-bridge/allow_net_filter_test.go
  • src/deps/libgvproxy-sys/gvproxy-bridge/udp_filter_test.go

📝 Walkthrough

Walkthrough

The change makes 192.168.127.254 subject to non-empty allow_net lists. It centralizes gvproxy filter construction, adds UDP and TCP regression coverage, preserves DNS resolution, and updates networking documentation.

Changes

Host alias allowlist enforcement

Layer / File(s) Summary
Centralized allowlist construction
src/deps/libgvproxy-sys/gvproxy-bridge/main.go, src/deps/libgvproxy-sys/gvproxy-bridge/udp_filter_test.go
newAllowNetFilter builds filters from production configuration without implicitly allowing HostIP. Transport and test network setup use the centralized helper.
Bridge filter and transport validation
src/deps/libgvproxy-sys/gvproxy-bridge/*_test.go
Tests use production filter construction and verify host-alias blocking, matching, routing, and explicit forwarding for UDP and TCP traffic.
Boxlite behavior and documentation
src/boxlite/tests/network_spec.rs, src/boxlite/src/net/constants.rs, docs/faq.md, docs/guides/README.md, docs/reference/README.md
Tests verify DNS preservation, blocked host-alias traffic, and restored access when HOST_IP is listed. Documentation describes the same behavior.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant Gvproxy
  participant HostLoopback
  Client->>Gvproxy: Send UDP or TCP traffic to 192.168.127.254
  Gvproxy->>Gvproxy: Apply allow_net filter
  Gvproxy->>HostLoopback: Forward traffic when address is listed
  Gvproxy-->>Client: Drop traffic when address is not listed
Loading

Possibly related PRs

Suggested labels: e2e-local

Suggested reviewers: dorianzheng

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely identifies the main change: applying allow_net filtering to the gvproxy host alias.
Description check ✅ Passed The description includes all required sections and clearly explains the change, verification steps, breaking-change risk, and rollout impact.
Docstring Coverage ✅ Passed Docstring coverage is 97.37% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/allow-net-host-alias

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@ltstriker
ltstriker marked this pull request as ready for review July 31, 2026 11:22
@ltstriker
ltstriker requested a review from a team as a code owner July 31, 2026 11:22
@boxlite-agent

boxlite-agent Bot commented Jul 31, 2026

Copy link
Copy Markdown

📦 BoxLite review — couldn't complete

claude exited 1

stdout:
{"is_error":true,"duration_api_ms":0,"num_turns":1,"stop_reason":"stop_sequence","session_id":"f42d9cf9-b8c1-46bf-80bc-a00327168425","total_cost_usd":0,"usage":{"input_tokens":0,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":0,"server_tool_use":{"web_search_requests":0,"web_fetch_requests":0},"service_tier":"standard","cache_creation":{"ephemeral_1h_input_tokens":0,"ephemeral_5m_input_tokens":0},"inference_geo":"","iterations":[],"speed":"standard"},"modelUsage":{},"permission_denials":[],"terminal_reason":"api_error","fast_mode_state":"off","fast_mode_disabled_reason":"sdk_opt_in_required","subtype":"success","api_error_status":403,"result":"Your organization has disabled Claude subscription access for Claude Code · Use an Anthropic API key instead, or ask your admin to enable access","type":"result","duration_ms":373,"uuid":"61d5691c-a9a4-49d0-b412-664e634eeeaa"}

stderr:
<empty>

powered by BoxLite

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/faq.md`:
- Around line 306-307: The documentation should clarify that a non-empty
allow_net permits the host alias when it includes “192.168.127.254” or a CIDR
covering that address. Update the corresponding guidance in docs/faq.md lines
306-307 and docs/guides/README.md lines 342-344; make the same wording
correction at both sites.

In `@src/deps/libgvproxy-sys/gvproxy-bridge/udp_filter_test.go`:
- Around line 431-434: Update the ReadFrom error handling in the UDP filter test
to return only when the error is a net.Error whose Timeout() is true; fail the
test for every other error instead of silently returning. Preserve the existing
dropped-datagram behavior for deadline timeouts.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 8d75af3d-0747-4515-be76-ed8a93054f8f

📥 Commits

Reviewing files that changed from the base of the PR and between bad0cbb and 8010d5b.

📒 Files selected for processing (10)
  • docs/faq.md
  • docs/guides/README.md
  • docs/reference/README.md
  • src/boxlite/src/net/constants.rs
  • src/boxlite/tests/network_spec.rs
  • src/deps/libgvproxy-sys/gvproxy-bridge/allow_net_filter_test.go
  • src/deps/libgvproxy-sys/gvproxy-bridge/forked_tcp_test.go
  • src/deps/libgvproxy-sys/gvproxy-bridge/forked_udp_test.go
  • src/deps/libgvproxy-sys/gvproxy-bridge/main.go
  • src/deps/libgvproxy-sys/gvproxy-bridge/udp_filter_test.go

Comment thread docs/faq.md
Comment thread src/deps/libgvproxy-sys/gvproxy-bridge/udp_filter_test.go Outdated
192.168.127.254 was handed to NewAllowNetFilter as an internal
address, so MatchesIP short-circuited on it before any rule was
consulted. The alias NATs to host loopback, which makes it an egress
destination like any other: a box with a restrictive allow_net could
still reach every service bound to 127.0.0.1 on the host, over both
TCP and UDP.

Its DNS record is still served unconditionally — resolving the alias
is not egress — but reaching it now requires listing "192.168.127.254"
or a covering CIDR.

Build the filter through a single newAllowNetFilter so the test
harness shares the production wiring. It previously duplicated the
argument list, which left this behaviour invisible to the Go suite.

BREAKING CHANGE: a non-empty allow_net no longer implies access to
host.boxlite.internal. Add "192.168.127.254" to keep it reachable.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@ltstriker
ltstriker force-pushed the fix/allow-net-host-alias branch from 8010d5b to ef82970 Compare July 31, 2026 16:14
@DorianZheng
DorianZheng added this pull request to the merge queue Jul 31, 2026
Merged via the queue into main with commit 400695b Jul 31, 2026
44 checks passed
@DorianZheng
DorianZheng deleted the fix/allow-net-host-alias branch July 31, 2026 16:58
G4614 pushed a commit to G4614/boxlite that referenced this pull request Aug 3, 2026
## Summary

`192.168.127.254` — the built-in host alias that gvproxy NATs to host
loopback — was exempt from `allow_net`, so a box with a restrictive
allowlist could still reach every service bound to `127.0.0.1` on the
host, over both TCP and UDP. It is now an ordinary egress destination.

## Changes

- Drop `config.HostIP` from the filter's always-allow set. The alias is
a NAT to host loopback, not a virtual-network endpoint like the gateway
and guest addresses, so it belongs under policy.
- Build the filter through a single `newAllowNetFilter(config)`. The Go
test harness previously duplicated the argument list, which is why a
one-line policy change was invisible to `go test`; all test construction
now routes through the production helper.
- Resolution is unchanged: the built-in DNS record for
`host.boxlite.internal` is still served unconditionally — resolving the
alias is not egress. Reaching it requires listing `"192.168.127.254"` or
a covering CIDR.
- Tests: tap-level reproducers for both transports plus a routing guard
that pins pre-NAT policy matching against post-NAT dialing; the four
Rust integration cases now cover blocked-and-listed on both TCP and UDP.
- Docs: four sites stated the alias was not governed by `allow_net`.

## How to verify

```
make test:unit:gvproxy FILTER='HostAlias'
make test:integration:rust FILTER='host_alias'
```

Manually: start a box with `allow_net: ["example.com"]`, then `wget
http://host.boxlite.internal:<port>/` against a host loopback listener —
the connection is refused while `nslookup host.boxlite.internal` still
returns `192.168.127.254`. Adding `"192.168.127.254"` to `allow_net`
restores it.

## Risks / rollout

Breaking change. Existing callers that set a non-empty `allow_net` and
rely on `host.boxlite.internal` must add `"192.168.127.254"`. Boxes with
an empty or omitted `allow_net` are unaffected.

Granularity is address-level: allowing the alias opens every port bound
to host loopback. `allow_net` has no port dimension, so this is not
expressible more narrowly today.

🤖 Generated with [Claude Code](https://claude.com/claude-code)


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **Bug Fixes**
- Host-loopback access now consistently follows `allow_net` rules for
UDP and HTTP traffic.
- Restrictive allowlists block access through `host.boxlite.internal`
unless `192.168.127.254` is explicitly included.
  - Empty or omitted allowlists continue to permit host-loopback access.
- DNS resolution for `host.boxlite.internal` remains available
regardless of access permissions.

- **Documentation**
- Updated networking FAQs, guides, and reference documentation to
clarify host-loopback addressing, allowlist behavior, and access
requirements.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants