Skip to content

Serve DHCP directly from Softnet and use predictable vmnet reservations - #209

Merged
edi-oai merged 2 commits into
mainfrom
dev/edi/dhcp-reservations
Sep 28, 2026
Merged

edi-oai merged 2 commits into
mainfrom
dev/edi/dhcp-reservations

Conversation

@edi-oai

@edi-oai edi-oai commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

The core idea here is to reduce host's attack surface by not allowing the VM to communicate its DHCP server at all.

To achieve that, we use vmnet_network_configuration_add_dhcp_reservation(_:_:_:) to get a predictable IPv4 credentials when constructing a vmnet interface, and then we just these credentials over a small DHCP server directly built into Softnet.

The nice thing is that vmnet prevents IPv4 network collisions for us, so we just pick a random /30 from a private IPv4 range, similarly to how Vetu does it.

Also t's pretty easy to support this in Tart as well: openai/tart#1355.

The only downsides are:

  • macOS 26 (Tahoe) is required now, but now that macOS 27 (Golden Gate) is released, it's probably a good idea to not be on any older release anyway
  • --allow=0.0.0.0/0 no longer enables inter-VM communication because each VM now uses a different bridge interface
    • it's still possible to have this with Tart's default shared (NAT) networking, though

Resolves #197, resolves #207.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-28T16:59:23.306282Z af8ee01 New commits
🔒 Security Review ✅ Completed 2026-09-28T17:01:04.063613Z af8ee01 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 15c7557399

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread lib/host.rs
Comment thread lib/proxy/mod.rs
Comment thread lib/subnet_finder/mod.rs
// Add private address space (as defined in RFC 1918[1])
//
// [1]: https://datatracker.ietf.org/doc/html/rfc1918#section-3
let private_subnets: Vec<Ipv4Net> = vec![

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: no action needed but just wanted to understand

were you able to test if vmnet supports the 10.0.0.0/8 and 172.16.0.0/12 subnets? I recall only testing 192.168.0.0/16 but just wanted to confirm.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, all of them work.

vmnet seems to actually validate these subnets, because e.g. 192.169.0.0/16 results in an error.

Comment thread lib/subnet_finder/mod.rs
// Figure out which address space is already utilized on the host
let mut used_subnets = Vec::new();

for interface in NetworkInterface::show()? {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: no action needed but just wanted to call this out

Since this is taking a snapshot of the current interfaces, and we don't refresh this on each retry, there could a super slim chance of a subnet collision with another softnet process that happens to want the same subnet. The retry should handle it, but I'm wondering if we should refresh the interface list on the retry attempt or not. Not a big deal.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Nice catch.

Given macOS's two-VM limit, we could probably get away without NetworkInterface::show() altogether.

But let's keep it for now as a middle ground.

@edi-oai
edi-oai merged commit e6ee4db into main Sep 28, 2026
2 checks passed
@edi-oai
edi-oai deleted the dev/edi/dhcp-reservations branch September 28, 2026 21:50
@alexey-zaharchenko

Copy link
Copy Markdown

I may be missing something, but the note that default shared NAT can still provide inter-VM communication seems inconsistent with current Sources/tart/Network/NetworkShared.swift

func attachments() -> [VZNetworkDeviceAttachment] {
    [VZNATNetworkDeviceAttachment()]
}

There is no Tart-managed common virtual network or bridge created here that attaches multiple VMs to the same L2 segment. Softnet’s current README states that VZNATNetworkDeviceAttachment enables bridge isolation by default and prevents cross-VM traffic.

What is the currently recommended Tart setup for connecting 2 or more VMs to the same network while keeping Internet access?

--net-bridged seems like an option, but there is also an open report that Wi-Fi bridging fails while Ethernet bridging works

@edi-oai

edi-oai commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor Author

--net-bridged seems like an option, but there is also an open report that Wi-Fi bridging fails while Ethernet bridging works

This works on latest macOS Golden Gate, though, see openai/tart#1289 (comment).

It seems that Apple has recently started enabling interface isolation by default for VZNATNetworkDeviceAttachment.

If there would be a way to disable it, this could solve your use-case easily. Perhaps, worth submitting a bug via Feedback Assistant?

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.

Investigate the feasibility of rejecting the fragmented traffic

4 participants