Skip to content

feat: forward guest DNS to Docker's embedded resolver - #793

Open
alimx07 wants to merge 1 commit into
urunc-dev:mainfrom
alimx07:feat/add-docker-dns
Open

feat: forward guest DNS to Docker's embedded resolver#793
alimx07 wants to merge 1 commit into
urunc-dev:mainfrom
alimx07:feat/add-docker-dns

Conversation

@alimx07

@alimx07 alimx07 commented Jun 28, 2026

Copy link
Copy Markdown

Description

On Docker user custom networks the DNS resolver (127.0.0.11) is loopback only and unreachable by the unikernel guest. Detect this case per container, expose the resolver via a virtual resolver IP configured by user using tc redirects between the tap and lo , and rewrite the guest's resolv.conf to point at that IP in our unikernel is linux one. Also we add a custom rules DNAT rules according to the enviroment (e.g. Docker -> PREROUTING DNAT (for DNS server ports))

Two TC rules added on tap and lo:

  • Tap : Redirect packets to resolvIP into lo
  • Lo : Redirect packets with src=ResolvIP into Tap

Related issues

How was this tested?

Tested in user custom docker network with urunc container u1 and normal one u2:

u1 lookup on github.com

/ # nslookup github.com
Server:		172.24.255.254
Address:	172.24.255.254:53

Non-authoritative answer:
Name:	github.com
Address: 140.82.121.3

u1 lookup on u2

/ # nslookup u2.
Server:		172.24.255.254
Address:	172.24.255.254:53

Non-authoritative answer:

Non-authoritative answer:
Name:	u2
Address: 172.24.0.3

u2 lookup on u1

Server:		127.0.0.11
Address:	127.0.0.11:53

Non-authoritative answer:

Non-authoritative answer:
Name:	u1
Address: 172.24.0.2

LLM usage

Checklist

  • I have read the contribution guide.
  • The linter passes locally (make lint).
  • The e2e tests of at least one tool pass locally (make test_ctr, make test_nerdctl, make test_docker, make test_crictl).
  • If LLMs were used: I have read the llm policy.

@netlify

netlify Bot commented Jun 28, 2026

Copy link
Copy Markdown

Deploy Preview for urunc ready!

Name Link
🔨 Latest commit c741409
🔍 Latest deploy log https://app.netlify.com/projects/urunc/deploys/6a852111d4295c0008a2ed70
😎 Deploy Preview https://deploy-preview-793--urunc.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@alimx07
alimx07 force-pushed the feat/add-docker-dns branch 2 times, most recently from 25a6350 to a743f29 Compare June 28, 2026 07:44
@alimx07
alimx07 force-pushed the feat/add-docker-dns branch from a743f29 to 6723c67 Compare July 10, 2026 15:49
@alimx07

alimx07 commented Jul 10, 2026

Copy link
Copy Markdown
Author

Hey @cmainas, I have implemented the changes we discussed during our sync. Could you please take a look and review them? This will allow us to make any necessary changes before we extend this logic to other unikernels.

@alimx07
alimx07 force-pushed the feat/add-docker-dns branch 6 times, most recently from 22a5784 to 89b24e6 Compare July 23, 2026 14:29

@cmainas cmainas left a comment

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.

Hello @alimx07 ,

thank you for all the changes and the fix. A few comments:

  • In the e2e testing the docker network does not exist and therefore creating the contianer will fail. We need to setup the network. Maybe in https://github.com/urunc-dev/urunc/blob/main/tests/e2e/docker_test.go#L25 and also remove later.
  • Let;s find a better name for loclahost.go. Maybe something like "dns_at_localhost.go"?
  • I think I got confused with the genericRules and dockerRules. Have we found a case where we should apply the genericRules (e.g. a CNI) rather than dockerRules?
  • We can wrap the execution of iptables in a function, instead of having cmd and cmd.Run in various places.
  • We should check if we can obtain the information we gather form iptables from other sources (e.g. netlink).
  • We can restructure the code and this logic in the network_dynamic.go (the only mode where these changes apply) and avoid re-opening the tap device etc. We can me use of https://github.com/urunc-dev/urunc/blob/main/pkg/network/network_dynamic.go#L23C6-L23C20 for passing information.
  • We should also clean up all the rules we apply.

Comment thread tests/e2e/test_cases.go Outdated
Comment thread pkg/network/localhost/localhost.go Outdated
Comment thread pkg/unikontainers/unikontainers.go Outdated
Comment thread pkg/network/localhost/localhost.go Outdated
Comment thread pkg/network/localhost/localhost.go Outdated
Comment thread pkg/network/localhost/docker.go
@alimx07
alimx07 force-pushed the feat/add-docker-dns branch 2 times, most recently from 39be2e9 to 7e73541 Compare July 24, 2026 17:34
Comment thread pkg/network/network_dynamic.go
Comment thread tests/e2e/common.go
_, err := commonCmdExec(cmdBase)
return err
}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

@cmainas , Regarding network. I think using the same pattern as container (rm , create) is the cleanest way here.
I know this is out of the scope of the PR now, and it just being larger and larger, but what touched here is minimal as possible. Also , a future PR will be opened (by Me) adding more test cases (instead of docker) touching other CLI tools. so if you are good, we can move with this right now.

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.

It is ok for the time being, let's just make sure we record it so we can fix it later.

Comment thread pkg/network/localhost/docker.go

@cmainas cmainas left a comment

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.

Hello @alimx07 ,

thank you for the changes:

  • The testing is ok (for the time being) to follow the container create flow. We can properly fix that in later iteration.

Comment thread pkg/network/network_dynamic.go
Comment thread tests/e2e/suite_test.go
Comment thread tests/e2e/common.go
_, err := commonCmdExec(cmdBase)
return err
}

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.

It is ok for the time being, let's just make sure we record it so we can fix it later.

Comment thread pkg/network/localhost/docker.go
Comment thread pkg/network/localhost/docker.go
Comment thread pkg/network/localhost/docker.go Outdated
Comment thread pkg/network/localhost/docker.go Outdated
Comment thread pkg/network/network_dynamic.go
Comment thread pkg/network/localhost/local_dns.go
@cmainas

cmainas commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Also, one more thing, do not forget to add yourself in https://github.com/urunc-dev/urunc/blob/main/.github/contributors.yaml

return nil
}

func uint16Ptr(v uint16) *uint16 {

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.

Can not we inline this?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I have tried but it fails everytime.

@cmainas cmainas Jul 30, 2026

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.

What does fail mean? Is it a compiler error, a runtime error, other failure?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Ptype should be a pointer to uint16. I got a error when trying to do this inline with a pointer operator before uint16.

@alimx07
alimx07 force-pushed the feat/add-docker-dns branch from 7e73541 to b27f329 Compare July 30, 2026 01:14
@alimx07

alimx07 commented Jul 30, 2026

Copy link
Copy Markdown
Author

@cmainas . Everything almost done. Let me if you have any other comments. meanwhile I will be working on sideContainers case for now :)

@cmainas

cmainas commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Hello @alimx07 , please rebase over the main branch.

@alimx07
alimx07 force-pushed the feat/add-docker-dns branch from b27f329 to d77880e Compare July 30, 2026 12:24
@alimx07

alimx07 commented Jul 30, 2026

Copy link
Copy Markdown
Author

Hello @alimx07 , please rebase over the main branch.

Hello @cmainas , Done

@cmainas cmainas left a comment

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.

Hello @alimx07 , some comments:

Comment thread go.mod Outdated
Comment on lines +33 to +36
golang.org/x/net v0.56.0
golang.org/x/sys v0.46.0
google.golang.org/grpc v1.81.1
k8s.io/cri-api v0.36.2

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.

Why have these changed?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Just random go mod tidy. No problems I revert it now and rebased also :)

Comment thread pkg/network/localhost/local_dns.go Outdated
// and set our `loIP` as `127.0.0.10` (first loopback nameserver),
// which will be the one in TC rules and Iptables one.
// Knowing that we should only rewrite the first nameserver in our `resolv.conf`,
// so final result will be :

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: space before ":"

Comment thread pkg/network/localhost/local_dns.go Outdated
for _, line := range lines {
fields := strings.Fields(line)

// if we have `resolv.conf` as :

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.

not: space before ":"

@alimx07
alimx07 force-pushed the feat/add-docker-dns branch 2 times, most recently from 9220678 to f278a84 Compare August 2, 2026 11:29
@cmainas

cmainas commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Hello @alimx07 , the PR does not pass its test. Could you also check the remaining two open comments?

@alimx07
alimx07 force-pushed the feat/add-docker-dns branch from f278a84 to e67c01b Compare August 8, 2026 12:15
@alimx07

alimx07 commented Aug 8, 2026

Copy link
Copy Markdown
Author

Hello @alimx07 , the PR does not pass its test. Could you also check the remaining two open comments?

Hello @cmainas , I addressed the spellcheck and commitLint, but for the docker test, this is weird as it is already working, I have tested it multiple times.

Detect first loopback nameserver in our resolv.conf and rewrite
to user defined virtIP (configured in urunc constants) and apply some
TC rules in general and IP rules (docker case) so we can route this
DNS queries to host localhost DNS server.

Signed-off-by: Ali Mohamed <amx746@gmail.com>
@alimx07
alimx07 force-pushed the feat/add-docker-dns branch from a2440a9 to c741409 Compare August 19, 2026 03:20
@cmainas

cmainas commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Tested it locally and seems to work, not sure what is wrong with CI. We need to check this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants