[PR #145] [MERGED] fix(lxc): honour Docker --network none (isolated netns, no bridge NIC) #144

Closed
opened 2026-10-15 12:52:20 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/games-on-whales/LXC2Docker/pull/145
Author: @JBailes
Created: 7/17/2026
Status: ✅ Merged
Merged: 7/17/2026
Merged by: @JBailes

Base: main ← Head: fix/network-none-isolation


📝 Commits (1)

  • a8fca84 fix(lxc): honour Docker --network none (isolated netns, no bridge NIC)

📊 Changes

3 files changed (+66 additions, -0 deletions)

View changed files

📝 internal/lxc/config.go (+10 -0)
📝 internal/lxc/network.go (+14 -0)
📝 internal/lxc/network_test.go (+42 -0)

📄 Description

Problem

A container created with --network none is given a routable NIC on the managed bridge instead of being isolated. In buildItems/buildPVEItems the network selection is:

if cfg.LANBridge != "" {
    ... DualNICConfig ...
} else if cfg.NetworkMode == "host" {
    // namespace.clone
} else {
    items = append(items, NetworkConfig(ip)...)   // veth on veth0 + IP + gateway
}

canonicalNetworkName("none") returns "none" (only ""/"default"/"bridge" map to the managed network), so a none-mode container has cfg.NetworkMode == "none" and falls through to the else, receiving:

lxc.net.0.type = veth
lxc.net.0.link = veth0
lxc.net.0.ipv4.address = 10.100.0.x/24
lxc.net.0.ipv4.gateway = 10.100.0.1

So --network none silently grants full network egress. Observed live: docker inspect reports NetworkMode=none while the container has eth0 with a 10.100.0.x address, a default route, and reaches the public internet directly (DNS + 1.1.1.1:443). This breaks any caller that relies on --network none for isolation — e.g. a sandboxed workload whose only intended egress is a proxy.

Fix

Add a none branch to both builders that emits LXC's isolated-netns primitive:

lxc.net.0.type = empty

empty gives the container a fresh network namespace containing only loopback — no veth, no IP, no route out — which is exactly Docker's --network none. (Deliberately not lxc.net.0.type = none, which in LXC shares the host netns — the opposite of isolation.)

Test

TestNetworkModeNoneIsolatesNetns runs both buildItems and buildPVEItems with NetworkMode: "none" and asserts the config has lxc.net.0.type = empty, no bridge link/IP/gateway, and no host lxc.namespace.clone.

go build ./... and go test ./internal/lxc/ pass (one unrelated, pre-existing TestCheckCreateDiskPressure failure is environmental — it depends on the host's free disk vs. the test threshold and also fails on a clean checkout).


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/games-on-whales/LXC2Docker/pull/145 **Author:** [@JBailes](https://github.com/JBailes) **Created:** 7/17/2026 **Status:** ✅ Merged **Merged:** 7/17/2026 **Merged by:** [@JBailes](https://github.com/JBailes) **Base:** `main` ← **Head:** `fix/network-none-isolation` --- ### 📝 Commits (1) - [`a8fca84`](https://github.com/games-on-whales/LXC2Docker/commit/a8fca8446f31a5ac5c8d1fdee011c1a6f8c1c391) fix(lxc): honour Docker --network none (isolated netns, no bridge NIC) ### 📊 Changes **3 files changed** (+66 additions, -0 deletions) <details> <summary>View changed files</summary> 📝 `internal/lxc/config.go` (+10 -0) 📝 `internal/lxc/network.go` (+14 -0) 📝 `internal/lxc/network_test.go` (+42 -0) </details> ### 📄 Description ## Problem A container created with `--network none` is given a **routable NIC on the managed bridge** instead of being isolated. In `buildItems`/`buildPVEItems` the network selection is: ```go if cfg.LANBridge != "" { ... DualNICConfig ... } else if cfg.NetworkMode == "host" { // namespace.clone } else { items = append(items, NetworkConfig(ip)...) // veth on veth0 + IP + gateway } ``` `canonicalNetworkName("none")` returns `"none"` (only `""`/`"default"`/`"bridge"` map to the managed network), so a none-mode container has `cfg.NetworkMode == "none"` and falls through to the `else`, receiving: ``` lxc.net.0.type = veth lxc.net.0.link = veth0 lxc.net.0.ipv4.address = 10.100.0.x/24 lxc.net.0.ipv4.gateway = 10.100.0.1 ``` So `--network none` silently grants full network egress. Observed live: `docker inspect` reports `NetworkMode=none` while the container has `eth0` with a `10.100.0.x` address, a default route, and reaches the public internet directly (DNS + `1.1.1.1:443`). This breaks any caller that relies on `--network none` for isolation — e.g. a sandboxed workload whose only intended egress is a proxy. ## Fix Add a `none` branch to both builders that emits LXC's isolated-netns primitive: ``` lxc.net.0.type = empty ``` `empty` gives the container a fresh network namespace containing **only loopback** — no veth, no IP, no route out — which is exactly Docker's `--network none`. (Deliberately **not** `lxc.net.0.type = none`, which in LXC shares the *host* netns — the opposite of isolation.) ## Test `TestNetworkModeNoneIsolatesNetns` runs both `buildItems` and `buildPVEItems` with `NetworkMode: "none"` and asserts the config has `lxc.net.0.type = empty`, no bridge link/IP/gateway, and no host `lxc.namespace.clone`. `go build ./...` and `go test ./internal/lxc/` pass (one unrelated, pre-existing `TestCheckCreateDiskPressure` failure is environmental — it depends on the host's free disk vs. the test threshold and also fails on a clean checkout). --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-15 12:52:20 +00:00
Sign in to join this conversation.
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
games-on-whales/LXC2Docker#144
No description provided.