简体   繁体   中英

Ubuntu - firewall rules MySQL on host | Docker containers to host

Is there any possible way to setup the host firewall to allow connections only for the network Docker containers uses?

Intro

The only way I was able to connect to a OS hosted MySQL instance from my new Docker containers was by opening to ports:

sudo ufw allow 3310

Inside the Docker container I am then able to connect using:

 (Docker container): mysql -u testuser -p -h 172.100.0.1 -P 3310

However this way the port is open to the internet as well, I would rather use SSH to connect using credentials.

NOTE: MySQL bind-address=0.0.0.0 is set

Information

  • On Host:

NOTE: Showing only applicable Docker network information - my containers use a custom named network (d-custom-network)

  ifconfig

  d-custom-network: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
    inet 172.100.0.1  netmask 255.255.0.0  broadcast 172.100.255.255
    inet6 fe80::42:b8ff:fe7f:c4bf  prefixlen 64  scopeid 0x20<link>
    ether 02:42:b8:7f:c4:bf  txqueuelen 0  (Ethernet)
    RX packets 473  bytes 34668 (34.6 KB)
    RX errors 0  dropped 0  overruns 0  frame 0
    TX packets 403  bytes 119797 (119.7 KB)
    TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

  docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
    inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
    inet6 fe80::42:13ff:fefc:301f  prefixlen 64  scopeid 0x20<link>
    ether 02:42:13:fc:30:1f  txqueuelen 0  (Ethernet)
    RX packets 28509  bytes 1593290 (1.5 MB)
    RX errors 0  dropped 0  overruns 0  frame 0
    TX packets 33351  bytes 173437123 (173.4 MB)
    TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
  • Inside container:

     ip addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever 69: eth0@if70: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:64:00:04 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.100.0.4/16 brd 172.100.255.255 scope global eth0 valid_lft forever preferred_lft forever
  • Docker network information:

     docker network ls 8a35ff6a0a88 bridge bridge local 572f80997782 magento2-network-frontend bridge local 4590216456c0 host host local a79a85d3a426 none null local
  • Docker network inspect: Partial content:

     docker network inspect magento2-network-frontend [ { "Name": "glo-magento2.3-network-frontend", "Id": "572f809977826942d1b582c17f2ac67f25f4221ddfe5a2f504ccb12a3aa6c786", "Created": "2020-08-11T12:05:51.988694032Z", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": null, "Config": [ { "Subnet": "172.100.0.0/16" } ] },

Partial iptables listing (Docker destinations) -: I noticed these connection information when connecting from inside the container when trying to connect in MySQL testing with a failed login

   FROM Within container:

   ERROR 1045 (28000): Access denied for user 'testuser'@'cpe-172-100-0-4.twcny.res.rr.com'
   ping cpe-172-100-0-4.twcny.res.rr.com
   PING cpe-172-100-0-4.twcny.res.rr.com (172.100.0.4) 56(84) bytes of data.
   64 bytes from 54195d3486eb (172.100.0.4): icmp_seq=1 ttl=64 time=0.063 ms

   iptables -L 

   Chain DOCKER (2 references)
   target     prot opt source               destination
   ACCEPT     tcp  --  anywhere             cpe-172-100-0-2.twcny.res.rr.com  tcp dpt:6082
   ACCEPT     tcp  --  anywhere             cpe-172-100-0-2.twcny.res.rr.com  tcp dpt:6081
   ACCEPT     tcp  --  anywhere             cpe-172-100-0-3.twcny.res.rr.com  tcp dpt:6379
   ACCEPT     tcp  --  anywhere             cpe-172-100-0-4.twcny.res.rr.com  tcp dpt:http-alt
   ACCEPT     tcp  --  anywhere             cpe-172-100-0-5.twcny.res.rr.com  tcp dpt:https
   ACCEPT     tcp  --  anywhere             cpe-172-100-0-5.twcny.res.rr.com  tcp dpt:http

What I tried

I thought I would be able to use the method mentioned here: This is also why I investigated how to make sure the docker network name used by host (ie. ifconfig output) , in my example I created d-custom-network

Direct link

To allow access on a specific port let's say port 3360 only to specific network interface eth2, then you need to specify allow in on and the name of the network interface:

 $ sudo ufw allow in on eth2 to any port 3306

 $ sudo ufw reload

So I tried sudo ufw allow in on d-custom-network to any port 3310

That is when I noticed the docker cpe-172-100-0-2.twcny.res.rr.com output when trying to force a failed login for testing the location I connect from.

I do not think I understood the usage correctly, and assumed that I could use the internal network 172.100.0.* where my docker containers connect to/from.

How would I go about this?

I had the same question, and the following worked for me (all commands run on the host):

  1. Identify which network your container is attached to:

     $ docker inspect mycontainer... "Networks": { "bridge": { "IPAMConfig": null, "Links": null, "Aliases": null, "NetworkID": "b8ecee4683b22db9154f8c3e56b48f371b2bdf663f25d092112fc7eb410a4816", "EndpointID": "56cd2b50116f92d49c643457059a0ef0350e14509a16d1b615f806bb62eb4ad5", ... } }...

    My container mycontainer is attached to the network named bridge :

     $ docker network ls NETWORK ID NAME DRIVER SCOPE b8ecee4683b2 bridge bridge local f9a4ecf5db2b host host local cc168ad8f868 none null local
  2. Identify which of the host's network interfaces corresponds to the bridge network:

     $ docker network inspect bridge... "Options": {... "com.docker.network.bridge.name": "docker0", ... }, ...

    My network bridge corresponds to host network interface docker0 :

     $ ip addr... 3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:c8:b4:a4:ba brd ff:ff:ff:ff:ff:ff inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0 valid_lft forever preferred_lft forever inet6 fe80::42:c8ff:feb4:a4ba/64 scope link valid_lft forever preferred_lft forever...
  3. Allow traffic from the identified host network interface docker0 , to port 3310 anywhere:

     $ sudo ufw allow in on docker0 to any port 3310

I tested it, and the database port on the host is now:

  • accessible when connecting from inside the docker container, and
  • filtered by the firewall when trying to connect from the network outside the host.

Also, since we're talking about securing a docker host with UFW, I feel it's important to mention this side note/warning about using UFW with docker, in case you're not already aware: See this discussion for details, in summary, Docker by default may override UFW's firewall rules in ways that a typical user may not be expecting. In particular, I think that exposing a port on a container via docker -p actually punches a hole in your firewall on that port, which UFW does not see or control.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM