Uncomplicated Firewall (UFW) is served as a frontend tool for iptables in Linux-based machine. It's used to provide easy interface to manage firewall so you don't have to manage them through complicated iptables and netfilter commands.
So today I tried experimenting UFW with NGINX running as a Docker container on Amazon Linux 2 EC2 instance in my AWS environments.
Before this, I have launched an Amazon Linux 2 EC2 instance and have SSH and TCP port 80 allowed for incoming request in the security group attached to the instance.
Install UFW
First, ssh into the EC2 instance.
$ ssh -i example.pem ec2-user@1.23.45.678
By default, UFW is not pre-installed on Amazon Linux 2 and not available in RHEL repository. We will need to install EPEL repository to our system.
$ sudo yum update -y
$ sudo yum install epel-release -y
Then, install UFW by running command below:
$ sudo yum install --enablerepo="epel" ufw -y
Then, start UFW service and enable it to start on boot time.
$ sudo ufw enable
Run command below to ensure UFW is running:
$ sudo ufw status
Install Docker
Next, install Docker runtime in the instance:
$ sudo amazon-linux-extras install docker
$ sudo service docker start
$ sudo usermod -a -G docker ec2-user
Confirm Docker is installed and you see version as output:
$ sudo docker -v
Docker version 20.10.7, build f0df350
Then, run a NGINX container using command below:
$ sudo docker run -d --name my-nginx -p 80:80 nginx
This command will pull the Docker image from Docker Hub and run as a container on local Docker runtime. Run command below to see if my-nginx
container is running:
$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c3aee3db60f1 nginx "/docker-entrypoint.…" 22 seconds ago Up 21 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp my-nginx
Next, run curl
command to see if your website is running perfect or go to your browser and search.
$ curl -L 1.23.45.678:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
You will see a beautiful NGINX website in front of you!
Problem arises
Next, here is something fun: I want to deny anyone looking for this website through UFW!
Go back to your EC2 instance. Run the command below to enable the rule of denying incoming request with port 80 in UFW:
$ sudo ufw deny 80
Rule updated
Rule updated (v6)
Validate the deny rule is enabled:
$ sudo ufw status
Status: active
To Action From
-- ------ ----
SSH ALLOW Anywhere
224.0.0.251 mDNS ALLOW Anywhere
22 ALLOW Anywhere
80 DENY Anywhere
SSH (v6) ALLOW Anywhere (v6)
ff02::fb mDNS ALLOW Anywhere (v6)
22 (v6) ALLOW Anywhere (v6)
80 (v6) DENY Anywhere (v6)
Now, test on your host machine and check again. You should not be able to see the NGINX website on your host machine!
$ curl -L 1.23.45.678:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
Why are you still here.....
What's the problem and how to fix it
From Docker documentation, I only learned that by default, Docker directly manipulates iptables for network isolation.
There are several ways to disable this. One of it is that we don't expose the port 80.
Another way is, we can disable this Docker behaviour by creating or modifying /etc/docker/daemon.json.
$ sudo vi /etc/docker/daemon.json
{ "iptables": false }
$ sudo service docker restart
By this, we don't have to worry if other port is exposed and open when we run another container with different ports exposed.
Last, try to connect again:
$ curl -L 1.23.45.678:80
curl: (7) Failed to connect to 1.23.45.678 port 80: Operation timed out
Done!
Conclusion
This article may not explain well about the fundamental of Linux security and you may think why do I need UFW when there's security group attached on EC2 instance and you can configure the allow/deny rules easily from security group.
Well, it's for experiment purpose! I never learned about UFW or security related topics in Linux and I thought security group is the only solution to secure my instances.
Let me know in the comments about your thoughts too!
Happy coding! 💻
Top comments (2)
This is a very bad idea, if you run multiple services in Docker they won't be able to talk to each other.. For more info github.com/chaifeng/ufw-docker
Thank you for the comment and the Github link. I wasn't aware of this issue.. It definitely helps and I can use this for my next experiment. ;)