Submind YouTube summaries
Thumbnail for Can you fit 500M of rules into a firewall? - Boris Lytochkin - EuroBSDcon 2024

Can you fit 500M of rules into a firewall? - Boris Lytochkin - EuroBSDcon 2024

Watch on YouTube

Video summary

Boris Lytochkin from Yandex presents a detailed case study on optimizing massive firewall rule sets, specifically addressing how to manage over 500 million entries without compromising performance. Working with FreeBSD-based routers across their corporate campus and data centers, his team manages approximately 400 devices that filter traffic for thousands of users connecting via VPN or wireless networks. The core challenge lies in maintaining a dynamic firewall where rules are generated within three seconds of user connection while adhering to strict CPU and memory constraints on low-power hardware. To achieve this, the system utilizes IPFW's marking capabilities to translate logical user identities into specific kernel actions, allowing for per-user granularity without loading millions of individual static rules directly into the main rule set. The presentation outlines a multi-stage optimization process that significantly reduces the number of active firewall entries from hundreds of millions down to manageable levels through structural innovation. Initially, raw IP-to-Mark mappings are converted using lookup tables, but this still results in too many sequential checks for efficient processing. The solution involves grouping large user cohorts into "pseudo-users" and employing a specialized logic flow called a "table walker." This mechanism allows the firewall to jump between different rule sets based on protocol, port, and destination prefix rather than checking every single entry linearly. By stripping redundant source IP data after initial marking and organizing rules into Radix trees that handle prefixes at higher levels while pushing specific ports down to leaves, the system achieves high-speed filtering with a final production footprint of roughly 17 million table entries consuming about 2 GB of RAM. Despite these advancements, Lytochkin emphasizes practical limitations and architectural trade-offs inherent in this approach. The technique relies heavily on minimizing CPU cycles by checking packet header items only once per flow, which means adding new pseudo-user groups incurs additional lookup costs; therefore, it is most effective for large departments rather than small teams or individual projects. Furthermore, the system handles ICMP traffic carefully to avoid disrupting IPv6 connectivity and loads user rules dynamically via RADIUS authentication events to ensure rapid scaling from a cold boot in roughly 15 seconds. Ultimately, this architecture demonstrates that while raw rule counts can be astronomical, intelligent structuring using marks, tables, and pseudo-users allows enterprise networks to enforce complex security policies efficiently on resource-constrained FreeBSD infrastructure.
Read the full video transcript
ladies and gentlemen quick Round of Applause for our next speaker Boris will be telling us about optimizing what large firewall rule sets y I'll be in the first row to first row row to troll you about it thank you Christoph uh at least two reasons why it is the best thing to to have an after party at the end of day one well the first reason is obvious it's always cruel to have an after party and the second one is not that obvious uh I'm not standing between you guys and the after party so I have some some time and give you a good need explanation about apfw techniques so uh how many people in the room are familiar with IP IPFW rule set just raise your hands okay IPFW lookup tables okay and uh table ARG from lookup tables oh yeah that's cool so I've submitted my work in April uh and it's September now so uh We've we've added 70 million of rules on top of that uh no breakage we are running okay uh so I had to change title a bit uh this is about one million times bigger rule Set uh than I wrote about 20 years ago when I was a student of physics department of Moscow State University back then uh I started really hard to improve my uh well improve my R set composition techniques so boom and I'm uh Yandex fellow I'm working as a network foran at Yandex I manage a small team of network Engineers that are responsible for every single Network in our campus and our warehouses uh we control the the management Network for our data centers and we do provide remote access to our corporate Network as well so uh let's take a look on the simplified diagram or our Network we have around uh 400 routers that are responsible for routing and filtering uh network uh access from users uh to the services of uh inside our corporate Network and the internet no matter if they are connected through the VPN or Wireless or through wire all of these servers are running FreeBSD that is why actually I'm standing here and uh this talk is a story about the firewall we are running on these servers a story of dynamic firewall so what are the properties of this firewall why we build it and how we build it the first thing uh it limits the whole traffic from the users uh to every single network uh either in corporate Network or the Internet it's combined uh with the old services that are uh needed for the users including DCP server uh array out advertisement for IPv6 we have a cach node for our internal streaming etc etc etc another very important property is that sometimes we run these routers and firewalls on very low power and almost silent servers so we need to keep our uh CPU footprint CPU requirements and green power something yeah uh at we very low levels and uh the main reason why we call this firewall Dynamic is that when a user connects to the network uh the firewall is configured for uh processing the user's traffic within 3 seconds let's take a look on the access rules how we do it uh what is inside and how we deal with it an access rule for dynamic firewall uh uses the user uh user notation from The Source because initially we don't not have any idea what are the user IP addresses the destination is usual it's a network prefix or domain name for the service either on the corporate Network or over in the net in the net let's talk about some challenges these thing arise we still want to use per user grity this is kind of new thing uh to the techniques that is common for the Enterprise firewalls so we do support per user or per group rules uh of any kind of any amount of that we do support uh the rule sets that are different uh if a user is connected through the VPN or through the wireless network within the offices we have some sensitive services that we know do not want to expose to the VPN we do run iv6 so we have a lot of AP addresses uh that are given out to users and they change frequently and one last but not least any user can roam to any office or switch to VPN network and it is totally okay to have it everywhere it want here or she wants so this is kind of another uh challenge to be solved we need to cut some Corners the first Corner we're going to cut uh we do support uh uh UDP and TCP only there's a way to support uh other protocols but so far we haven't seen any demand for that so TCP and UDP are enough you know most of the user most of the rules we have in our uh rule set are made for large groups especially large groups like all staff members and we can we will see how we deal with this to uh to save some RAM and CP usage and another thing that we don't not want uh all users to be loaded into firewall rule set we can load them on demand and when the user is disconnected unload the rules from the kernel let's take a look on the groups we have we have at the high level of the rules We compare we combine users uh like staff all the Departments uh or we can combine users uh based on their projects basically we have couple of couple more uh ways to group the group uh users into this kind of three view structure and all of these groups are are pretty much okay uh to be used in the rule set here's the sample rule we have in our database the rule uh tells us that the user number one the user one has access to the dev server using SSH HTTP and https and the percent Mark denotes that this just a user this is a group you group rule it allows all the soft members to the DNS cache and another rule uh is all about uh giving access for all the Developers to some Network for uh their project in green you see how the processor that is uh in charge of converting these rules into apfw uh unlocks on unpacks these rules given that simple explanation here's our numbers we have about uh 50,000 of rules running in our kernel we have 65 uh th000 users and it's growing both rules and users and if you combine the uh individual user accounts and the IP address destinations you will get that number that was on the on the title so 570 million of uh entries firewall entries in the rule set the first thing to think to fix Is How We Do conversion between user account that is in the rules and the IP address because firewall is all about IP addresses and network traffic not not that users to do that uh we can use a thing that is called Mark it was integrated into uh freeb the kernel couple of years ago and this is basically uh the very similar to F FW Mark uh you can take a in Linux kernel but we had added some tweaks for that so this is a 32bit number unsigned you can uh it is saved in an Boo and bo tag for each packet you can set it using IPFW uh set Mark action you can make a check with a mark action mark up code you can do a look up in lookup tables for that and the most valuable thing for me is every uh every time you use Mark you can mask out some bits so you can play with the uh Mark as a bit field value another thing we need to uh to be uh to use for the our f is lookup tables lookup tables can have different keys for ex we will be using address key and uh number key in this talk there are different algorithms uh that are supporting different type of keys and we use uh different value types so we when you uh do a lookup table then you can fetch a value from that and that will be uh that value will be used in table Arc this is basically what I asked about table Arc in the in the beginning so let's try uh to take these two parts together and configure our firewall converting this sample rule to the to the way we can uh we can load it into to the kernel first thing we need to do we need to create a table uh and that table would like would have would help us to convert a IP address into Mark in this example we somehow we know that user one uses IP address ending one with zero one ones and user four is using another one IP address so we load it into the table now now we have a table uh comprising two records and what we can do uh we can use set Mark when looking up a source IP address in the uh packet processing and then we are going to check it using the markup code so far so good because this is the real IPFW rule that you can install into the kernel it will work the problem is that you need a special tool or a special side car to track all user IP addresses and push these uh these mappings into into the kernel for this we've built a message queue uh the publisher for the for the messages are radio server and there are only two different types of messages message uh type number one it's a new map so user IP address and the way it is is connected to the network and the second message is flashing IP address the when the user is disconnected so uh we are able to convert all these rules into the row IP OFW format but we have some issues there so we have 50,000 rules uh we have like 120 million of ores when we are comparing marks and this is not going to have to be loaded into the kernel it's too big it's too slow and I don't like it besides that IPFW is rather slow when you're uh talking about adding or removing rules and well there are only 65,000 of drule numbers and we have like 50 50,000 rules already and we want uh some spare uh spare numbers for our static firewall or some to grow it so let's take a look on another differential it's in review state so if you have any ideas or comments just go to the uh fabricator and leave your opinion I think we'll be merging it uh in a uh in a week or so and that differential allows us to use 32bit R numbers yeah it should be enough at least for a couple of years but still uh evaluating these r sequentially one by one it's not an option for us because it's too it's way too slow to cope with this what we can do we can create a per user rule set or per user rule number push all the rul all the rules that applicable for the user into its rule set and that will gives us uh a drop in rul set count to around 13 uh 13,000 let's take take a look how we do it we've seen the first step uh on the previous slides we do a look up of the source IP address of the user and we Mark uh traffic with the mark assigned for each user as well then uh we need a another table that is U that is converting Mark of the user user into uh the rule number that that hosts all the users rule rules let's take a look on this so we have two user now two rules and we are going to convert them into apfw format the rule set for user one is pretty much simple we skip Source IP address here we Den note an any here because we've checked Source address when we were looking up uh Mark for the user forward rule set is AIT a bit more uh bigger here so two two rules and an example and now we need a glue to uh forward or to to drive the traffic uh check routine to these rule sets for that we create a numberto number table uh for the key we use Mark for the value we use skip to table skip to Value so the rule rule number of the user rule set so far so good Okay so we've converted 50,000 rules to 13,000 rules but it's not enough right it's way too long to check let's optimize it even further so this is a sample rule set of user we stripped out the source IP address because we've checked it and now we're going to uh put this rule set into another table we use uh prefix as a key and protocol and the port sequence as a Val as a value you cannot put uh protocol in ports uh to the table as is so we have a we have to have another uh another step involving these checks so we have the original procedure with the 13k of rules let's add some more steps instead of just assigning a user uh rule number we are going to add per user table and look up the prefix in this table and when we find find the match there we are going to check ports and protocols there let's take a look on this on this example so this is a small Ru rule set comprising two two fire two five firewall rules and we can load it into the radx tree the normal structure for prefixes but if we do it the way uh we used to do there's a problem if we make a look up in the table we are going to uh find a more specific prefix in the table in the radic and to make it right to filter the the traffic properly we need to pull all the protocols and ports down to the leaves of the tree so we take a uh TCP 22 port and push it down uh one level then we do the same thing for the next levels etc etc etc so at the bottom of the tree all the leaves have all the protocols and ports from the uh their parents this way we can do filtering uh with a single uh table lookup let's take a look how we do it first thing we need going to strip out the prefixes and we are going to rewrite protocol and port check without without any IP addresses we number them so we make an index for that and this allow us to create a user table let's take a look for that so this is a set of rules that check for protocol ports and this is the per user table as it should be written so we have prefix in the key and uh rule number to check protocol ports as a value and now we need a glue glue is simple take a destination IP address make a look up in the table and do skip to that allows us to convert the whole rule set to another structure we have not our 500 million of rules but we have 570 million of uh table entries in the firew rule set and we don't have that amount of rules in the rule set itself it's not that good but still it's it's a way to go that that was the one of the first implementations we were running in production it was like I think eight years ago so that was done and what we're going to do we're going to take a look how we can push the total amount of table entries down to do that we can we can remember that most of the rules are done for the big groups of users mostly the whole company uh and if you have a like 65,000 uh employees then these five rules will get us more than three 300,000 table entries and that is actually a thing uh to be optimized if we're talking about small group well it's still 25,000 entries and that's not an option for us to fix that what we're going to do we're going to convert the big groups the big uh the big groups that are referenced in the rule set into pseudo users well just just change the asra just add with a PR sign and now we have converted uh all all stuff PT all group into a user and DPT devs is also a user as well we left the project one group as a group so it will be expanded to the per user rule sets but okay we've done that we do not have any kind of way to reference the new sudo users we've created to the real users rule set to do that we need some Loops in the AP W um logic you canot write a for Loop there so we're going to use uh strictly written uh with the finite amount of Cycles so we we're going to spell it out uh rule set that allows us to check another user if we do not find found a match in the per user table or we you didn't find a match in the protocoling ports so we can go from the per user table or uh layer four decision block back to the user selection let's take a look how we do that first thing we we need to create a rule set for users including pseudo users this is a sample rule set for the pseudo user called dpto all this is a set of PR set of rules that is are that we need for configur the check checking protocols and ports here take a look on the last rules rule action for the real user and the pseudo users we use different thing we we use Deni for the real users and return next rule for the P sudo user let's let's do the rul set the first thing we need we are going to do we create a table Yeah table is uh is used to convert Mark to uh to real number for each real user okay now we create another table another table tells that user with this Mark uh should be checked again DPT all or other sudo user that is is uh when the user is a member of this group basically what we can do we can do as much uh tables as we want so we can add more pseudo users to uh real user rule set let's compile this all together we create a rule set that uh checks for the per user rules uh per user table we create a set of tables that are uh responsible for converting Mark to the rule set numbers to skip or to call and we need a special uh thing we call uh table Walker that is responsible for looking up Mark and choosing where to jump into the rule set that is the way basically how we converted all these entries down to 25 million of uh uh table entries in our all set and this is the VM start from real production server uh there are about 48,000 uh users loaded into the kernel and our Ru set takes about 2 GB of RAM uh there are yeah there are 17 million of TP entries there this technique has some limitations though uh one is obvious uh every time you want to add a pseudo user to uh user rule set you you are going to add an additional table R up and it will cost you some CPU power so you don't want to convert very small groups you want to convert only large groups to super uh to pseudo users here's some tips for you if you want to build this uh this kind of rule sets uh first thing to think about is to check one packet uh header item once so if you take a source IP address check it once assign a mark and use Mark afterwards as we know rul sets inserts and deletions uh as slow keep the rule sets as small as possible well we do have like one 100,000 of rules we consider it not that small firewall rule set but still keeping the firewall Ru set small with help of help of tables and you know what Mark rules use it any questions uh is your ipw hooked both on input and output or unhooked at One Direction uh this rule set is set on input input input so clear oh how long does it take to um uh uh rebuild this in memory from a cold boot um these days we use uh loading users on demand so the whole procedure from zero to uh IPFW is a capable of uh filtering the connected users is about 10 or 15 seconds how do you expire users out of the table is that also how do you expire users out of the table yep is that done by with radius as well or uh it can it could be done by radius uh you can track the user traffic and uh know that there is no traffic from user it can reload it unload it is it is radius used for 802.1x yep okay anyone else when you answered the question on the loading time uh you aren't doing this using IPFW from SLB IPFW right yeah uh what we do actually we push the T push the rules using this BFW but all the tables are loaded through the yoka tail are you using IPv6 exclusively uh not exclusively but we treat any network with IPv6 broken as broken um so you said you're only doing uh UDP and TCP how do you handle icmp because just dropping icmp can create some problems with IPv6 okay uh this is very simple we allow most of icmp without any Dynamic rules so this is kind of it was it is branching uh prior jumping into the dynamic firewall all right am I missing anyone going once going twice thank you very much for this presentation e for