In this tutorial we'll learn how to use doctl, the official the cloud provider command-line client, to create and manage Cloud Firewalls for a web server.

Introduction

the cloud provider Cloud Firewalls provide a powerful firewall service at the network level, protecting your resources from unauthorized traffic.

Although you can configure Cloud Firewalls through the the cloud provider Control Panel, when you have many Droplets to manage, need to script a process, or prefer working from the terminal, a command-line interface can be a better choice.

In this tutorial we'll learn how to use doctl—the official the cloud provider Command-Line Client—to create and manage Cloud Firewalls for a web server.

Prerequisites

cloud illustration for: Prerequisites

For this tutorial, you will need:

We'll be creating a one-click LAMP (Linux, Apache, MySQL, PHP) stack image running Ubuntu 16.04, in the nyc1 region, and we'll put this on a 512MB Droplet. Before beginning this tutorial, though, we recommend that you familiarize yourself with doctl and Cloud Firewalls by reading How To Use Doctl, the Official the cloud provider Command-Line Client and An Introduction To the cloud provider Cloud Firewalls.

Step 1 — Setting Up the Web Server

First, we'll choose a region for our Droplet. We'll be using nyc1 in this tutorial, but you can see all of the regions and their slugs with the following command:

				
					
[environment local]

doctl compute region list

				
			
				
					
[environment local]

[secondary_label Output]

Slug Name Available

nyc1 New York 1 true

sfo1 San Francisco 1 true

ams2 Amsterdam 2 true

sgp1 Singapore 1 true

lon1 London 1 true

nyc3 New York 3 true

ams3 Amsterdam 3 true

fra1 Frankfurt 1 true

tor1 Toronto 1 true

sfo2 San Francisco 2 true

blr1 Bangalore 1 true

				
			

Since we don't want to send passwords over the network and we want to reduce the possibility of a _brute-force attack_, we'll secure our web server with SSH key authentication.

To create a Droplet that includes an SSH key, doctl requires the SSH key fingerprint, which you can obtain with the command:

				
					
[environment local]

doctl compute ssh-key list

				
			
				
					
[environment local]

[secondary_label Output]

ID Name FingerPrint

9763174 sammy_rsa <^>your_ssh_key_fingerprint<^>

				
			

Copy the fingerprint of the SSH key you want to use with your Droplet.

Now, let's bring everything together in a single command that will create a 512MB Droplet named <^>web-1<^> in the nyc1 region, using a one-click LAMP stack image running Ubuntu 16.04 with our SSH key.

				
					
[environment local]

doctl compute droplet create &lt;^&gt;web-1&lt;^&gt; \

 --region &lt;^&gt;nyc1&lt;^&gt; \

 --image &lt;^&gt;lamp-16-04&lt;^&gt; \

 --ssh-keys &lt;^&gt;your_ssh_key_fingerprint&lt;^&gt; \

 --size &lt;^&gt;512mb&lt;^&gt;

				
			

The output gives us an overview of the Droplet we just created, including the Droplet's ID, name, IPv4 address, Memory, and more:

				
					
[environment local]

[secondary_label Output]

ID Name Public IPv4 Private IPv4 Public IPv6 Memory VCPUs Disk Region Image Status Tags

52059458 web-1 512 1 20 nyc1 Ubuntu LAMP on 16.04 new 

				
			

Note: You will need to wait a few minutes for the provisioning process to complete. Once provisioned, the Droplet will have an IPv4 address and a status of active instead of new.

Use the following command to check your Droplet's status, and, if it's fully provisioned, make note of the ID as we'll need it when assigning the firewall to the Droplet in Step 2. Do not move past this step until your Droplet's status reads active.

				
					
[environment local]

doctl compute droplet list &lt;^&gt;web-1&lt;^&gt;

				
			
				
					
[environment local]

[secondary_label Output]

ID Name Public IPv4 Private IPv4 Public IPv6 Memory VCPUs Disk Region Image Status Tags

&lt;^&gt;52059458&lt;^&gt; web-1 203.0.113.1 512 1 20 nyc1 Ubuntu LAMP on 16.04 active 

				
			

Next, use doctl to log into the Droplet via SSH, enabling your LAMP installation and getting additional instructions about how to prepare your server for production use. If you get a connection refused error message, your Droplet is not yet ready. Wait a few minutes and then re-run the list command to verify that your Droplet's status is set to active before continuing.

				
					
