Configuring a DNS server

Docker provides hostname and DNS configurations for each container without us having to build a custom image. It overlays the /etc folder inside the container with virtual files, in which it can write new information.

This can be seen by running the mount command inside the container. Containers receive the same resolv.conf file as that of the host machine when they are created initially. If a host's resolv.conf file is modified, this will be reflected in the container's /resolv.conf file only when the container is restarted.

In Docker, you can set DNS options in two ways:

  • Using docker run --dns=<ip-address>
  • Adding DOCKER_OPTS="--dns ip-address" to the Docker daemon file

You can also specify the search domain using --dns-search=<DOMAIN>.

The following figure shows a nameserver being configured in a container using the DOCKER_OPTS setting in the Docker daemon file:

Configuring a DNS server

The main DNS files are as follows:

  • /etc/hostname
  • /etc/resolv.conf
  • /etc/hosts

The following is the command to add a DNS server:

# docker run --dns=8.8.8.8 --net="bridge" -t -i  ubuntu:latest /bin/bash

Add hostnames using the following command:

#docker run --dns=8.8.8.8 --hostname=docker-vm1  -t -i  ubuntu:latest /bin/bash

Communication between containers and external networks

Packets can only pass between containers if the ip_forward parameter is set to 1. Usually, you will simply leave the Docker server at its default setting, --ip-forward=true, and Docker will set ip_forward to 1 for you when the server starts up.

To check the settings or to turn IP forwarding on manually, use these commands:

# cat /proc/sys/net/ipv4/ip_forward
0
# echo 1 > /proc/sys/net/ipv4/ip_forward
# cat /proc/sys/net/ipv4/ip_forward
1

By enabling ip_forward, users can make communication possible between containers and the external world; it will also be required for inter-container communication if you are in a multiple-bridge setup. The following figure shows how ip_forward = false forwards all the packets to/from the container from/to the external network:

Communication between containers and external networks

Docker will not delete or modify any pre-existing rules from the Docker filter chain. This allows users to create rules to restrict access to containers.

Docker uses the docker0 bridge for packet flow between all the containers on a single host. It adds a rule to forward the chain using IPTables in order for the packets to flow between two containers. Setting --icc=false will drop all the packets.

When the Docker daemon is configured with both --icc=false and --iptables=true and docker run is invoked with the --link option, the Docker server will insert a pair of IPTables accept rules for new containers to connect to the ports exposed by the other containers, which will be the ports that have been mentioned in the exposed lines of its Dockerfile. The following figure shows how ip_forward = false drops all the packets to/from the container from/to the external network:

Communication between containers and external networks

By default, Docker's forward rule permits all external IPs. To allow only a specific IP or network to access the containers, insert a negated rule at the top of the Docker filter chain.

For example, using the following command, you can restrict external access such that only the source IP 10.10.10.10 can access the containers:

#iptables –I DOCKER –i ext_if ! –s 10.10.10.10 –j DROP
Communication between containers and external networks

Restricting SSH access from one container to another

Following these steps to restrict SSH access from one container to another:

  1. Create two containers, c1 and c2.

    For c1, use the following command:

    # docker run -i -t --name c1 ubuntu:latest /bin/bash
    

    The output generated is as follows:

    root@7bc2b6cb1025:/# ifconfig
    eth0      Link encap:Ethernet  HWaddr 02:42:ac:11:00:05
              inet addr:172.17.0.5  Bcast:0.0.0.0  Mask:255.255.0.0
              inet6 addr: 2001:db8:1::242:ac11:5/64 Scope:Global
              inet6 addr: fe80::42:acff:fe11:5/64 Scope:Link
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
              RX packets:7 errors:0 dropped:0 overruns:0 frame:0
              TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:0
              RX bytes:738 (738.0 B)  TX bytes:696 (696.0 B)
    lo        Link encap:Local Loopback
              inet addr:127.0.0.1  Mask:255.0.0.0
              inet6 addr: ::1/128 Scope:Host
              UP LOOPBACK RUNNING  MTU:65536  Metric:1
              RX packets:0 errors:0 dropped:0 overruns:0 frame:0
              TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:0
              RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
    
    Restricting SSH access from one container to another

    For c2, use the following command:

    # docker run -i -t --name c2 ubuntu:latest /bin/bash
    

    The following is the output generated:

    root@e58a9bf7120b:/# ifconfig
    eth0      Link encap:Ethernet  HWaddr 02:42:ac:11:00:06
              inet addr:172.17.0.6  Bcast:0.0.0.0  Mask:255.255.0.0
              inet6 addr: 2001:db8:1::242:ac11:6/64 Scope:Global
              inet6 addr: fe80::42:acff:fe11:6/64 Scope:Link
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
              RX packets:6 errors:0 dropped:0 overruns:0 frame:0
              TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:0
              RX bytes:648 (648.0 B)  TX bytes:696 (696.0 B)
    lo        Link encap:Local Loopback
              inet addr:127.0.0.1  Mask:255.0.0.0
              inet6 addr: ::1/128 Scope:Host
              UP LOOPBACK RUNNING  MTU:65536  Metric:1
              RX packets:0 errors:0 dropped:0 overruns:0 frame:0
              TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:0
              RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
    

    We can test connectivity between the containers using the IP address we've just discovered. Let's see this now using the ping tool:

    root@7bc2b6cb1025:/# ping 172.17.0.6
    PING 172.17.0.6 (172.17.0.6) 56(84) bytes of data.
    64 bytes from 172.17.0.6: icmp_seq=1 ttl=64 time=0.139 ms
    64 bytes from 172.17.0.6: icmp_seq=2 ttl=64 time=0.110 ms
    ^C
    --- 172.17.0.6 ping statistics ---
    2 packets transmitted, 2 received, 0% packet loss, time 999ms
    rtt min/avg/max/mdev = 0.110/0.124/0.139/0.018 ms
    root@7bc2b6cb1025:/#
    
    root@e58a9bf7120b:/# ping 172.17.0.5
    PING 172.17.0.5 (172.17.0.5) 56(84) bytes of data.
    64 bytes from 172.17.0.5: icmp_seq=1 ttl=64 time=0.270 ms
    64 bytes from 172.17.0.5: icmp_seq=2 ttl=64 time=0.107 ms
    ^C
    --- 172.17.0.5 ping statistics ---
    2 packets transmitted, 2 received, 0% packet loss, time 1002ms
    rtt min/avg/max/mdev = 0.107/0.188/0.270/0.082 ms
    root@e58a9bf7120b:/#
    
  2. Install openssh-server on both the containers:
    #apt-get install openssh-server
    
  3. Enable iptables on the host machine:
    1. Initially, you will be able to SSH from one container to another.
    2. Stop the Docker service and add DOCKER_OPTS="--icc=false --iptables=true" to the default Dockerfile of the host machine. This option will enable the iptables firewall and drop all ports between the containers.

      By default, iptables is not enabled on the host. Use the following command to enable it:

      root@ubuntu:~# iptables -L -n
      Chain INPUT (policy ACCEPT)
      target     prot opt source               destination
      Chain FORWARD (policy ACCEPT)
      target     prot opt source               destination
      DOCKER     all  --  0.0.0.0/0            0.0.0.0/0
      ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
      ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0
      DOCKER     all  --  0.0.0.0/0            0.0.0.0/0
      ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
      ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0
      ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0
      ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0
      
      #service docker stop
      #vi /etc/default/docker
      
    3. Docker Upstart and SysVinit configuration file. Customize the location of the Docker binary (especially for development testing):
      #DOCKER="/usr/local/bin/docker"
      
    4. Use DOCKER_OPTS to modify the daemon's startup options:
      #DOCKER_OPTS="--dns 8.8.8.8 --dns 8.8.4.4"
      #DOCKER_OPTS="--icc=false --iptables=true"
      
    5. Restart the Docker service:
      # service docker start
      
    6. Inspect iptables:
      root@ubuntu:~# iptables -L -n
      Chain INPUT (policy ACCEPT)
      target     prot opt source             destination
      Chain FORWARD (policy ACCEPT)
      target     prot opt source             destination
      DOCKER     all  --  0.0.0.0/0          0.0.0.0/0
      ACCEPT     all  --  0.0.0.0/0          0.0.0.0/0    ctstate RELATED, ESTABLISHED
      ACCEPT     all  --  0.0.0.0/0          0.0.0.0/0
      DOCKER     all  --  0.0.0.0/0          0.0.0.0/0
      ACCEPT     all  --  0.0.0.0/0          0.0.0.0/0   ctstate RELATED, ESTABLISHED
      ACCEPT     all  --  0.0.0.0/0          0.0.0.0/0
      ACCEPT     all  --  0.0.0.0/0          0.0.0.0/0
      DROP       all  --  0.0.0.0/0          0.0.0.0/0
      

    The DROP rule has been added to iptables on the host machine, which drops a connection between containers. Now you will be unable to SSH between the containers.

  4. We can communicate with or connect containers using the --link parameter, with the help of following steps:
    1. Create the first container, which will act as the server, sshserver:
      root@ubuntu:~# docker run -i -t -p 2222:22 --name sshserver ubuntu bash
      root@9770be5acbab:/#
      
    2. Execute the iptables command, and you will find a Docker chain rule added:
      #root@ubuntu:~# iptables -L -n
      Chain INPUT (policy ACCEPT)
      target     prot opt source         destination
      Chain FORWARD (policy ACCEPT)
      target     prot opt source         destination
      Chain OUTPUT (policy ACCEPT)
      target     prot opt source         destination
      Chain DOCKER (0 references)
      target     prot opt source         destination
      ACCEPT     tcp  --  0.0.0.0/0        172.17.0.3     tcp dpt:22
      
    3. Create the second container, which acts like a client, sshclient:
      root@ubuntu:~# docker run -i -t --name sshclient --link sshserver:sshserver ubuntu bash
      root@979d46c5c6a5:/#
      
    4. We can see that there are more rules added to the Docker chain rule:
      root@ubuntu:~# iptables -L -n
      Chain INPUT (policy ACCEPT)
      target     prot opt source               destination
      Chain FORWARD (policy ACCEPT)
      target     prot opt source               destination
      Chain OUTPUT (policy ACCEPT)
      target     prot opt source               destination
      Chain DOCKER (0 references)
      target     prot opt source               destination
      ACCEPT     tcp  --  0.0.0.0/0            172.17.0.3           tcp dpt:22
      ACCEPT     tcp  --  172.17.0.4           172.17.0.3           tcp dpt:22
      ACCEPT     tcp  --  172.17.0.3           172.17.0.4           tcp spt:22
      root@ubuntu:~#
      

      The following image explains communication between the containers using the --link flag:

      Restricting SSH access from one container to another
    5. You can inspect your linked container with the docker inspect command:
      root@ubuntu:~# docker inspect -f "{{ .HostConfig.Links }}" sshclient
      [/sshserver:/sshclient/sshserver]
      

      Now you can successfully ssh into sshserver with its IP.

      #ssh [email protected] –p 22
      

    Using the --link parameter, Docker creates a secure channel between the containers that doesn't need to expose any ports externally on the containers.

    Restricting SSH access from one container to another
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset