robbertkl / docker-ipv6nat

Extend Docker with IPv6 NAT, similar to IPv4
MIT License
662 stars 48 forks source link

README Question: Using image/image inside #61

Closed johntdavis84 closed 4 years ago

johntdavis84 commented 4 years ago

Hello,

Thanks for putting so much effort into the README. It explains both the problem and solution, and quite a bit about how all this actually works.

I've been trying to set up pihole with v6 support for a few weeks now (I tinker with it at night), and have mostly been stunned at how underdeveloped docker's v6 support is--even the documentation is incomplete.

I was definitely very happy to find your software and instructions, and I'd like to try to roll it out with pihole.

I do have a couple questions about the documentation.

Thanks!

bephinix commented 4 years ago

@johntdavis84 Using IPv6 with Docker is not as simple as it should be, thats right.

Could you please add an example compose file equivalent to the example docker run command?

The equivalent compose subtree for the Docker-Run-Command:

version: '3.3'
services:
    ipv6nat:
        container_name: ipv6nat
        privileged: true
        network_mode: host
        restart: unless-stopped
        volumes:
            - '/var/run/docker.sock:/var/run/docker.sock:ro'
            - '/lib/modules:/lib/modules:ro'
        image: robbertkl/ipv6nat

(You might want to check Composerize.

When would I need to install and enable the system service?

This depends on how you want to run and deploy Docker-IPv6 NAT. If you run it by creating a docker container with docker run or an equivalent docker-compose configuration, you need to run it in privileged mode (at least with NET_ADMIN and SYS_MODULE capabilities) and pass the docker socket and the corresponding module libraries for IPTables to the container.

I always run Docker-IPv6 as a system service - so no container, directly on the host - as Docker-IPv6 NAT is more or less an additional service to provide an infrastructure to use and deploy containers. As there is a package for your distribution (ArchLinux/Manjaro), I recommend to use this package, but you are free to use another deployment variant.

The AUR package (which I currenty maintain) only supports amd64 at the moment, but I deployed Docker-IPv6 to my own PiHole last week, so I will update the package to support ARM systems, too. :+1:

bephinix commented 4 years ago

@johntdavis84 The AUR package is now also available for armv6h, armv7h and aarch64, so you can run Docker-IPv6-NAT as a system service by installating the AUR package or as a container by using the docker command or the docker compose script. :tada:

robbertkl commented 4 years ago

Awesome @bephinix !

johntdavis84 commented 4 years ago

@bephinix & @robbertkl Good morning! Thanks so much for your replies. @bephinix , I can't say how much I appreciate taking time to publish a new version of the AUR package. I've been going slowly mad trying to do it by hand--but at least I understand a lot more about how v6 and docker work now. Thank you!

One last question: I am assuming, but not 100 percent sure, that I need to keep the daemon.json commands to actually enable IPv6 at all. Is that correct?

{ "ipv6": true, "fixed-cidr-v6": "$NETMASK::/80" }

"Not as simple as it should be" is a much more circumspect than I ended up being over here. I tried to point out what I felt were some more shortcomings of the builtin v6 features. Maybe some of my rambling might be useful in the readme description of why this package is so useful? https://github.com/docker/docker.github.io/issues/6075#issuecomment-667407864

Admittedly, I was pretty frustrated at that point, having spent hours and days to even realize the docker documentation wasn't actually complete and then dig around to try to get it up and running. I eventually found this ( https://medium.com/@skleeschulte/how-to-enable-ipv6-for-docker-containers-on-ubuntu-18-04-c68394a219a2 ). That all made sense and worked but was way too much work. I found myself trying to learn bash scripting Thursday night to automatically run the ip6tables commands at boot to manually route the pihole and default networks, and realized I needed to try something different.

bephinix commented 4 years ago

@johntdavis84 If you want to enable IPv6 on your default docker0 bridge, you have to keep the options in daemon.json. For manually created networks, this should not be necessary.

Dual-Stack for containers are not as common as one might think; most of the time only the ingress itself uses dual-stack and all other internal containers and services use IPv4 or IPv6. AFAIK Kubernetes is currently implementing/testing IPv6, maybe Docker will also update their IPv6 support. If you check "moby" and "libnetwork" repositories, you will find issues and pull requests for IPv6 support, NAT fixes and more.

(I wrote a Tutorial for a Hosting Provider which might be useful if you ever want to run IPv4+IPv6 Docker on recent Debian machines.)

Let us know, when your IPv6-NAT deployments is up and running. :smile:

johntdavis84 commented 4 years ago

@bephinix is there a good reason to enable v6 on the default bridge? My understanding (so far) is that regularly using the default bridge for anything when there's a container with its own network available has negative security implications.

I understand that it's not a common use case, though I'm definitely surprised that the current docker documentation does not actually explain how to get a dual-stack container (or even a single stack v6 container) up and running. The closest I got was using Skleeschulte's Medium article, and even then he convinced me that the far superior solution was to use the docker-ipv6 package. :-)

What got me diving head first down this rabbit hole to begin with was noticing the default docker-compose.yml file for pihole did not bring up a pihole instance that actually obtained a v6 address and screened v6 ad-serving addresses. I'm not even sure what percentage of actual advertising that is, but I very much got sucked into the challenge of making it work. :-P

I'm about to try to install it now. I'll let you know how it goes.

EDIT: That little green light after you start and enable something is so satisfying. :) ... And the pi rebooted correctly, so. Win?

image

I still need to update the docker-compose.yml and try to bring up pihole again. Hopefully later tonight, but I must go be a responsible adult for a bit, alas.

Thanks again for all your help.

johntdavis84 commented 4 years ago

@bephinix , thanks again for your help.

I'm able to bring up the docker-compose.yml powered container, using the IPv6: 'True' flag in the environment. During startup, I see this:

pihole | Using IPv4 and IPv6

That all seems to be working as intended, but then I get the following when I try to inspect the network it creates. It's not enabling IPv6, and the image does not appear to receive a v6 address at all.

Do I need to manually create the network with a docker command before bringing up the container to ensure it gets an address? Right now I'm relying on docker-compose to automatically create it, and if it doesn't know about the ipv6nat add-on it makes sense that it wouldn't do anything.

OR: Do I need to set the pihole service's "network_mode" to "host," similar to your containerized, non-systemd service example above?

$ sudo docker network inspect pi-hole_default [ { "Name": "pi-hole_default", "Id": "7463b9a0f2d7a8f70b8b02173ccc60a11c1e98feaa3ec3fcdc3e7f52db8c822a", "Created": "2020-08-02T20:23:40.058489215-05:00", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": null, "Config": [ { "Subnet": "172.20.0.0/16", "Gateway": "172.20.0.1" } ] }, "Internal": false, "Attachable": true, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": { "dd398fe98233b7e7a6e55f7c22769669c3cc739ce3f91804385d34b7880fd0ff": { "Name": "pihole", "EndpointID": "49f27594b6f21a606b7a2c8fa760fa440d66b23af584d95374fd14c5e6c5ae05", "MacAddress": "02:42:ac:14:00:02", "IPv4Address": "172.20.0.2/16", "IPv6Address": "" } }, "Options": {}, "Labels": { "com.docker.compose.network": "default", "com.docker.compose.project": "pi-hole", "com.docker.compose.version": "1.26.2" } } ]

bephinix commented 4 years ago

@johntdavis84

My understanding (so far) is that regularly using the default bridge for anything when there's a container with its own network available has negative security implications.

Exactly, simply use custom created bridges all the time. :+1:

Do I need to manually create the network with a docker command before bringing up the container to ensure it gets an address?

You do not have. It is possible to create an bridge network with IPv6 via docker compose, although you may need to use v2 of docker compose files. The bridge or docker compose do not need to known about Docker-IPv6-NAT, as IPv6-NAT simply monitors active docker networks via the docker socket and creates and removes IPTables rules accordingly.

Do I need to set the pihole service's "network_mode" to "host," similar to your containerized, non-systemd service example above?

I am running Pi-Hole and a few other services on my Raspberry Pi 4. Pi-Hole uses the network stack of the docker host and all the other services will use a custom bridge network. The reason why Pi-Hole is bound to the host's network stack is that it es easier to setup because of DHCP, Broadcasts and so on.

johntdavis84 commented 4 years ago

@bephinix

I've added network_mode: host to my pihole service description, along with my static v4 host address and (the most) static v6 address that box seems to have.

I'm realizing starting my docker adventure with pihole was likely not the best idea. The pihole docs make it sound super-simple, but to even get it to come up on Manjaro Linux I had to make the pihole container privileged, even without trying to use IPv6. Otherwise the container's webserver completely chokes on launch. Not to mention it interfaces with the outside world as a DNS server. Complications! ;)

I am running Pi-Hole and a few other services on my Raspberry Pi 4. Pi-Hole uses the network stack of the docker host and all the other services will use a custom bridge network. The reason why Pi-Hole is bound to the host's network stack is that it es easier to setup because of DHCP, Broadcasts and so on.

So, that's why letting it set up a bridge mode network failed to assign an IPv6 address? Since it was just blank, I wasn't sure if the ipv6nat service might be malfunctioning or something.

Even the default host network shows up with "EnableIPv6": false when I inspect it with pi-hole running. I'm guessing whatever generates that output isn't really aware of what docker-ipv6nat.service is doing.

In host mode, is it even using docker-ipv6nat.service at all? It looks like it's just passing the host's network directly to pihole--pihole now shows its server address as the host machine's address, on both v4 and v6 networks.

In any case, at least it's working now. 🌵

What other services do you run? Could you recommend one for me to use to test to make sure bridge networking is working as expected?

bephinix commented 4 years ago

@johntdavis84 At the moment, only Pi-Hole is running on the PI. You might want to use any simple container like NGINX and a default Debian container to test your bridge networking.

@robbertkl I think, we can close this Issue.