Archive for the ‘object-group’ tag
A few years ago, I developed a Perl-based application that take a template file and pukes out standardized access rules for new hosts as they’re added to the network. This works great for making sure that each host is able to be managed properly. This solution, however, is not very flexible. If I need to remove a host’s access, I may have to take out 20 rules individually. That’s not really cool, so, at the suggestion of a coworker, I’m working on a solution that uses objects, object-groups, and nested object-groups. This should minimize the configured rules and allow new host rules to be added and removed by simply adding hosts to object-groups.
Example time. Let’s say you have a bunch of RFC1918 addresses behind your firewall that all need HTTP access to one network on the InterTubes. First thing to do is to create the objects that will be involved; in this case, that’s all the networks and/or ranges. To be more specific, 192.0.2.0/24 is the public IP to which the hosts need access. The internal hosts are 192.168.0.0/24 and the IP range 10.0.0.1-25. Yes, I know the names are terrible.
object network NET1 subnet 192.0.2.0 255.255.255.0 object network NET2 subnet 192.168.0.0 255.255.255.0 object network NET3 range 10.0.0.1 10.0.0.25
Now, we can use some Snort-like configuration to create object-groups that include the objects we just created. In this case, we’re creating an InterWebs-based object-group and another for local addresses.
object-group network REMOTE-NETS network-object object NET1 object-group network LOCAL-NETS network-object object NET2 network-object object NET3
Now we can use these object-groups to create ACLs. You’ve done this before, right?
access-list TEST-ACL extended permit tcp object- group LOCAL-NETS object-group REMOTE-NETS eq www
To be sure it worked as expected, let’s take a look at the ACLs. The format sucks because the lines are so long; sorry about that.
firewall# show access-list TEST-ACL access-list TEST-ACL; 7 elements; name hash: 0x5329ed72 access-list TEST-ACL line 1 extended permit tcp object-group LOCAL-NETS object-group REMOTE-NETS eq www 0x1abfa4a0 access-list TEST-ACL line 1 extended permit tcp 192.168.0.0 255.255.255.0 192.0.2.0 255.255.255.0 eq www (hitcnt=0) 0x50797e0c access-list TEST-ACL line 1 extended permit tcp host 10.0.0.1 192.0.2.0 255.255.255.0 eq www (hitcnt=0) 0xa2159c9d access-list TEST-ACL line 1 extended permit tcp 10.0.0.2 255.255.255.254 192.0.2.0 255.255.255.0 eq www (hitcnt=0) 0x93f1c362 access-list TEST-ACL line 1 extended permit tcp 10.0.0.4 255.255.255.252 192.0.2.0 255.255.255.0 eq www (hitcnt=0) 0x512fc827 access-list TEST-ACL line 1 extended permit tcp 10.0.0.8 255.255.255.248 192.0.2.0 255.255.255.0 eq www (hitcnt=0) 0x7b11e96f access-list TEST-ACL line 1 extended permit tcp 10.0.0.16 255.255.255.248 192.0.2.0 255.255.255.0 eq www (hitcnt=0) 0xc302aa0e access-list TEST-ACL line 1 extended permit tcp 10.0.0.24 255.255.255.254 192.0.2.0 255.255.255.0 eq www (hitcnt=0) 0x2ea75962
Cool. Everything looks great, and everyone should have the access they need. If a new host with the IP of 172.16.0.28 comes online inside the network, you add a new nested object-group that includes that host. Access is automagically updated, so there’s no need for more ACL lines. Another method is to add the new host directly to the LOCAL-NETS object-group, but that’s going to limit the ways to address that box and related hosts in an ACL. I suggest you just add the new object to the object-group.
As a bonus, you can also nest object-groups into each other. For example, we can create an object-group that includes our the LOCAL-NETS and REMOTE-NETS object-groups.
object-group network ALL-NETS group-object LOCAL-NETS group-object REMOTE-NETS
I don’t know where you’d ever use that specific object-group, but you could use this technique in other ways. I’m looking to create object-groups for each interface of the firewall and creating a super-object (my term) to allow the standard access stuff. You could do the same for office networks; each office has it’s own object-group for access that is also nested in an object that provides basic access to the TubeWebs or something. Use your imagination. :)
Send any questions my way.
This article is based on an ASA 5505 running 8.3.1. Most of the config above should be portable to any 8.x except for declaring the objects. In other versions of 8.x, you may have to add host directly to the object-group. Running on 7.x and below may be a different story.
My biggest complain about modern firewalls is their lack of the ability to create rules based on URLs or HTTP streams; you have to open access between IP addresses. Yes, I know there are other means to do that, but I want my ASA/PIX/FWSM to do it without making me do so much work.
Anyway, the fact that you have to use IPs brings up some interesting problems. Let’s say you have a server in a DMZ that needs to query Google for some content. Since you’re a hard-ass network guy like I am, you tell the admin that they have provide the data flow they want to use — source IP, destination IP, protocol, port. They come back and tell you that they need their server to connect via HTTP to 184.108.40.206. You put in the rules as given, but the IP has suddenly changed on you.
Google (and lots of other big sites) uses some tricks to keep the load down on their servers and to help with availability, and one such trick is to use round robin DNS, which rotates the A record so everyone doesn’t slam the same boxes. You can query google.com once and get an address, but, when you query it again, you may get a different address. That means that when your new rules don’t work, you have to check the logs, see what got denied, open that up, rinse, and repeat. That sucks.
An easier way might be to create an object-group that includes IPs as you discover them. You put in rules based on an object-group, then, when it fails, you just add to the object-group so you don’t have to put in any more rules. The problem is that you’ll spend a lot of time building up a good baseline. If only there were a way to get a list of IP addresses that Google uses. Hmmm. *segue*
Have you ever heard of SPF netblock records? SPF is an email security mechanism that allows an email server to verify that an email message is coming from an authorized email source. In other words, when a mail server receives mail, it can check to see if the sending server is actually allowed to send mail on behalf of the source domain. It supposed to cut down on spam and whatnot, but I don’t follow it closely enough to know if it’s working. The moral of the story is that is involves a list of IP addresses that an organization maintains; Google happens to be a participant in SPF.
If you query for the TXT record _netblocks.google.com, you get back a text record that looks like this.
[jac@holland ~]$ dig +short txt _netblocks.google.com
“v=spf1 ip4:220.127.116.11/19 ip4:18.104.22.168/19 ip4:22.214.171.124/20 ip4:126.96.36.199/18 ip4:188.8.131.52/17 ip4:184.108.40.206/20 ip4:220.127.116.11/16 ip4:18.104.22.168/20 ip4:22.214.171.124/20 ip4:126.96.36.199/16 ?all”
This record includes all IP addresses that Google says is authorized to send email from google.com. That’s a lot of IP addresses, isn’t it? It might make sense that this list might also be the definitive list of Google production IPs.
My company has used this TXT record in the past to open access to Google. We had an app that needed to query Google maps, and one of our engineers was tired of nickel and diming it to death, so he found the SPF block and put them all in. Works like a champ.
There are always dangers when you rely on information from somebody else, though, right? Google’s usually pretty good about stuff like this, but what if you did the same for another company who only half-heartedly kept their records up-to-date? You may only have half of their IPs in your object-gropu. You might even wind up opening access to or from a cable modem system or from another company who bought the IP addresses.
I’ll also note that there aren’t that many domains using this technique, so finding SPF netblock records may be a challenge. It’s worth the time to do a simply query, though; it might save you some time.
Send any carved pumpkins questions my way.
I can’t believe I haven’t talked about object-groups yet. I had a whole other blog entry written up, and, when I went to link things over, I realized I couldn’t find an intro to it. Here it goes.
Welcome to the modern world. A world of wonder. A world of quickly-advancing technology. A world where clusters of machines sit behind load balancers for scalability and availability. A world where those clusters need access to other clusters. A world where your firewall rulebase gets so big that it’s unreadable without some help.
Enough with the drama already. I would say I hate the cheesy stuff, but I think my whole blog is nothing but cheesy stuff, right? To the point. Enterprise firewall configurations can get quite large with ACLs applied in different directions to different interfaces. Our ACL entries number in the 6000 range, but the firewall we’re running says we’re only at 5% utilization in the ACLE memory space. That means that our not-top-of-the-line firewall is designed to handle 120k lines of ACLs. That can be quite a handful to configure by hand. There may be an easier-to-maintain solution, though.
Let’s say you have a cluster of servers behind your CSM that all need to access a database. Since there’s a nice ASA, FWSM, or PIX between the servers and database (as there should be), you have to open up access for this connection. Let’s say that you have four servers with the IPs of 192.168.100.101-104 that need access to 10.10.10.1 on the mySQL port (TCP/3306).
access-list LIST1 permit tcp host 192.168.100.101 host 10.10.10.1 eq 3306 access-list LIST1 permit tcp host 192.168.100.102 host 10.10.10.1 eq 3306 access-list LIST1 permit tcp host 192.168.100.103 host 10.10.10.1 eq 3306 access-list LIST1 permit tcp host 192.168.100.104 host 10.10.10.1 eq 3306
Where are your remarks? Why don’t you document something for once in your life?
Anyway, that’s easy, right. Four configuation lines isn’t so bad, but some of the server admins come to you one day and tell you that the company actually marketed the new web app and that tey are adding 37 more servers to the cluster. Now the 37 new servers need the same rules, right? The server dudes also tell you that, since the app has grown so much, the DBAs have set up a split-read-write scenario where the current database handles the reads and a new database handles the writes. That’s 78 new rules (37 to the old and 41 for the new). That’s a lot of rules.
Object-groups to the rescue. An object-group is a logical group of objects (duh!) that you can use to create ACLEs. You can create a group of hosts, a group of network, or a group of ports. For our example, let’s create an object-group that includes all the hosts in the new huge cluster.
object-group network CLUSTER1 description The Huge Cluster (that's what she said) network-object host 192.168.100.101 network-object host 192.168.100.102 ... network-object host 192.168.100.141
What do we do with it, though? You treat it (almost) just like it was a host in an ACL. Remember we wanted to open access to the old database on TCP/3306, right?
access-list LIST1 permit tcp object-group CLUSTER1 host 10.10.10.1 eq 3306
If you do a show access-list LIST1 now, you’ll see that a new rules has been added for each object in the object-group. It should look something like this.
access-list LIST1 permit tcp object-group CLUSTER1 host 10.10.10.1 eq 3306 access-list LIST extended permit tcp host 192.168.100.101 host 10.10.10.1 eq 3306 (hitcnt=0) access-list LIST extended permit tcp host 192.168.100.102 host 10.10.10.1 eq 3306 (hitcnt=0) ... access-list LIST extended permit tcp host 192.168.100.141 host 10.10.10.1 eq 3306 (hitcnt=0)
Notice that the firewall created 41 rules for you out of your one configured line, but now the rules are indented. The indention means that the rules is generated automagically instead of by hand. Since you can only take out rules that you put in by hand, so you can’t take out the line allowing 192.168.100.123 access; it’s an all-or-nothing scenario. Be aware of that.
You can use object-group for ports, too. Let’s add to our example and say that the cluster will need to access the memcached instance on the database server as well. Those processes run on TCP ports 15000 – 15100.
First we build an object-group for the ports we need.
object-group service DBPORTS description mySQL and memcached ports service-object tcp eq 3306 service-object tcp range 15000 15100
Now let’s apply it to the ACL.
access-list LIST1 permit tcp object-group CLUSTER1 host 10.10.10.1 object-group DBPORT
What does the ACL look like now? Well, it’s a Duesenberg.
access-list LIST1 permit tcp object-group CLUSTER1 host 10.10.10.1 object-group DBPORTS access-list LIST extended permit tcp host 192.168.100.101 host 10.10.10.1 eq 3306 (hitcnt=0) access-list LIST extended permit tcp host 192.168.100.101 host 10.10.10.1 eq 15000 (hitcnt=0) ... access-list LIST extended permit tcp host 192.168.100.101 host 10.10.10.1 eq 15099 (hitcnt=0) access-list LIST extended permit tcp host 192.168.100.101 host 10.10.10.1 eq 15100 (hitcnt=0) ... access-list LIST extended permit tcp host 192.168.100.141 host 10.10.10.1 eq 3306 (hitcnt=0) access-list LIST extended permit tcp host 192.168.100.141 host 10.10.10.1 eq 15000 (hitcnt=0) ... access-list LIST extended permit tcp host 192.168.100.141 host 10.10.10.1 eq 15099 (hitcnt=0) access-list LIST extended permit tcp host 192.168.100.141 host 10.10.10.1 eq 15100 (hitcnt=0)
That’s a lot of ACL entries for one configuration line, isn’t it? Let’s see. 102 ports times 41 servers is 4182 lines in the ACL. You can see how might be to your advantage to use object-groups at times.
Send any candy corn questions my way.