[environment local]

doctl compute ssh &lt;^&gt;web-1&lt;^&gt;

				
			
				
					
[secondary_label Output]

...

-------------------------------------------------------------------------------

Thank you for using the cloud provider's LAMP Application.



LAMP has now been enabled. You can access your LAMP instance at:

Your web root is located at /var/www/html and can be seen from

 http://203.0.113.1

...

				
			

After you configure the Droplet for your needs, exit the SSH session.

				
					
[environment]

exit

				
			

Finally, point your web browser to the Droplet's IP address to make sure that the LAMP stack is working correctly. You should see the default the cloud provider one-click LAMP stack landing page with the message: "Please log into your droplet via SSH to configure your LAMP installation." If you don't, re-trace the preceeding steps to ensure that you've enabled LAMP and that you've correctly copied your Droplet's IP address into your browser.

Because we've already completed the LAMP configuration required for this tutorial, we're ready to move on to protecting the Droplet from unauthorized traffic.

Step 2 — Creating the Firewall for the Web Server

To begin, we'll use the Droplet ID that we got from the doctl compute droplet list command in Step 1 to create a Cloud Firewall named <^>web-firewall<^> that allows inbound SSH connections on port 22 and all outbound TCP, UDP and ICMP connections. This will let us administer the server from the command line while still giving many fundamental services the ability to operate normally.

The protocol field is required and must be set either to tcp, udp, or icmp, and you must include a ports value for all protocols except icmp which, by its specification, doesn't require one.

The address field specifies which IP addresses are allowed to access a given port. If you want to allow traffic from all IPv4 addresses, use 0:0:0:0/0, and if you want to allow traffic from all IPv6 addresses, use ::0/0.

Lastly, each Firewall that you create must have at least one rule, either under the --inbound-rules or --outbound-rules flag, and all values must be entered as comma-separated key:value lists. Use a quoted string of space-separated values for multiple rules.

Now, use the create command create the firewall:

				
					
[environment local]

doctl compute firewall create --name &lt;^&gt;web-firewall&lt;^&gt; \ 

 --droplet-ids &lt;^&gt;your_droplet_id&lt;^&gt; \

 --inbound-rules "protocol:tcp,ports:22,address:0.0.0.0/0,address:::/0" \

 --outbound-rules "protocol:icmp,address:0.0.0.0/0,address:::/0 protocol:tcp,ports:all,address:0.0.0.0/0,address:::/0 protocol:udp,ports:all,address:0.0.0.0/0,address:::/0"

				
			

The output contains a basic overview of the new Cloud Firewall. Make note of the Cloud Firewall's ID, as you'll use it in Step 3 to add additional rules to the Firewall.

				
					
[environment local]

[secondary_label Output]

ID Name Status Created At Inbound Rules Outbound Rules Droplet IDs Tags Pending Changes

&lt;^&gt;c7b39b43-4fcc-4594-88f2-160a64aaddd4&lt;^&gt; web-firewall waiting 2017-06-17T21:20:38Z protocol:tcp,ports:22,address:0.0.0.0/0,address:::/0 protocol:icmp,ports:0,address:0.0.0.0/0,address:::/0 protocol:tcp,ports:0,address:0.0.0.0/0,address:::/0 protocol:udp,ports:0,address:0.0.0.0/0,address:::/0 &lt;^&gt;your_droplet_id&lt;^&gt; droplet_id:&lt;^&gt;your_droplet_id&lt;^&gt;,removing:false,status:waiting

				
			

If you ever need to specify a port range, use the following format:

				
					
--inbound-rules "protocol:tcp,&lt;^&gt;ports:8000-8080&lt;^&gt;,address:0.0.0.0/0,address:::/0"

				
			

You can also use the droplet_id flag instead of the address flag. This can be particularly useful in setups that involve multiple Droplets communicating with each other.

				
					
--inbound-rules "protocol:tcp,ports:8000-8080,droplet_id:&lt;^&gt;your_droplet_id&lt;^&gt;"

				
			

And, you can combine multiple address or droplet_id fields into a single rule, like:

				
					
--inbound-rules "protocol:tcp,ports:8000-8080,droplet_id:&lt;^&gt;your_first_droplet_id&lt;^&gt;,droplet_id:&lt;^&gt;your_second_droplet_id&lt;^&gt;"

				
			

At this point, confirm that the Cloud Firewall is working correctly by pointing your web browser to the Droplet's IP address. You should see a message indicating that the site is no longer reachable. If you don't, double-check the output from the previous create command to make sure you didn't miss any error messages.

Lastly, even though our inbound rule should already allow for SSH, we'll verify it using doctl.

				
					
[environment local]

doctl compute ssh &lt;^&gt;web-1&lt;^&gt;

				
			

If you're unable to connect to the Droplet, the How To Troubleshoot SSH tutorial series will help you diagnose the problem.

Once you've successfully connected to the Droplet, exit the SSH session:

				
					
[environment]

exit

				
			

As we've now verified that the Cloud Firewall is working correctly, we'll add an additional rule to allow for incoming traffic to the web server.

Step 3 — Adding Additional Rules

Using the Firewall ID that we got from the doctl compute firewall create command in Step 2, we are now going to add a rule to allow inbound TCP traffic for Apache on port 80.

We'll use the add-rules command, which requires a Firewall ID and at least one rule. Rules are specified using --outbound-rules and --inbound-rules flags, just like in Step 2.

				
					
[environment local]

doctl compute firewall add-rules &lt;^&gt;c7b39b43-4fcc-4594-88f2-160a64aaddd4&lt;^&gt; \

	--inbound-rules "protocol:tcp,ports:80,address:0.0.0.0/0,address:::/0"

				
			

If you need HTTPS, allow inbound TCP traffic on port 443.

				
					
[environment local]

doctl compute firewall add-rules &lt;^&gt;c7b39b43-4fcc-4594-88f2-160a64aaddd4&lt;^&gt; \

	--inbound-rules "protocol:tcp,ports:443,address:0.0.0.0/0,address:::/0"

				
			

If successful, this command will produce no output. If you receive an error message, follow the on-screen instructions to diagnose the problem.

Now, re-point your web browser to your Droplet's IP address. This time you should see the default the cloud provider one-click LAMP stack landing page again. If you don't, double-check that you've correctly copied your IP address into your web browser and then re-trace the preceeding steps.

If you have additional web servers that you'd like to protect, continue on to Step 4. Otherwise, skip ahead to Step 5 where we'll manage Cloud Firewalls with tags.

(Optional) Step 4 — Adding Droplets to the Firewall

If you have multiple Droplets, you can apply the same Cloud Firewall to each of them.

Use the add-droplets command to add additional Droplets to a Cloud Firewall. This command requires a Cloud Firewall ID as an argument, and it uses the droplet-ids flag to determine which Droplets to apply the Firewall to.

If you don't know the Cloud Firewall's ID, use the list command:

				
					
[environment local]

doctl compute firewall list

				
			
				
					
[environment local]

[secondary_label Output]

ID Name Status Created At Inbound Rules Outbound Rules Droplet IDs Tags Pending Changes

&lt;^&gt;c7b39b43-4fcc-4594-88f2-160a64aaddd4&lt;^&gt; web-firewall succeeded 2017-06-17T21:20:38Z protocol:tcp,ports:22,address:0.0.0.0/0,address:::/0 protocol:tcp,ports:80,address:0.0.0.0/0,address:::/0 protocol:icmp,ports:0,address:0.0.0.0/0,address:::/0 protocol:tcp,ports:0,address:0.0.0.0/0,address:::/0 protocol:udp,ports:0,address:0.0.0.0/0,address:::/0 52059458 

				
			

You can also use the list command to get Droplets' IDs:

				
					
[environment local]

doctl compute droplet list

				
			
				
					
[environment local]

[secondary_label Output]

ID Name Public IPv4 Private IPv4 Public IPv6 Memory VCPUs Disk Region Image Status Tags

&lt;^&gt;51146959&lt;^&gt; test-1 203.0.113.1 512 1 20 nyc1 Ubuntu LAMP on 16.04 active 

&lt;^&gt;52059458&lt;^&gt; web-1 203.0.113.2 512 1 20 nyc1 Ubuntu LAMP on 16.04 active 

				
			

Using the following doctl command, we'll add the <^>test-1<^> Droplet to the <^>web-servers<^> Firewall, which has an ID of <^>c7b39b43-4fcc-4594-88f2-160a64aaddd4<^>:

				
					
[environment local]

doctl compute firewall add-droplets &lt;^&gt;c7b39b43-4fcc-4594-88f2-160a64aaddd4&lt;^&gt; \

	--droplet-ids &lt;^&gt;51146959&lt;^&gt;

				
			

If you don't receive any output, the command was successful. If you receive an error message, follow the on-screen instructions to diagnose the problem.

And, if you want to add multiple Droplets at once, separate them out using commas. Note that there are no spaces between two IDs:

				
					
--droplet-ids &lt;^&gt;51146959&lt;^&gt;,&lt;^&gt;52059458&lt;^&gt;

				
			

Now, let's use Tags for easier Cloud Firewall management.

Step 5 — Using Tags

At this point, we've added individual Droplets to the Cloud Firewall, but Cloud Firewalls also support Tags for easier management of multiple resources. To better understand how Tags work, see How To Tag cloud servers.

In this step, we'll tag Droplets, add Tags to the Cloud Firewall, and then remove the individual Droplet IDs from the Firewall keeping the Droplets secure by way of Tags.

Before we can add a Tag to a Droplet using doctl, we need to first create the Tag with the tag create command:

				
					
[environment local]

doctl compute tag create &lt;^&gt;web-servers&lt;^&gt;

				
			
				
					
[environment local]

[secondary_label Output]

Name Droplet Count

&lt;^&gt;web-servers&lt;^&gt; 0

				
			

Once the Tag is created, apply it to the Droplet using the droplet tag command. This command takes the Droplet ID as an argument, and it gets the Tag name from the --tag-name flag.

				
					
[environment local]

doctl compute droplet tag &lt;^&gt;52059458&lt;^&gt; \

	--tag-name "&lt;^&gt;web-servers&lt;^&gt;"

				
			

If you want to secure multiple Droplets with one Cloud Firewall, repeat the previous command for each Droplet.

Next, add the Tag to the Cloud Firewall with the add-tags command, which takes the Firewall ID as an argument and gets the list of Tag names to use from the --tag-names flag:

				
					
[environment local]

doctl compute firewall add-tags &lt;^&gt;c7b39b43-4fcc-4594-88f2-160a64aaddd4&lt;^&gt; \

	--tag-names &lt;^&gt;web-servers&lt;^&gt;

				
			

If you don't receive any output, the command was successful. If you receive an error message, follow the on-screen instructions to diagnose the problem.

And, if you need to add multiple Tags, provide them as a comma-separated list:

				
					
--tag-names &lt;^&gt;web-servers&lt;^&gt;,&lt;^&gt;backend-servers&lt;^&gt;

				
			

Finally, we can remove the Droplet's ID from the Firewall, because the Droplet is part of the web-servers Tag, and that entire Tag is now protected.

				
					
[environment local]

doctl compute firewall remove-droplets &lt;^&gt;c7b39b43-4fcc-4594-88f2-160a64aaddd4&lt;^&gt; \

	--droplet-ids &lt;^&gt;52059458&lt;^&gt;

				
			

Repeat the previous step for each Droplet you want to secure by Tag only.

[warning]

Warning: Removing non-tagged Droplets from the Cloud Firewall leaves the Droplets unprotected from unauthorized traffic.

You now have a fully configured Cloud Firewall which will protect your web server from unauthorized traffic. If you also want to delete a rule from the Firewall, continue on to Step 6.

(Optional) Step 6 — Removing Rules from the Firewall

If you want to remove a rule from a Cloud Firewall, use the remove-rules command.

The remove-rules command takes a Firewall ID as its argument, and rules are specified using the --outbound-rules and --inbound-rules flags. Note that the specified rule must be exactly the same as the rule that was used during creation.

				
					
[environment local]

doctl compute firewall remove-rules &lt;^&gt;c7b39b43-4fcc-4594-88f2-160a64aaddd4&lt;^&gt; \

	--inbound-rules &lt;^&gt;protocol:tcp,ports:80,address:0.0.0.0/0,address:::/0&lt;^&gt;

				
			

If you don't receive any output, the command was successful. If you receive an error message, follow the on-screen instructions to diagnose the problem.

Conclusion

In this tutorial, we used doctl to create the cloud provider Cloud Firewalls, add rules to those Firewalls, add additional Droplets to the Firewalls, manage Firewalls with Tags, and remove rules from Firewalls.

To learn other ways to use Cloud Firewalls, see How To Organize the cloud provider Cloud Firewalls.

And, to learn about troubleshooting Cloud Firewalls, visit How To Troubleshoot cloud firewalls.