Allowing remote access involves opening firewall ports. Gain an overview of how to do this in UFW and iptables.
- [Instructor] When we need to connect to a remote server, one of the most important things we need to be aware of is the firewall. Regardless of what method of remote access we're using or how secure the authentication mechanism is, the firewall needs to allow access to permit us to connect. Depending on your system, you might use UFW or you might be writing iptables rules directly. Let's take a quick look at how to set up a rule using each of these approaches. UFW, the Uncomplicated Firewall, provides an easy way to make basic firewall changes on an Ubuntu system. In the background, it's really managing iptables rules for you.
But if all you need to do is allow or disallow access to certain ports, it's a lot quicker to use UFW than to deal with iptables directly. Commands for UFW follow a basic pattern, starting with the ufw command and then a directive, generally to allow or deny access to a port, then a port number and, optionally, a protocol. So to permit access using the TCP protocol on port 22, we'd write ufw allow 22/tcp. The default behavior for UFW, when it's enabled, is to deny access to anything that isn't specifically allowed.
But we can also explicitly deny access to a given combination of port and protocol. Now that I've allowed access for my SSH session, I can turn on the firewall without being disconnected. To do that, I'll write ufw enable. Specifying only a port and a protocol applies a rule to any host that might be requesting communication. UFW allows the ability to target a rule to a specific address or range of addresses and local interfaces. So you can set the firewall to allow access to a certain port only to members of the same local network or through only one network interface if your system has more than one.
To permit access only from local clients, to port 22 for example, I'd write something like this. I'd write ufw allow from 10.0.2.0/24, my local network, to any port 22. The words to any here refer to the destination address on the local system. If I left this out, it would set the rule to allow access from port 22 on this network range which isn't the behavior that we want. It's important to check out the result of adding a rule after you add it to make sure that it's been applied as you intend. You can take a look at the existing rules that you have WS managing with ufw status.
The columns show, from the firewall's perspective, how the rule works out. Here, for example, to port 22 using the TCP protocol, the action that we're specifying is allow from any host. We also have a rule allowing access to port 22 with the allow action from just our local network. These first two rules operate in IPv4 space and the third rule here operates in IPv6 space and was added automatically when we added the 22/tcp allow. When you have more than one rule, they'll be evaluated in the order in which they appear in the list.
So if you have a permissive rule, say allowing access to port 22 from any client, followed by a more restrictive rule, such as allowing port 22 access only from local addresses, the earlier rule will take precedence and the later more restrictive rule will be ignored. If you find you've made a mistake and need to remove a rule, you can do that with the delete command. Delete works both with a number, the order in which the rule appears in the list, or with a rule itself. So to delete this first rule here that was created with allow 22/tcp, I could write ufw delete 1 or ufw delete allow 22/tcp.
In this case, I'll go with 1 to remove the first rule on the list. And then I'll see what's left with ufw status. I've gotten rid of one of the permissive rules but the IPv6 one's still here. I'll get rid of that with ufw delete allow 22/tcp. And now, taking a look at the status, I'm left with my restrictive rule. UFW can't be used for everything. And in order to make more complex rules, you'll need to write iptables rules directly. The iptables rules are organized in chains. And packets are compared to each rule in the relevant chain in sequence.
If a rule can act on a packet, it does so. And if not, the packet is passed to the next rule in the chain. If the packet makes it all the way to the end of a chain without matching a condition, the default action for the chain is taken. We can take a look at these chains with the iptalbes -L command. Here at the top is the input chains which acts on packets coming into the system. And its default policy is DROP which ignores packets that don't match any of the rules provided. There's other chains here for FORWARD, in case the firewall is facilitating packet forwarding, like a router, and there's the OUTPUT chain for traffic leaving the system.
Those are the commonly used chains and the rest of these here are ones added by UFW for its various actions, rules applied before the regular iptables runs, rules applied after, and so on. Chains can refer to other chains which makes it possible, if a little complex, to build up really detailed rules, almost like programming the firewall rather than just giving it a flat list of rules. This layout is a helpful way of viewing what the firewall's doing. To edit the rules, we need to take a bit of a different approach. The whole set of chain definitions is treated as one object.
So, in order to make it change to rules, we need to export the entire set of information, make a change, and then reimport the whole set. We can dump the whole set of rules with the iptables-save command. That'll dump to the screen or you can redirect it to a file. Then we can edit that file. Notice that the syntax of the rules here is a little bit different than what we saw with the listing earlier. Here we define the name of the chains and then for each rule, we use -A to append a rule to a given chain with one rule on each line.
The rules each are targeted to a particular condition. For example, here, we're looking for a packet to be using the protocol tcp on a given destination port. And then, if the packet matches that, we tell the packet to jump to a particular chain or action. Scrolling down further here, I can see the rules that I added with UFW printed in iptables format. In this case, we're specifying the source using the protocol tcp and the destination port 22. And when a packet matches that, we're jumping to the ACCEPT action which allows the packet through the firewall to wherever it's trying to go.
We can also jump packets to DROP which ignores them, or REJECT which explicitly bounces the packet back to the sender. If I had made a change to the file, I would load it into the firewall with iptables-restore and the name of the file. On one hand, managing configurations like this makes it easy to keep a record of your firewall configuration and to keep it in source control if you need to track changes. But on the other hand, it's a little bit of work to make small changes. And for a lot of small tasks, that's why we have UFW. Keep in mind too that, while we need to allow access to remote management software through the local systems firewall, we'll also need to allow access through any upstream firewalls like the organization's firewall with the Internet.
Iptables rules can look a little cryptic but as you work with them more, they'll start to make more sense. We won't get into writing the rules here. I covered that in the network security course in this series. So take a look there for more of a look at composing rules. And be sure to check out the main page for iptables as well for a really detailed look at everything that's possible.