application delivery
2320 TopicsAutomating F5 Application Delivery and Security Platform Deployments
The F5 ADSP Architecture Automation Project The F5 ADSP reduces the complexity of modern applications by integrating operations, traffic management, performance optimization, and security controls into a single platform with multiple deployment options. This series outlines practical steps anyone can take to put these ideas into practice using the F5 ADSP Architectures GitHub repo. Each article highlights different deployment examples, which can be run locally or integrated into CI/CD pipelines following DevSecOps practices. The repository is community-supported and provides reference code that can be used for demos, workshops, or as a stepping stone for your own F5 ADSP deployments. If you find any bugs or have any enhancement requests, open an issue, or better yet, contribute. The F5 Application Delivery and Security Platform (F5 ADSP) The F5 ADSP addresses four core areas: how you operate day to day, how you deploy at scale, how you secure against evolving threats, and how you deliver reliably across environments. Each comes with its own challenges, but together they define the foundation for keeping systems fast, stable, and safe. Each architecture deployment example is designed to cover at least two of the four core areas: xOps, Deployment, Delivery, and Security. This ensures the examples demonstrate how multiple components of the platform work together in practice. DevSecOps: Integrating security into the software delivery lifecycle is a necessary part of building and maintaining secure applications. This project incorporates DevSecOps practices by using supported APIs and tooling, with each use case including a GitHub repository containing IaC code, CI/CD integration examples, and telemetry options. Demo: F5 Distributed Cloud WAF and BIG-IP Advanced WAF Resources: F5 Application Delivery and Security Platform GitHub Repo and Guide ADSP Architecture Article Series: Automating F5 Application Delivery and Security Platform Deployments (Intro) F5 Hybrid Security Architectures (Part 1 - F5's Distributed Cloud WAF and BIG-IP Advanced WAF) F5 Hybrid Security Architectures (Part 2 - F5's Distributed Cloud WAF and NGINX App Protect WAF) F5 Hybrid Security Architectures (Part 3 - F5 XC API Protection and NGINX Ingress Controller) F5 Hybrid Security Architectures (Part 4 - F5 XC BOT and DDoS Defense and BIG-IP Advanced WAF) F5 Hybrid Security Architectures (Part 5 - F5 XC, BIG-IP APM, CIS, and NGINX Ingress Controller) Minimizing Security Complexity: Managing Distributed WAF Policies
566Views3likes0CommentsYou Don't Have to Have Played to Understand the Game
Andy Reid barely played football. He was a community college tackle who transferred to BYU and then rode the bench for most of his time in Provo. Teammates remember him as the guy in the film room, not the guy on the field. He spent his Saturdays watching, taking notes, and pestering head coach LaVell Edwards with so many questions about strategy that Edwards eventually told him: Kid, you should coach. That’s the origin story of three Super Bowl wins for my local Kansas City Chiefs, six appearances across the Chiefs and Eagles, and one of the winningest coaches in NFL history. Not a stud player who worked his way down to the sideline, but a guy who asked a lot of questions, kept asking them, and turned that into a career. Richard Williams had never picked up a tennis racket in his life when he saw Virginia Ruzici win a tournament on TV in 1978 and decided his daughters were going to be world champions. He taught himself the sport from books and instructional videos and then wrote and implemented a 78-page plan for coaching Venus and Serena on the public courts in Compton when they were very young. Thirty Grand Slam singles titles between them later and the “you have to have played at the highest level to coach at the highest level” theory was looking pretty thin. Nobody looks at Reid's three Super Bowl rings and says “yeah, but did you really understand it without playing in the league?” Nobody tells Richard Williams his daughters’ Grand Slam titles have an asterisk because he learned the game from a VHS tape. We accept, in sports, that there’s more than one way to know a thing. Somehow that grace evaporates the second AI enters the conversation. Doing isn't understanding There’s a flavor of pushback on AI use that goes something like: “you have to do it manually first to really understand it.” Sometimes that’s gatekeeping in a wise-elder’s costume. Sometimes it’s a genuine concern. An experienced person who built their intuition the hard way, watching newer folks skip the grind, and worrying (not unreasonably) that the intuition won’t form. But “doing it manually” and “understanding it” aren’t the same thing. They overlap, but they’re not the same thing. You can grind through a problem manually for years and still not understand the system around it. And you can understand a system deeply without having implemented every piece of it yourself, if you’re willing to ask enough questions. The questioning is the work Here’s the part I think people miss when they’re worried about AI making us dumber: A lot of what an expert does for you, when you’re lucky enough to have one, is answer questions patiently. Over and over. Sometimes the same question is phrased three different ways because you didn’t quite get it the first time. Sometimes a dumb question that you’d be embarrassed to ask on a Slack channel. Good mentors don’t get tired of this. But there are very few good mentors. They’re busy, and you only get so many of them in a career. I’ve been at this for thirty years now and I can count the great mentors I’ve had on one hand. LLMs don’t get tired. They don’t sigh. They don’t make you feel stupid for asking why something works the way it does for the fourth time. And the act of formulating the question, asking "what exactly am I confused about?" and "what do I need to know to clear the fog?” That’s a huge chunk of where understanding actually comes from. The model is a sparring partner for your own thinking, if you let it be one. Use it as a vending machine and you’ll get exactly that: answers, not understanding. The tragic version of LLM use is the one where someone pastes the problem, takes the answer, ships it, and walks away no smarter than they started. Then does it again the next day. And the next. Building a career out of outputs they couldn’t reproduce or defend if you took the tool away. That's the version the skeptics are right about. It just isn’t the only version. Andy Reid didn’t need to have been a pro-bowl tackle to understand offensive football. He needed to watch carefully, ask the right questions, and think rigorously about what he was seeing. Richard Williams didn’t need to have been on tour. He needed books, tapes, and the willingness to do the homework. Playing at the highest level is one path to understanding. But for systemic thinking, tactical thinking, architectural thinking, it might not always be the best one. Two things I learned this week First: I’m working on a side project where the FastAPI Cloud backend runs as a two-instance replica deployment. I started on SQLite, which worked fine until I realized writes were landing in whichever instance happened to handle the request, leaving me with two file-based databases with immediate data drift. I moved to a serverless Postgres database (Neon) to give both instances a single source of truth, and once I was there, realized I could just point dev and prod at the same data. Yes, in a real production system this is an anti-pattern and I’d never recommend it. But for a small project where I’m iterating fast and the bottleneck is my own understanding of the problem, not having to migrate data back and forth every time I want to test a frontend change or hunt down a bug? Game changer. I got there by talking the tradeoffs through with my good friend Claude. What breaks, when it breaks, what the actual risk surface looks like at my scale. Nobody handed me a "here's when to break the rule" tutorial. I asked questions until I understood the rule well enough to break it on purpose. Second: I'm building an on-box tool for BIG-IP (article coming soon), and I hit the HA problem. How do I keep state synced across boxes? My first instinct was file-based storage on the host, which, it turns out, is exactly where AS3 and SSL Orchestrator started. SSLO went a step further and built a dedicated sync layer called gossip to keep those files coordinated across the cluster. Over time, both products converged on a different approach: data-groups for metadata and iFiles for larger payloads, both of which ride along with standard config sync. That's a much smaller surface area to maintain, and it leans on infrastructure the platform already guarantees. So I'm following the same path: metadata in data-groups, data blobs in iFiles. I figured this out by interrogating Claude about how those products were architected, why they made the choices they did, and what the failure modes were. I could have read the source, and I could have tried to track down the developers and architects (and I should have over dinner to get the inside scoop). But the speed of “ask, get an answer, ask the next question, get an answer” let me sketch the whole design space in an afternoon. That's not skipping the understanding. That’s building it. Get off whose lawn? I get the resistance. Some of it is "get off my lawn." Some of it is genuine expertise feeling devalued. Some of it is real fear about what this technology means for the people who come up behind us. None of those concerns are stupid. The people who built their understanding the hard way, by tinkering, by breaking things, by reading source code under duress at 2am because there was no other way to get the system back online? They are not wrong about the value of that path. They earned something real in all that trial by fire. Some of them are the best engineers I know. The intuition that comes from years of manual struggle is a kind of literacy that doesn’t have a shortcut, and the people who have it are the ones I most want in the room when something goes sideways. But I’d push back on the specific claim that you must do every step manually to understand the thing. You don’t. Engage with it seriously. Ask real questions and chase the answers until they hold together. Be willing to be wrong. Notice when you’re wrong, and update accordingly. Used well, an LLM doesn’t dull that loop. It tightens it. The design decision, the tradeoff, the bet, I’m getting to that part of the problem sooner than I would have otherwise. Reid had Edwards. Williams had the library. The skeptics aren’t wrong that some understanding only comes from doing. They’re wrong that this is one of them.37Views1like0CommentsF5 BIG-IP OneConnect and MinIO S3 – Finetune TCP
The BIG-IP OneConnect feature may in some cases increase network throughput by efficiently managing connections created between the BIG-IP system and back-end pool members. The OneConnect feature works with HTTP Keep-Alives to allow the BIG-IP system to minimize the number of server-side TCP connections, such as those carrying S3 to MinIO AIStor servers, by making existing connections available for reuse by other clients. Why bother you might say, surely setting up rapid TCP connections is something BIG-IP and modern Linux-based server storage pools have well in hand? The reality is there can be tangible benefits from orchestrating the readiness of bulk TCP connections in the backend, advantages can be had by using pooled and immediately "on" TCP connections, potentially squeezing more performance from your S3 cluster. The goal of the following lab tests is to allow a reader to determine if further investigation is needed, to see if the “juice might be worth the squeeze”. Getting TCP Primed and Ready for S3 Flows A chief reason why a BIG-IP results in a scalable, performant S3 cluster is its role as a force multiplier. As opposed to S3 clients addressing individual nodes per request, we aim to abstract the full pool of nodes with a BIG-IP virtual server, a sort of "super" server which can incorporate all back-end resources. This means transactions can automatically be fanned out logically and land upon optimal origin servers in the pool. For S3 clients one target, the virtual server, for requests keeps complexity “out of sight, out of mind”. A broad set of algorithms are built in to BIG-IP as the front end for an AIStor cluster, to distribute load and avoid performance “hot spots” from inadvertently degrading service. The BIG-IP, though, is more than a load balancer. It’s a purpose-designed communications appliance, in both physical and software forms. One aspect of the appliance is the ability to sculpt protocol behavior to enhance the application experience. Drilling down, why would the back-end, from BIG-IP to a server cluster, actually benefit from controlled characteristics of something as ubiquitous as TCP, a foundational protocol that traces back to the 1970s? For one thing, the standard TCP control plane setup for a connection, SYN-SYN/ACK-ACK, is not completely without latency. In the context of wide-area networks, it is more significant than between collocated BIG-IPs and MinIO servers, however, it is not completely negligible. A method to consistently and frequently bypass this three-message setup phase is of interest. A second consideration is the memory consumption for each TCP connection; estimates vary, but a value of 3 to 4 kilobytes is a common assumption with Linux platforms. The reality of large ebbs and flows in TCP connections, as traffic rises and wanes, means many connections have passed through the useful data transport “established” phase and per the protocol specification are in the TIME_WAIT state, frequently referred to as 2MSL (two-times maximum segment lifetime). With 2MSL, connections cannot be removed entirely from memory as the legacy of TCP was to be wary of segments arriving late from peers, even long after the receiver had sent a TCP FIN message and received a TCP FIN ACK. Legacy networks exhibited more acute latency and packet-by-packet routing differences, meaning a safeguard TIME_WAIT was required. To this day, modern Linux systems often hold older, unused, TCP sessions in this state for 60 seconds, and some Windows platforms reach 3 to 4 minutes. The net result, the resource consumption on server resources, due to the true number of TCP connections in various states, is often much more significant than just the momentary live “data-on-the- wire” would suggest. A third of many reasons exists as to why a solution to constrain the number of new TCP sessions requiring setup is valuable. It is a byproduct of the number of round-trip times (RTT) required to maximize the TCP congestion window. In other words, the round trips to fully capitalize the fullest data carrying capacity of a newly setup connection. The amount of data in flight, unacknowledged, is traditionally only grown when positive feedback from across the network appears, the arrival of TCP ACK messages. To avoid overwhelming network capacity, algorithms like TCP Slow Start with Congestion Avoidance only expand the carrying capacity of the connection after a surprisingly high number of round trips. Best case, newer congestion control algorithms like CUBIC and BRR can take a few round trips, older stacks may take a dozen or more RTT to move "peak data". All of these reasons contribute to the notion that having an established pool of ready and waiting TCP connections primed to resume moving data from the front side of BIG-IP to the backend AIStor server pool members could be beneficial. How OneConnect Actually Works Through use of HTTP Keep-Alive directives, BIG-IP can instruct origin servers behind it, such as AIStor nodes, to keep TCP connections established, even after transactional data flow has completed. This is a good fit for S3 API compatible data flows which harness the HTTP protocol, normally within an HTTPS encrypted flow, and as such are excellent candidates for the use of Keep-Alives. OneConnect adds fine grain controls for Netops to control things like the maximum number of such connections to maintain, the amount of re-use in terms of total data before tearing down, and the ability to cap the amount of time idle connections are held up. One aspect of the HTTP-centric behavior we are trying to leverage is that the BIG-IP must be working in a mode where both full-header inspection and manipulation are supported. This means a “standard” virtual server profile, with its ability to perform full TLS interception, is a good fit. An http family of profile is also recommended. A pure layer-four proxy, such as the FastL4 server profile where TLS in not decrypted on the box, while very fast, is not a fit. A Lab Validation of OneConnect and MinIO AIStor To understand the out-of-the-box expected result of enabling a OneConnect profile, the following 4 node MinIO setup was used in a lab. To drive S3 load, and be able to have fine grained control of that traffic, the Linux command-line “warp” utility was installed on an Ubuntu client machine. Warp is an open-source load S3 traffic generator than can be downloaded here. Warp offers full “mixed” benchmarking options, mixed in the sense it can easily combine uploading, downloading, and deleting objects from an appropriately named “warp-benchmark-bucket” bucket on AIStor. The nice aspect is that an array of object sizes will automatically be included in each test run and cleaned up for you at the end. In the testing done, a fixed-size object, an e-book of 870 kilobytes, was used as the test object and warp was instructed to download it repeatedly. The --duration and --concurrent flags allow for control of how long tests run and the number of concurrent TCP connections to the BIG-IP virtual server that will be harnessed for S3 transactions. A simple S3 test syntax would be as follows, which runs a 1-minute test with transactions spread across 400 TCP connections: sudo ./warp get --host 10.1.40.163:9000 --list-existing --access-key 0t7hrh3nxhJPzEgBSEY8 --secret-key dfksjBkS3Bf5qs0R6rqkzijPrvp9clrn7IXq9UYX --duration 1m --concurrent 400 For TLS support, including the ability to accept certificates without requirement of authenticating them, simply add flags –tls and –insecure to the above example. Behavior Without the OneConnect Profile The lab-oriented S3 validation testing with MinIO AIStor started with a standard BIG-IP operating with a virtual server of type “Standard” to ensure the proxy operation had control and visibility of layer 7 features, in lock step with this the client’s http profile was set to the standard “http” profile. This will allow us to see the impact upon MinIO S3 traffic of subsequent adjustments, such as enabling OneConnect. As warp conducts a one-minute test, one practical screen to watch is the pool member connections and requests screen. To recap, in this warp test, all S3 transactions were GETs pulling an 800 kB electronic document from the cluster, repeatedly. As seen in the diagram, at this early stage within the one-minute test run, 400 backend TCP connections have been distributed with relatively equal weighting to the four backend AIStor nodes. To this point, as seen in the screenshot, 1.9K S3 transactions have been completed. At the end of the test run, warp provides a succinct summary of the results. In the case of this one-minute test run, we see 9,485 object downloads, with no errors, have been achieved (double-click to enlarge image). This corresponds to the pool statistics provided by BIG-IP. The key observation is that all backend TCP connections have now been torn down, there is zero left in place for this pool. Note also, the 9.5K requests displayed line up with the warp summary. Configure and Understand Settings of the OneConnect Profile To create a OneConnect profile for a lab evaluation, follow the path displayed below and click the (+) button to create a new instance. As with many shipped profiles with BIG-IP, it’s important to create a new profile instance. The idea is, although one can use the default, it’s not good practice to modify it. Instead, a new instance of the profile is created, and can be customized, and this can certainly be based upon the default. The following shows a new instance “OneConnect_Eval” profile, based upon the default, with some of the key parameters called out. After a virtual server, in our case for S3 traffic, has satisfied the transactions received, when tied to the above profile, the BIG-IP will keep any resultant idle TCP connections to the backend AIStor nodes established. When new S3 requests arrive, subsequently, OneConnect will analyze and, if available, use these idle connections to promptly communicate with the backend AIStor servers. The highlighted fields are to focus on the maximums, for instance, the highest number of idle connections that will be possibly maintained across server pools. Simply servicing a small burst of initial S3 traffic will only see just the required backend connections added afterwards to the OneConnect connection pool. Connections are not proactively established in advance of first seeing an actual need. Similar highlighted values put into place limits on the maximum age of the backed connections, although origin servers are free to close connections at their discretion. A maximum number of times an idle connection may be reused is also configurable, a level of fidelity common to most profiles within BIG-IP. A last note on two other fields. It’s noted that the option to “share pools” exists, enabling this would allow similar virtual servers, perhaps variants on front doors into MinIO clusters, to share back-end connections. Also, the connections on the back-end, internal side of a BIG-IP normally do not use the client source IP address observed by the virtual server on the front-end. Instead, the source address in use is normally pulled from “automap”, which is to say an available self-ip defined on the origin pool side of BIG-IP or an address from a configured SNAT pool. The source mask, if set to none, means transactions can utilize an idle OneConnect TCP connection with one source address, even if SNAT had suggested the use of another source address. As mentioned above, BIG-IP tends to allow the highest degree of flexibility possible, so a full 32-bit mask could restrict connection reuse to only an idle connection with a completely matching SNAT source IP address after the load balancing decision has been made. Evaluate OneConnect Under Lab Conditions With a S3 BIG-IP virtual server fronting traffic for the four-node AIStor cluster, warp was again used to apply load with high concurrency on the front end. There is a real-time OneConnect display, which can be found in the following spot in the BIG-IP TMUI interface. While the warp run is underway, we see that OneConnect is already in on the action. In the screenshot below, we are being told that OneConnect has seen 484 backend TCP connections created, and 3.8K times a TCP connection has already been re-used to carry a S3 transaction. At this snapshot in time, 94 connections are idle and candidates to carry new S3 requests, with the maximum idle count so far observed being 132. A very quick shorthand to know if OneConnect is taking place, beyond the specific counters above, is to simply watch the cluster pool statistics between test iterations of warp. If S3 traffic load is not actively being presented to the front end of BIG-IP, and “current” backend TCP connections are present in bulk, OneConnect is in effect. Remember, frequently refresh statistics or enable auto-refresh when doing analysis. Note that by design, any TCP-based health monitor traffic to pools that you may have configured is happily not included in the pool statistics, nicely avoiding any confusion. After two full warp runs, with high concurrency, the following were the OneConnect metrics. Of the roughly 19,000 S3 transactions unleashed by warp over two test runs, spaced out by a few minutes, 18,500 transactions are noted to have used existing and retained tcp connections. How cool is that? The value of OneConnect is compounded with intermittent S3 traffic intended for the MinIO backed, with AIStor servers. By default closing out idle connections that remain dormant for five minutes; traffic bursts within this window simply leverage the pool of waiting connections. The following full test run demonstrates that not one new TCP connection was required to complete another high-rate warp session. Addressing Non-Concurrent Traffic Loads Targeting AIStor An interesting feature of Minio warp for lab testing is the ability to send high S3 traffic loads over a highly controlled number of concurrent TCP connections to the virtual server on the front side of BIG-IP. By default, warp runs with 20 concurrent connections, with experiments leveraging S3 traffic over as few as one single connection and all the way up to hundreds of concurrent connections. In real world scenarios, especially with S3 traffic often being generated by applications and automation, the number of new connections per second a single traffic source may impose is worth noting. Take for example, a trivial bash shell script leveraging a repeated curl command requesting a MinIO-housed object, in this case with TLS enabled on both sides of BIG-IP. The net result in this case is a new S3 retrieval for each and every request of the object. As such, in a non-OneConnect setup, the BIG-IP counters display 100 connections to achieve 100 S3 retrievals. The amount of TCP setup alone, coupled with the fact that this is a full TLS interception scenario, and as such TLS will need to be established or resumed for each backend S3 request should be top of mind. With a standard OneConnect profile applied to the virtual server, the exact same test has a very different result on the wire, as seen below. We observe, in this simple lab setup at least a reduction of 92 percent in the required TCP connections, dropping from 100 to only 8. Nice. A Last Interesting Impact of OneConnect – Per S3 Transaction Load Balancing OneConnect is most well-known for its ability to constrain TCP sprawl in the backend of BIG-IP to origin server communications. However, there is another interesting byproduct. This is the fact that when a persistent TCP connection is used by a client to conduct serial transactions, such as S3 requests, the later requests will follow the same load balancing decision decided upon for the first request. This can be visually seen in the following BIG-IP screen after running a warp test with --connections set to only one, meaning all S3 GETs without an OneConnect profile attached at the virtual server will flow on a single TCP connection in the backed: sudo ./warp get --host 10.1.40.163:9000 --list-existing --access-key 0t7hrh3nxhJPzEgBSEY8 --secret-key dfksjBkS3Bf5qs0R6rqkzijPrvp9clrn7IXq9UYX --duration 1m --concurrent 1 The above is not necessarily negative behavior. It is simply a solution observation. In some cases, there are protocols that are served best by persisting one user's traffic to the same backend node. Also, this exercise is quite trivial, based upon a single S3 load source. In a real-world deployment, there might be hundreds or thousands of sources, which would serve to even out overall backend AIStor node utilization. However, in some cases, having the 4.3K requests in the previous image individually analyzed and load balanced in isolation makes sense. Take one example, a transaction may carry a cookie header, a cookie assigned previously by the load balancer and intended to persist just by traffic presenting that specific cookie to a specific node. The cookie can normally serve to override an individual load-balancing decision and deliver the transaction to a specific backend server. BIG-IP can fully support cookie persistence, it is described here. In such a case, how can one achieve per-request load-balancing decisions, even on persistent front-end connections with serialized requests? Yes, OneConnect can do this. Note the difference when the exact same warp load, over a single TCP connection, lands upon a virtual server, now using OneConnect. The per-transaction load balancing, independent of the incoming traffic being on a single TCP connection, becomes evident when OneConnect is enacted for the virtual server. For a deeper dive into the characteristics of OneConnect the following Knowledge Base article 7208 is provided. Summary Using a lab setup involving BIG-IP and MinIO AIStor S3 servers, the nuances of tying an OneConnect profile to S3 virtual servers were investigated. The ability to maintain large numbers of setup and primed TCP connections between bursts of traffic was demonstrated, largely using Minio Warp to drive S3 traffic. The optimal result was traffic, which was intermittent, perhaps minute by minute ebbs and flows. As default behavior noted is that AIStor will close idle TCP connections after five minutes. S3 client traffic that generally sets up many short TCP connections, thus driving up TCP load, was investigated. This was achieved by nested curl commands pulling public bucket contents from AIStor. The potential gain of OneConnect appears even higher in such S3 low-TCP persistence environments, as intermittent traffic can result in continual re-use of OneConnect back-end connection pools. In other words, the ratio of front-end TCP connection count to back-end TCP connection count is driven even higher, suggesting more value is attainable. A final interesting use case of OneConnect was observed with long persistent connections, carrying many S3 requests in a serialized manner. OneConnect allows for each carried transaction to be load-balanced by BIG-IP on an individual request-by-request basis. This might introduce additional load in terms of decision making on BIG-IP but still in some cases may be useful for deeper examination of items such as HTTP header cookies as opposed to making a single load-balancing choice for all carried requests.116Views2likes0CommentsOne Quick Step to Make your website AI-Agent/MCP Ready with an iRule
The Problem Nobody Warned You About Here’s the thing about the AI agent explosion: GPTBot, ClaudeBot, PerplexityBot, and a dozen other crawlers are hitting your web applications today. And they’re getting back the same bloated HTML that your browser gets, complete with navigation bars, cookie banners, SVG icons, inline JavaScript, and CSS that means absolutely nothing to an LLM, other than a hit to your token usage. These agents don’t need your <nav> with 47 links. They don’t need your cookie consent modal. They definitely don’t need 200+ lines of minified CSS & JS. They need the content. The headings, the paragraphs, the links, the data. If you, or anyone, are using an agent to access and utilize the data on the page, it’s burning through a massive amount of tokens, generally ~2k per GET. But what if your BIG-IP could intercept these requests, see that the client is an AI agent, and transform that HTML response into clean markdown before it ever leaves your network? BTW, there is plenty of room for improvement here, and a small disclaimer at the end! The Approach The iRule works in three phases across three HTTP events. Here’s the flow: Client Request => HTTP_REQUEST (detect agent, strip Accept-Encoding) Origin Response => HTTP_RESPONSE (check HTML, collect body) Body Received => HTTP_RESPONSE_DATA (convert HTML => Markdown, replace body) Client receives clean markdown with Content-Type: text/plain Detection: Who’s an AI Agent? This example is set up to detect agents three ways; because different agents announce themselves differently, and we want to give humans a way to trigger it too (mostly I used this for testing, notes on that later). when HTTP_REQUEST { set is_ai_agent 0 set ua [string tolower [HTTP::header "User-Agent"]] # The usual suspects if { $ua contains "gptbot" || $ua contains "chatgpt-user" || $ua contains "claudebot" || $ua contains "claude-web" || $ua contains "perplexitybot" || $ua contains "cohere-ai" || $ua contains "google-extended" || $ua contains "applebot-extended" || $ua contains "bytespider" || $ua contains "ccbot" || $ua contains "amazonbot" } { set is_ai_agent 1 } # Explicit opt-in via header if { [HTTP::header "X-Request-Format"] eq "markdown" } { set is_ai_agent 1 } # Content negotiation (the standards-correct way) if { [HTTP::header "Accept"] contains "text/markdown" } { set is_ai_agent 1 } Why three methods? User-Agent detection handles the common crawlers automatically. The X-Request-Format header lets any client explicitly request markdown. And Accept: text/markdown is proper HTTP content negotiation, the way it should work once the ecosystem matures. The Demo Path: /md/ Prefix I added one more trigger that’s purely for demos: set orig_uri [HTTP::uri] if { $orig_uri starts_with "/md/" } { set is_ai_agent 1 set new_uri [string range $orig_uri 3 end] if { $new_uri eq "" } { set new_uri "/" } HTTP::uri $new_uri } Visit /md/ in your browser and you get the markdown version of the upstream site. This is great for showing the capability to someone without having to modify your User-Agent string or install curl. Preventing Compressed Responses This one bit me during testing. And if you could believe it, Kunal Anand is the one who gave me a tip to actually find the resolution. If the origin returns gzip-compressed HTML, HTTP::payload gives you binary garbage. The fix: if { $is_ai_agent } { HTTP::header replace "Accept-Encoding" "identity" } We just need to strip the Accept-Encoding header on the request side so the origin sends us uncompressed HTML. And I added a safety net in HTTP_RESPONSE: when HTTP_RESPONSE { if { $is_ai_agent } { if { [HTTP::header "Content-Type"] contains "text/html" } { set ce [HTTP::header "Content-Encoding"] if { $ce ne "" } { if { $ce ne "identity" } { set is_ai_agent 0 HTTP::header insert "X-Markdown-Skipped" "compressed-response" return } } } } If the upstream ignores our Accept-Encoding override and sends gzip anyway, we bail gracefully instead of serving corrupted content. Defense in-depth! The Conversion: Where the Magic Happens This is HTTP_RESPONSE_DATA, the body has been collected and we have the raw HTML. Now we convert it to markdown through a series of regex passes. Phase 1: The Multiline Problem Tcl's . in regex doesn't match newlines. Every <script>, <style>, and <nav> block in real HTML spans multiple lines. So this won’t work: # This silently fails on multiline <script> blocks! regsub -all -nocase {<script[^>]*>.*?</script>} $html_body "" html_body The fix, again, another hint from Kunal: collapse all newlines to a sentinel character before stripping block elements, then restore them after: set NL_MARK "\x01" set html_body [string map [list "\r\n" $NL_MARK "\r" $NL_MARK "\n" $NL_MARK] $html_body] # NOW these work, everything is one "line" regsub -all -nocase "<script\[^>\]*>.*?</script>" $html_body "" html_body regsub -all -nocase "<style\[^>\]*>.*?</style>" $html_body "" html_body regsub -all -nocase "<nav\[^>\]*>.*?</nav>" $html_body "" html_body # ... strip footer, header, noscript, svg, comments, forms, cookie banners # Restore newlines set html_body [string map [list $NL_MARK "\n"] $html_body] This is the single biggest quality improvement. Without it, you get raw JavaScript and CSS bleeding into your markdown output. Phase 2: Converting Structure With the junk stripped and newlines restored, we convert HTML elements to markdown syntax. Here’s the key insight that took a few iterations: Use [^<]* instead of .*? for tag content. # BAD: .*? crosses newlines in Tcl and matches across multiple tags regsub -all -nocase {<a[^>]*href="(/[^"]*)"[^>]*>(.*?)</a>} ... # GOOD: [^<]* stops at the next tag boundary regsub -all -nocase {<a[^>]*href="(/[^"]*)"[^>]*>([^<]*)</a>} ... This matters when you have two <a> tags on adjacent lines. The .*? version matches from the first <a> opening all the way to the second </a> closing, one giant broken link. The [^<]* version correctly matches each link individually. Here’s the conversion order (it matters): # 1. Headings regsub -all -nocase {<h2[^>]*>([^<]*)</h2>} $html_body "\n## \\1\n\n" html_body # 2. Emphasis BEFORE links (so **bold** inside links works) regsub -all -nocase {<strong[^>]*>([^<]*)</strong>} $html_body {**\1**} html_body # 3. Links with relative URL resolution regsub -all -nocase {<a[^>]*href="(/[^"]*)"[^>]*>([^<]*)</a>} \ $html_body "\[\\2\](https://${http_request_host}\\1)" html_body # 4. Tables, code, lists, paragraphs, blockquotes, images... # 5. Strip ALL remaining tags regsub -all {<[^>]+>} $html_body "" html_body # 6. Decode HTML entities regsub -all {“} $html_body {"} html_body regsub -all {’} $html_body {'} html_body # ... 20+ entity decodings Emphasis before links is important. If you have <a href="/pricing"><strong>$149,900</strong></a>, converting emphasis first gives you <a href="/pricing">$149,900</a>, which then converts to [$149,900](/pricing). Do it the other way, and the bold markers end up orphaned. URL Resolution AI agents need absolute URLs. A relative link like /properties is useless to a bot that doesn’t know what host it’s talking to. We capture $http_request_host in HTTP_REQUEST and use it during link conversion: # Relative to absolute regsub -all -nocase {<a[^>]*href="(/[^"]*)"[^>]*>([^<]*)</a>} \ $html_body "\[\\2\](https://${http_request_host}\\1)" html_body # Absolute stays absolute regsub -all -nocase {<a[^>]*href="(https?://[^"]*)"[^>]*>([^<]*)</a>} \ $html_body "\[\\2\](\\1)" html_body Same treatment for images. Dynamic Table Separators (Yet another place Kunal offered some tips) This one is kind of tricky to solve, because of common HTML table structure standards. Markdown tables need a separator row between the header and body: | Name | Price | Status | |------|-------|--------| | Unit A | $500k | Available | The separator needs the right number of columns. We count <th> tags in the <thead> and build it dynamically (but what if there is no thead? I try to account for that, too): set col_count 0 set thead_check $html_body if { [regsub -nocase {<thead[^>]*>(.*?)</thead>} $thead_check "\\1" first_thead] } { set col_count [regsub -all -nocase {<th[^>]*>} $first_thead "" _discard] } if { $col_count > 0 } { set sep "\n|" for { set c 0 } { $c < $col_count } { incr c } { append sep "---|" } append sep "\n" } If we can’t count the columns in thead, then we default to 6 columns, which could still use some work. But we end up without a hardcoded 2-column separator, breaking our 5-column tables. Performance Considerations This iRule runs in TMM. Every CPU cycle it uses is a cycle not processing other connections. So I built in several guardrails (could be better still): Size limit: Pages over 512KB skip conversion entirely. The regex chain gets expensive on large documents and the output quality degrades anyway. if { $content_length > 524288 } { set is_ai_agent 0 HTTP::header insert "X-Markdown-Skipped" "body-too-large" } Targeted Accept-Encoding: By stripping Accept-Encoding only for AI agent requests, normal browser traffic still gets compressed responses. No performance impact on human users. Logging: Every conversion logs the byte reduction to /var/log/ltm so you can monitor the overhead: markdown: converted 15526 bytes -> 4200 bytes (73% reduction) What This Doesn’t Do (And I Think That’s OK) I will be honest about the limitations: No DOM parsing. This is regex-based conversion. Complex nested structures (a <strong> that wraps three <div>s) won't convert perfectly. You need a real DOM parser for that, and iRules doesn't have one. I avoided using iRulesLX for this project entirely. Multiline tags within content blocks. The newline collapse trick handles <script> and <style>, but a <p> tag with inline markup that spans lines will partially match. The [^<]* pattern helps, but it can't capture text that contains child tags. Tables without <thead>. It detects column count from <th> tags. Tables that use plain <tr><td> with no header get a fallback separator. For 80% of web pages, the output is surprisingly good. For the other 20%, consider iRulesLX (Node.js sidecar with a real DOM parser) or a sideband approach with compiled-language HTML parsing. The Complete iRule Here it is, attach it to your virtual server and you're done: when HTTP_REQUEST { set is_ai_agent 0 set ua [string tolower [HTTP::header "User-Agent"]] if { $ua contains "gptbot" || $ua contains "chatgpt-user" || $ua contains "claudebot" || $ua contains "claude-web" || $ua contains "perplexitybot" || $ua contains "cohere-ai" || $ua contains "google-extended" || $ua contains "applebot-extended" || $ua contains "bytespider" || $ua contains "ccbot" || $ua contains "amazonbot" } { set is_ai_agent 1 } if { [HTTP::header "X-Request-Format"] eq "markdown" } { set is_ai_agent 1 } if { [HTTP::header "Accept"] contains "text/markdown" } { set is_ai_agent 1 } set orig_uri [HTTP::uri] if { $orig_uri starts_with "/md/" } { set is_ai_agent 1 set new_uri [string range $orig_uri 3 end] if { $new_uri eq "" } { set new_uri "/" } HTTP::uri $new_uri } elseif { $orig_uri eq "/md" } { set is_ai_agent 1 HTTP::uri "/" } set http_request_host [HTTP::host] if { $is_ai_agent } { HTTP::header replace "Accept-Encoding" "identity" } } when HTTP_RESPONSE { if { $is_ai_agent } { if { [HTTP::header "Content-Type"] contains "text/html" } { set ce [HTTP::header "Content-Encoding"] if { $ce ne "" } { if { $ce ne "identity" } { set is_ai_agent 0 HTTP::header insert "X-Markdown-Skipped" "compressed-response" return } } set content_length [HTTP::header "Content-Length"] set do_collect 1 if { $content_length ne "" } { if { $content_length > 524288 } { set is_ai_agent 0 set do_collect 0 HTTP::header insert "X-Markdown-Skipped" "body-too-large" } } if { $do_collect } { if { $content_length ne "" } { if { $content_length > 0 } { HTTP::collect $content_length } } else { HTTP::collect 524288 } } } } } when HTTP_RESPONSE_DATA { if { $is_ai_agent } { set html_body [HTTP::payload] set orig_size [string length $html_body] # Phase 1: Collapse newlines for multiline tag stripping set NL_MARK "\x01" set html_body [string map [list "\r\n" $NL_MARK "\r" $NL_MARK "\n" $NL_MARK] $html_body] regsub -all -nocase "<script\[^>\]*>.*?</script>" $html_body "" html_body regsub -all -nocase "<style\[^>\]*>.*?</style>" $html_body "" html_body regsub -all -nocase "<nav\[^>\]*>.*?</nav>" $html_body "" html_body regsub -all -nocase "<footer\[^>\]*>.*?</footer>" $html_body "" html_body regsub -all -nocase "<header\[^>\]*>.*?</header>" $html_body "" html_body regsub -all -nocase "<noscript\[^>\]*>.*?</noscript>" $html_body "" html_body regsub -all -nocase "<svg\[^>\]*>.*?</svg>" $html_body "" html_body regsub -all "<!--.*?-->" $html_body "" html_body regsub -all -nocase "<form\[^>\]*>.*?</form>" $html_body "" html_body # Phase 2: Restore newlines, convert structure set html_body [string map [list $NL_MARK "\n"] $html_body] regsub -all -nocase {<h1[^>]*>([^<]*)</h1>} $html_body "# \\1\n\n" html_body regsub -all -nocase {<h2[^>]*>([^<]*)</h2>} $html_body "\n## \\1\n\n" html_body regsub -all -nocase {<h3[^>]*>([^<]*)</h3>} $html_body "\n### \\1\n\n" html_body regsub -all -nocase {<h4[^>]*>([^<]*)</h4>} $html_body "\n#### \\1\n\n" html_body regsub -all -nocase {<strong[^>]*>([^<]*)</strong>} $html_body {**\1**} html_body regsub -all -nocase {<b[^>]*>([^<]*)</b>} $html_body {**\1**} html_body regsub -all -nocase {<em>([^<]*)</em>} $html_body {*\1*} html_body regsub -all -nocase {<i>([^<]*)</i>} $html_body {*\1*} html_body regsub -all -nocase {<a[^>]*href="(/[^"]*)"[^>]*>([^<]*)</a>} $html_body "\[\\2\](https://${http_request_host}\\1)" html_body regsub -all -nocase {<a[^>]*href="(https?://[^"]*)"[^>]*>([^<]*)</a>} $html_body "\[\\2\](\\1)" html_body regsub -all -nocase {<a[^>]*>([^<]*)</a>} $html_body {\\1} html_body regsub -all -nocase {<th[^>]*>([^<]*)</th>} $html_body "| \\1 " html_body regsub -all -nocase {<td[^>]*>([^<]*)</td>} $html_body "| \\1 " html_body regsub -all -nocase {</tr>} $html_body "|\n" html_body regsub -all -nocase {<code>([^<]*)</code>} $html_body {`\1`} html_body regsub -all -nocase {<li[^>]*>([^<]*)</li>} $html_body "- \\1\n" html_body regsub -all -nocase {</?[uo]l[^>]*>} $html_body "\n" html_body regsub -all -nocase {<p[^>]*>([^<]*)</p>} $html_body "\\1\n\n" html_body regsub -all -nocase {<br\s*/?>} $html_body "\n" html_body regsub -all -nocase {<hr\s*/?>} $html_body "\n---\n\n" html_body regsub -all -nocase {<blockquote[^>]*>} $html_body "> " html_body regsub -all -nocase {</blockquote>} $html_body "\n\n" html_body regsub -all -nocase {<cite>([^<]*)</cite>} $html_body "-- *\\1*\n" html_body regsub -all {<[^>]+>} $html_body "" html_body regsub -all {&} $html_body {\&} html_body regsub -all {<} $html_body {<} html_body regsub -all {>} $html_body {>} html_body regsub -all {"} $html_body {"} html_body regsub -all { } $html_body { } html_body regsub -all {“} $html_body {"} html_body regsub -all {”} $html_body {"} html_body regsub -all {‘} $html_body {'} html_body regsub -all {’} $html_body {'} html_body regsub -all {—} $html_body {--} html_body regsub -all {–} $html_body {-} html_body regsub -all {…} $html_body {...} html_body regsub -all {&#[0-9]+;} $html_body {} html_body regsub -all {\n +} $html_body "\n" html_body regsub -all {\n{3,}} $html_body "\n\n" html_body regsub -all {([^\n])\n\n([^#\n\[>*-])} $html_body "\\1\n\\2" html_body set html_body [string trim $html_body] HTTP::payload replace 0 [HTTP::payload length] $html_body HTTP::header replace "Content-Type" "text/plain; charset=utf-8" HTTP::header replace "Content-Length" [string length $html_body] HTTP::header insert "X-Markdown-Source" "bigip-irule" } } Testing / Demoing It # Normal browser request, HTML as usual curl https://your-site.example.com/ # AI agent simulation curl -H "User-Agent: GPTBot/1.0" https://your-site.example.com/ # Explicit markdown request curl -H "X-Request-Format: markdown" https://your-site.example.com/ # Browser-friendly demo curl https://your-site.example.com/md/ # (or just visit it in your browser) What's Next This is a solid starting point for making your existing sites AI-agent ready without touching application code. A few directions to take it: Agent discovery files: serve /llms.txt and /.well-known/ai-plugin.json so agents can programmatically discover your markdown capability iRulesLX upgrade path: When regex-based conversion isn't enough, move the HTML parsing to a Node.js sidecar with a real DOM parser (cheerio, jsdom). Same detection logic, better conversion quality. The AI agent wave isn't coming. It’s here. Your BIG-IP already sees every request. Might as well make those responses useful. Disclaimer! The iRule in this article was developed as part of a proof-of-concept for edge-layer HTML-to-Markdown conversion. It's been tested on BIG-IP 17.5.1+. Your mileage may vary on complex single-page applications, but for content-heavy sites, it works remarkably well for something that's "just regex."342Views9likes3CommentsIPv8 Would Fix My Routing Tables. It Will Never Ship.
Anyone who worked on a service provider backbone in the late 90s or early 2000s remembers the squeeze. Cisco 7500s and early GSRs came with RAM budgets that looked generous at install and felt terrifying three years later, and the global BGP table kept growing faster than the hardware refresh cycle. Providers started summarizing aggressively, pushing back on customers who wanted to advertise /24s for traffic engineering, and progressively raising the minimum prefix length they’d accept at the edge. It was a real problem on both sides of every BGP session, and the fix was always the same conversation: “we’d love to carry all your cute disparate /25 CIDR blocks, but my RIBs are a little sore.” Twenty-five years later, the table is pushing toward a million prefixes. The hardware got bigger, and we quietly learned to live with a routing system whose growth has no architectural ceiling. So when I read this IPv8 draft and got to the part where the /16 minimum injectable prefix rule effectively caps the global table on the order of one entry per originating ASN, dropping us from ~900K prefixes to something closer to ~150–200K in steady state, I performed Balki’s dance of joy in my head (look it up, youngins!) and was ready to sign up on the spot. A bounded global routing table, WHOIS8 validation that meaningfully raises the bar on prefix hijacking, and a Cost Factor metric that actually accumulates end-to-end across AS boundaries instead of stopping at the edge. That’s three things the younger me wanted twenty years ago, bundled into one draft. Of note: this is an individual -00 Internet-Draft with no working-group adoption or visible industry backing yet. Plenty of RFCs started this way, but it's a design document at this stage, not a standards-track specification. But it’s not all puppies and rainbows. And the reason why gets to something more important: IPv6 didn’t struggle because it solved the wrong problem. It struggled because it solved only one problem in a system where operators needed several to be solved concurrently. Before I dig into why that matters for IPv8, let’s take a step back and consider the history of IP in general, because the reasons a proposal like this is hard to ship are the same reasons IPv6 is still stuck at half the internet three decades in. IPv4 has been carrying the internet since 1981, and its 32-bit address space, roughly 4.3 billion addresses, was declared exhausted at the IANA level in 2011. IPv6 was ratified as the official successor back in 1998 with a 128-bit address space, and despite nearly three decades of standards work, deployment campaigns, and World IPv6 Day t-shirts (who doesn’t love a good #nerd shirt?), it still carries a minority of overall traffic, even if the telecom percentage is now more than half. That’s the backdrop against which IPv8 is proposed. IPv8 is a proposed 64-bit successor to IPv4 that pairs an expanded address space with a unified management architecture. Addresses take the form r.r.r.r.n.n.n.n, where the first 32 bits encode an ASN and the last 32 are an IPv4-semantic host address. When r.r.r.r = 0.0.0.0, the address is IPv4, which the draft leans on to argue IPv4 is a proper subset of IPv8 and no flag day or dual-stack phase is needed. Beyond addressing, the draft specifies a “Zone Server” that collapses DHCP, DNS, NTP, OAuth2 auth, telemetry, route validation, ACLs, and IPv4↔IPv8 translation onto one platform. It also introduces an end-to-end Cost Factor routing metric, the /16 minimum prefix rule mentioned above, and mandatory egress validation that drops any packet without a matching DNS lookup and WHOIS8-registered route. How IPv8 Differs From IPv6 IPv6 was scoped narrowly: solve address exhaustion. It went to 128 bits, modernized some header mechanics, and left DHCP, DNS, auth, telemetry, and routing security to evolve on their own, which, thirty years later, they mostly still haven’t in any coordinated way. Transition assumed dual-stack everywhere until IPv4 could eventually be retired. Eventually is doing some heavy lifting in that sentence. IPv8's authors argue exhaustion is only one of three structural IPv4 failures, the others being management, fragmentation and unbounded, unvalidated BGP, and try to solve all three at once while rejecting dual-stack outright. Addressing, routing, identity, policy, and telemetry are treated as one system. That’s either exactly what the industry needed, or exactly why it won’t ship. Why IPv6 Adoption Stalled We’ll get into the reasons below, but it’s worth looking at where things actually stand. The headline numbers people quote for IPv6 come from Google, APNIC, and Cloudflare, all of which measure eyeball-to-content traffic, users reaching public services. Here’s how that breaks down by country as of early 2026 (Is that FRANCE leading the way?!?): Dual-stack did most of the damage. Running both protocols in parallel roughly doubled the config, monitoring, firewall, and troubleshooting surface area with nothing new to show for it operationally. Cost was immediate; benefit was deferred to a day that kept sliding to the right. Every network engineer who has debugged a dual-stack MTU issue at 2am has opinions about this. Carrier-grade NAT finished the job. Once ISPs could stretch IPv4 with CGNAT, the exhaustion crisis stopped being acute and quietly became someone else’s problem, specifically the problem of whoever was trying to run a peer-to-peer protocol through three layers of translation. Add a non-backward-compatible header and 128-bit colon-hex notation that fights operator muscle memory, and the business case never really came together. We’ve spent three decades turning the “IPv6 is coming” war cry into the networking equivalent of fusion power. The Enterprise Internal-Network Blind Spot The country-level numbers above tell you what mobile carriers and residential ISPs have shipped. They don’t tell you anything about the LAN side of the corporate firewall, which is a completely different story. Internal enterprise IPv6 adoption is sitting somewhere between 20% and 30% and has barely moved in a decade, a gap the headline statistics quietly gloss over. A few data points worth knowing: RFC 9386 (IPv6 Deployment Status), the closest thing to an official IETF status report, surveyed European service providers in 2020 and found the enterprise segment lagging mobile and fixed broadband even when measured from the provider’s perspective. Internal deployment numbers were mostly not collected because they were understood to be negligible. HexaBuild's IPv6 Adoption Reports from 2018 and 2020 explicitly call out that “many commercial enterprises still lack IPv6 connectivity at their Internet perimeters and don’t have any IPv6 network connectivity in their internal networks.” Follow-on coverage hasn’t meaningfully changed that framing. OMB Memorandum M-21-07 required US federal agencies to hit 80% IPv6-only on internal assets by September 30, 2025. As of October 2025, no federal agency has publicly announced reaching that threshold. This is a mandate with five years of runway, presidential-memo weight, and FAR procurement backing, and it still missed its own deadline across essentially every agency. The reasons internal adoption is stuck are painfully mundane, and every network engineer reading this will recognize them: RFC 1918 solved the address problem thirty years ago. 10.0.0.0/8 gives you 16 million addresses. Unless you’re a hyperscaler or you’ve acquired your way into overlapping subnet hell, that’s functionally infinite. It’s hard to sell a renumbering project to a CFO when the existing scheme has never once failed to have enough addresses. Every piece of tooling assumes IPv4. Firewalls, load balancers, IPAM, NetFlow collectors, ACL generators, SIEM parsers, monitoring dashboards, runbooks, change management templates, and the regex in that one critical Perl script from 2008, all of it was written for dotted-quad. Dual-stack means maintaining two of everything with no operational payoff. Troubleshooting costs roughly double that. Anyone who has tried to correlate a dual-stack flow across a load balancer, a WAF, and three microservices knows exactly why executives didn’t approve the project. The failure modes aren’t symmetric. An IPv6-only path can break in ways that leave the IPv4 path working, which means “it works on my machine” becomes “it works on my protocol family.” Security teams often see IPv6 as a new attack surface rather than a modernized infrastructure. Auto-configuration and neighbor discovery behave differently enough from ARP that existing segmentation, spoofing, and rogue-device playbooks need to be rewritten. For a team already underwater on IPv4 incidents, opting into a second set of attack patterns is a hard sell. There’s no customer-visible benefit. The user doesn’t care what protocol their apps run on internally. The CIO/CISO might (ok, for sure) have an opinion, but the CFO definitely doesn’t. This is actually a stronger argument for the IPv8 approach than the draft itself makes. The reason IPv6 bounced off the enterprise LAN is that it offered zero operational improvement over what RFC 1918 and NAT were already providing. IPv8’s pitch, that IPv4 is a proper subset, that internal networks keep their existing addressing, and that the management story is the value proposition rather than the address space, is at least aimed at the right problem. Pros & Cons No proposal this ambitious gets everything right or everything wrong, and IPv8 is no exception. A few things it nails, a few things it doesn’t, and one quiet standout worth calling out even if the rest of the draft never ships. Pros Backward compatibility is the one thing this gets right that IPv6 got wrong. Encoding IPv4 as IPv8 with a zero ASN prefix means existing applications, RFC 1918 networks, and CGNAT deployments don’t need to change to keep working. If that claim holds up in implementation, it sidesteps the single biggest political failure of the IPv6 transition, the one where you had to convince every stakeholder in the chain to move at the same time for anyone to benefit. The management-fragmentation critique is strong, and the answer makes a lot of sense. Networking from disparate angles doesn’t exactly evoke a thoughtful design pattern, but feels more like a whack-a-mole approach. DHCP, DNS, syslog, SNMP, and auth really were specified independently over four decades with no shared identity or telemetry model, and anyone who’s ever tried to correlate an incident across them knows the pain. A Zone Server with OAuth2/JWT as the common substrate is a reasonable swing at it, and it’s refreshing to see a proposal treat operations as a first-class concern instead of an exercise left to the reader. Cost Factor is the routing metric OSPF and EIGRP always wanted to be. CF accumulates seven signals: RTT, loss, congestion window state, session stability, link capacity, economic policy, and great-circle distance as a physics floor, end-to-end across AS boundaries, which is exactly where OSPF and EIGRP stop being useful. The geographic component is the clever bit: no path can measure faster than the speed of light over the great circle distance allows, so a path that appears better than physics permits is flagged as an anomaly instead of silently poisoning route selection. That’s a better hijack detector than most of what we have today, and it falls out of the metric for free. Honorable mention: bounded routing table. Already covered in the intro, but worth restating that the /16 minimum-prefix rule plus mandatory WHOIS8 validation is the structural fix for both unbounded RIB growth and prefix hijacking. If any single piece of this draft gets adopted à la carte, this is the one I’d bet on. Cons “No dual stack" understates the deployment reality. IPv4 packets transit an IPv8 router fine, but anything that actually uses the ASN prefix (new header fields, A8 records, AF_INET8 sockets, 8to4 tunneling, WHOIS8 egress validation) requires updated stacks, resolvers, middleboxes, firewalls, and applications. Backward-compatible is not the same as zero deployment cost, and the draft blurs the two in a way that will feel familiar to anyone who remembers the original “IPv6 is a drop-in replacement" sales pitch. The Zone Server is a massive trust and failure domain. This is the part that should make operators nervous. We've spent the last twenty years decomposing monoliths, breaking apart control planes, distributing systems, and reducing blast radius. The Zone Server pulls DHCP, DNS, auth, telemetry, validation, and policy back into a single logical system. Even with active/active HA, it’s a high-value target, it expands the trust boundary significantly, and a bad day becomes a very bad day. We’ve seen this pattern before in other control-plane centralizations. It works great…until it doesn’t. The scope is probably fatal to adoption. Ten companion drafts covering a new IP version, five routing protocols, a new exchange-point architecture, a zone-server platform, support protocols, a MIB, WiFi8, and mandatory NIC certification with hardware-enforced rate limits is the opposite of how the IETF actually ships things. The institutional motto is “rough consensus and running code”, not “ten coordinated drafts and a reference architecture.” I love the crazy ambition, but narrow, incrementally deployable specs get adopted. Monolithic suites rarely do, just ask OSI. The Real Roadblock: Incentives IPv8 won’t fail because it’s too ambitious. It will fail because no one with budget authority is experiencing enough pain to justify replacing the system. For it to succeed, the RIRs would need to stand up WHOIS8 as a high-availability egress-gating service, and RPKI, a much narrower version of the same idea, is still partially deployed fifteen years in (don’t get Chase started). At least one major vendor (Cisco, Juniper, Arista, Nokia, or the merchant-silicon ecosystem) would need to publicly commit to shipping IPv8 forwarding, certified NIC firmware, and Zone Server reference code, while somehow reconciling the “just a software update” framing with the mandatory NIC certification and hardware rollback prevention the draft also requires. And the hyperscalers, who have already solved VPC overlap and multi-cloud routing on their own terms, would need a reason to adopt a standard that constrains their existing architecture. Meanwhile, CGNAT works well enough. Hyperscalers have already built their own solutions. And operational pain sits with engineers, not executives, which is the same incentive gap that killed IPv6 momentum. The draft answer, that Cost Factor will naturally incentivize IPv4 transit ASNs to upgrade because 8to4 paths measure slower, is clever but requires enough IPv8 traffic to exist for the signal to register, which is the same chicken-and-egg problem IPv6 has been losing for thirty years. There’s a faint echo here of other efforts like segment routing and SD-WAN where pieces of this vision are already being adopted, just not as a single unified system. That’s probably the shape of whatever actually ships. Bottom Line The diagnosis is on point. Management fragmentation, unbounded BGP, unauthenticated routing, and CGNAT's drag on peer-to-peer protocols are real problems that IPv6 didn’t address and that the industry has mostly absorbed as permanent friction in their engineering and operational playbooks. IPv6 addresses one of them. IPv8 tries to address all of them at once, and that’s both its strength and the reason it probably won’t ship. If anything from this proposal survives, it will likely be the smaller pieces (stronger route validation, better routing metrics, more cohesive management models) adopted incrementally rather than as a full replacement. Which is a bit of a shame, because a bounded routing table alone would have solved one of the hardest conversations of my early career. IPv8 is what the internet might look like if it were designed today. Unfortunately, the internet we have is the one that has to adopt it. What do you think? Come at me and my IPv8 hot takes!672Views2likes0CommentsVMware VKS integration with F5 BIG-IP and CIS
Introduction vSphere Kubernetes Service (VKS) is the Kubernetes runtime built directly into VMware Cloud Foundation (VCF). With CNCF certified Kubernetes, VKS enables platform engineers to deploy and manage Kubernetes clusters while leveraging a comprehensive set of cloud services in VCF. Cloud admins benefit from the support for N-2 Kubernetes versions, enterprise-grade security, and simplified lifecycle management for modern apps adoption. Alike with other Kubernetes platforms, the integration with BIG-IP is done through the use of the Container Ingress Services (CIS) component, which is hosted in the Kubernetes platform and allows to configure the BIG-IP using the Kubernetes API. Under the hood, it uses the F5 AS3 declarative API. Note from the picture that BIG-IP integration with VKS is not limited to BIG-IP´s load balancing capabilities and that most BIG-IP features can be configured using this integration. These features include: Advanced TLS encryption, including safe key storage with Hardware Security Module (HSM) or Network & Cloud HSM support. Advanced WAF, L7 bot and API protection. L3-L4 High-performance firewall with IPS for protocol conformance. Behavioral DDoS protection with cloud scrubbing support. Visibility into TLS traffic for inspection with 3 rd party solutions. Identity-aware ingress with Federated SSO and integration with leading MFAs. AI inference and agentic support thanks to JSON and MCP protocol support. Planning the deployment of CIS for VMware VKS The installation of CIS in VMware VKS is performed through the standard Helm charts facility. The platform owner needs to determine beforehand: Whether the deployment is hosted on a vSphere (VDS) network or an NSX network. It has to be taken into account that on an NSX network, VKS doesn´t currently allow to place the load balancers in the same segment as the VKS cluster. No special considerations have to be taken when hosting BIG-IP in a vSphere (VDS) network. Whether this is a single-cluster or a multi-cluster deployment. When using the multi-cluster option and clusterIP mode (only possible with Calico in VKS), it has to be taken into account that the POD networks of the clusters cannot have overlapping prefixes. What Kubernetes networking (CNI) is desired to be used. CIS supports both VKS supported CNIs: Antrea (default) and Calico. From the CIS point of view, the CNI is only relevant when sending traffic directly to the PODs. See next. What integration with the CNI is desired between the BIG-IP and VKS NodePort mode This is done by making applications discoverable using Services of type NodePort. From the BIG-IP, the traffic is sent to the Node´s IPs where it is redistributed to the POD depending on the TrafficPolicies of the Service. This is CNI agnostic. Any CNI can be used. Direct-to-POD mode This is done by making applications discoverable using the Services of type ClusterIP. Note that the CIS integration with Antrea uses Antrea´s nodePortLocal mechanism, which requires an additional annotation in the Service declaration. See the CIS VKS page in F5 CloudDocs for details. This Antrea nodePortLocal mechanism allows to send the traffic directly to the POD without actually using the POD IP address. This is especially relevant for NSX because it allows to access the PODs without actually re-distributing the PODs IPs across the NSX network, which is not allowed. When using vSphere (VDS) networking, either Antrea’s nodePortLocal or clusterIP with Calico can be used. Another way (but not frequent) is the use of hostNetwork POD networking because it requires privileges for the application PODs or ingress controllers. Network-wise, this would have a similar behavior to nodePortLocal, but without the automatic allocation of ports. Whether the deployment is a single-tier or a two-tier deployment. A single-tier deployment is a deployment where the BIG-IP sends the traffic directly to the application PODs. This has a simpler traffic flow and easier persistence and end-to-end monitoring. A two-tier deployment sends the traffic to an ingress controller POD instead of the application PODs. This ingress controller could be Contour, NGINX Gateway Fabric, Istio or an API gateway. This type of deployment offers the ultimate scalability and provides additional segregation between the BIG-IPs (typically owned by NetOps) and the Kubernetes cluster (typically owned by DevOps). Once CIS is deployed, applications can be published either using the Kubernetes standard Ingress resource or F5’s Custom Resources. This latter is the recommended way because it allows to expose most of the BIG-IPs capabilities. Details on the Ingress resource and F5 custom annotations can be found here. Details on the F5 CRDs can be found here. Please note that at time of this writing Antrea nodePortLocal doesn´t support the TransportServer CRD. Please consult your F5 representative for its availability. Detailed instructions on how to deploy CIS for VKS can be found on this CIS VKS page in F5 CloudDocs. Application-aware MultiCluster support MultiCluster allows to expose applications that are hosted in multiple VKS clusters and publish them in a single VIP. BIG-IP & CIS are in charge of: Discover where the PODs of the applications are hosted. Note that a given application doesn´t need to be available in all clusters. Upon receiving the request for a given application, decide to which cluster and Node/Pod the request has to be sent. This decision is based on the weight of each cluster, the application availability and the load balancing algorithm being applied. Single-tier or Two-tier architectures are possible. NodePort and ClusterIP modes are possible as well. Note that at the time of this writing, Antrea in ClusterIP mode (nodePortLocal) is not supported currently. Please consult your F5 representative for availability of this feature. Considerations for NSX Load Balancers cannot be placed in the same VPC segment where the VMware VKS cluster is. These can be placed in a separate VPC segment of the same VPC gateway as shown in the next diagram. In this arrangement the BIG-IP can be configured as either 1NIC mode or as a regular deployment, in which case the MGMT interface is typically configured through an infrastructure VLAN instead of an NSX segment. The data segment is only required to have enough prefixes to host the self-IPs of the BIG-IP units. The prefixes of the VIPs might not belong to the Data Segment´s subnet. These additional prefixes have to be configured as static routes in the VPC Gateway and Route Redistribution for these must be enabled. Given that the Load Balancers are not in line with the traffic flow towards the VKS Cluster, it is required to use SNAT. When using SNAT pools, the prefixes of these can optionally be configured as additional prefixes of the Data Segment, like the VIPs. Specifically for Calico, clusterIP mode cannot be used in NSX because this would require the BIG-IP to be in the same VPC segment as VMware VKS. Note also that BGP multi-hop is not feasible either because it would require the POD cluster network prefixes to be redistributed through NSX, which is not possible either. Conclusion and final remarks F5 BIG-IPs provides unmatched deployment options and features for VMware VKS; these include: Support for all VKS CNIs, which allows sending the traffic directly instead of using hostNetwork (which implies a security risk) or using the common NodePort, which can incur an additional kube-proxy indirection. Both 1-tier or 2-tier arrangements (or both types simultaneously) are possible. F5´s Container Ingress Services provides the ability to handle multiple VMware VKS clusters with application-aware VIPs. This is a unique feature in the industry. Securing applications with the wide range of L3 to L7 security features provided by BIG-IP, including Advanced WAF and Application Access. To complete the circle, this integration also provides IP address management (IPAM) which provides great flexibility to DevOps teams. All these are available regardless of the form factor of the BIG-IP: Virtual Edition, appliance or chassis, allowing great scalability and multi-tenancy options. In NSX deployments, the recommended form-factor is Virtual Edition in order to connect to the NSX segments. We look forward to hearing your experience and feedback on this article.866Views1like1CommentHands-On Quantum-Safe PKI: A Practical Post-Quantum Cryptography Implementation Guide
Update (April 2026): The CNSA 2.0 section of this article originally listed both ML-DSA-65/87 and ML-KEM-768/1024 as approved. That's incorrect — CNSA 2.0 requires ML-DSA-87 and ML-KEM-1024 exclusively per draft-jenkins-cnsa2-pkix-profile §4. FIPS 204/203 standardize additional parameter sets but CNSA 2.0 only adopts Category 5. Is your Public Key Infrastructure quantum-ready? Remember way back when we built the PQC CNSA 2.0 Implementation guide in October 2025? So long ago! Due to popular request, we've expanded the lab to now include THREE distinct learning paths: NIST FIPS standards, NSA CNSA 2.0 compliance, AND alternative post-quantum algorithms for those wanting diversity or international compliance options.. The GitHub lab guide walks you through building quantum-resistant certificate authorities using OpenSSL with hands-on exercises. Why learn and implement post-quantum cryptography (PQC) now? While quantum computing is a fascinating area of science, all technological advancements can be misused. Nefarious people and nation-states are extracting encrypted data to decrypt at a later date when quantum computers become available, a practice you better know by now called "harvest now, decrypt later." Close your post-quantum cryptographic knowledge gap so you can get secured sooner and reduce the impact(s) that may not surface until after it's too late. Ignorance is not bliss when it comes to cryptography and regulatory fines, so let's get started. The GitHub lab provides step-by-step instructions to create: Quantum-resistant Root CA using ML-DSA-87 (FIPS and CNSA 2.0) Algorithm flexibility based on your compliance needs Quantum-safe server and client certificates OCSP and CRL revocation for quantum-resistant certificates TLS 1.3 key exchange testing with ML-KEM and hybrid modes Alternative algorithm exploration (FrodoKEM, BIKE, HQC) for TLS/KEM usage Access the Complete Lab Guide on GitHub → At A Glance: OpenSSL Quantum-Resistant CA Learning Paths Select the path that aligns with your requirements: FIPS 203/204/205 CNSA 2.0 Alt. Algorithms Target Audience Commercial organizations Government contractors, classified systems Researchers, international compliance, defense-in-depth Compliance Standard NIST FIPS standards NSA CNSA 2.0 Non-NIST algorithms, international standards Algorithm Coverage ML-DSA, ML-KEM, SLH-DSA, Hybrid ML-DSA-87, ML-KEM-/1024 FrodoKEM, BIKE, HQC Use Case General quantum-resistant infrastructure National security systems Algorithm diversity, conservative security 📚 Learning Path 1: NIST FIPS 203/204/205 For commercial organizations implementing quantum-resistant cryptography using NIST standards. This path uses OpenSSL 3.5.x's native post-quantum cryptography support—no external quantum library providers required. So nice, so easy. Modules Module Description 00 - Introduction Overview of FIPS 203/204/205, prerequisites, and lab objectives 01 - Environment Setup Verifying OpenSSL with PQC support 02 - Root CA Building a Root CA with ML-DSA-87 03 - Intermediate CA Creating an Intermediate CA with ML-DSA-65 04 - Certificates Issuing end-entity certificates for servers and users 05 - Revocation Implementing OCSP and CRL certificate revocation 06 - Hybrid Methods IETF hybrid PQC methods (X25519MLKEM768, composite signatures) Algorithms Covered ML-DSA-44/65/87 (FIPS 204) - Lattice-based signatures ML-KEM-512/768/1024 (FIPS 203) - Lattice-based key encapsulation X25519MLKEM768 - Hybrid TLS 1.3 key exchange 📚 Learning Path 2: NSA CNSA 2.0 For government contractors and organizations requiring CNSA 2.0 compliance. This path uses OpenSSL 3.2+ with Open Quantum Safe (OQS) providers for strict CNSA 2.0 algorithm compliance. Modules Module Description 01 - Introduction Overview of CNSA 2.0 requirements and compliance deadlines 02 - Root CA Building a Root CA with ML-DSA-87 03 - Intermediate CA Creating an Intermediate CA with ML-DSA-87 04 - Certificates Issuing CNSA 2.0 compliant certificates 05 - Revocation Implementing OCSP and CRL certificate revocation CNSA 2.0 Approved Algorithms Algorithm Type Approved Algorithms NIST Designation Digital Signatures ML-DSA-87 FIPS 204 Key Establishment ML-KEM-1024 FIPS 203 Hash Functions SHA-384, SHA-512 FIPS 180-4 Note: CNSA 2.0 requires ML-DSA-87 and ML-KEM-1024 exclusively — no other parameter sets are approved. ML-DSA-44, ML-DSA-65, ML-KEM-512, ML-KEM-768, SLH-DSA, and Falcon are NOT part of CNSA 2.0, even though several are FIPS-approved. See draft-jenkins-cnsa2-pkix-profile §4. 📚 Learning Path 3: Alternative PQC Algorithms (NEW!) For researchers, organizations requiring algorithm diversity, and those interested in international PQC implementations. This path explores post-quantum algorithms outside the primary NIST standards, providing options for defense-in-depth strategies and understanding of the broader PQC landscape. Perfect for organizations wanting to hedge against potential future vulnerabilities in current adopted standards. Modules Module Description 00 - Introduction Overview of non-NIST algorithms, international standards, use cases 01 - Environment Setup OpenSSL and modifying OQS provider configuration 02 - FrodoKEM Conservative unstructured lattice KEM (European recommended: BSI, ANSSI) 03 - BIKE and HQC Code-based KEMs (HQC is NIST-selected backup to ML-KEM) 04 - International PQC EU, South Korean, and Chinese algorithm standards 05 - Performance Analysis Comparing algorithms, latency impacts, use cases, nerd stats Algorithms Covered Algorithm Type Mathematical Basis Key Characteristic FrodoKEM KEM Unstructured lattice (LWE) Conservative security, European endorsed (BSI, ANSSI) BIKE KEM Code-based (QC-MDPC) NIST Round 4 candidate, smaller keys than HQC HQC KEM Code-based (Quasi-cyclic) NIST-selected backup to ML-KEM (standard expected 2027) Why Alternative Algorithms Matter Algorithm Diversity: If a vulnerability is found in lattice-based cryptography (ML-KEM), code-based alternatives provide a backup International Compliance: European agencies (BSI, ANSSI) specifically recommend FrodoKEM for conservative security Future-Proofing: HQC will become a FIPS standard in 2027 as NIST's official backup to ML-KEM Research & Testing: Understand the broader PQC landscape for informed decision-making What This Lab Guide Achieves Complete PKI Hierarchy Implementation The lab walks through building an internal PKI infrastructure from scratch, including: Root Certificate Authority: Using ML-DSA-87 providing the highest quantum-ready NIST security level Intermediate Certificate Authority: Intermediate Certificate Authority: ML-DSA-65 in the FIPS path, ML-DSA-87 in the CNSA 2.0 path for hierarchy-wide compliance. End-Entity Certificates: Server and user certificates with comprehensive Subject Alternative Names (SANs) for real-world applications Revocation Infrastructure: Both Certificate Revocation Lists (CRL) and Online Certificate Status Protocol (OCSP) implementation TLS 1.3 Key Exchange Testing: Hands-on testing with ML-KEM, hybrid modes, and alternative algorithms Security Best Practices: Restrictive Unix file permissions, secure key storage, and backup procedures throughout Key Takeaways After completing one or more of the labs, you will: Understand ML-DSA Cryptography: Gain hands-on experience with both ML-DSA-65 (Level 3 security) and ML-DSA-87 (Level 5 security) algorithms Explore Algorithm Diversity: Understand when and why to use alternative algorithms like FrodoKEM, BIKE, and HQC Configure Modern PKI Features: Implement SANs with DNS, IP, email, and URI entries, plus both CRL and OCSP revocation mechanisms Test TLS 1.3 Key Exchange: Hands-on experience with ML-KEM and hybrid key exchange in real TLS sessions Troubleshoot Effectively: Learn to diagnose and resolve common issues with opensl and oqsproviders for PQC compatibility Prepare for Migration: Start the practical steps needed to transition existing PKI infrastructure to quantum-resistant algorithms Access the Complete Lab Guide on GitHub → About This Guide We built the first guide for NSA Suite B in the distant past (2017) to learn ECC and modern cipher requirements. It was well received enough to built a new guide for CNSA 2.0 but it's quite specific for US federal audiences. That lead us to build a NIST FIPS PQC guide which should apply to more practical use cases. And now we've added alternative algorithms because things are only going to get a bit more complicated moving forward. In the spirit of Learn Python the Hard Way, it focuses on manual repetition, hands-on interactions and real-world scenarios. It provides the practical experiences needed to implement quantum-resistant PKI in production environments. By building it on GitHub, other PKI fans can help where we may have missed something; or simply to expand on it with additional modules or forks. Have at it! Frequently Asked Questions (FAQs) Q: What is CNSA 2.0? A: CNSA 2.0 (Commercial National Security Algorithm Suite 2.0) is the NSA's updated cryptographic standard requiring quantum-resistant algorithms. Q: When do I need to implement quantum-resistant cryptography? A: The NSA and NIST mandate CNSA 2.0 and FIPS 203/204/205 implementation by 2030. Organizations should begin now due to "harvest now, decrypt later" attacks where adversaries collect encrypted data today for future quantum decryption. Q: What is ML-DSA (Dilithium)? A: ML-DSA (Module-Lattice Digital Signature Algorithm), formerly known as Dilithium, is a NIST-standardized quantum-resistant digital signature algorithm specified in FIPS 204. Q: What is ML-KEM (Kyber)? A: ML-KEM... ships in three parameter sets — ML-KEM-512 (~AES-128), ML-KEM-768 (~AES-192), and ML-KEM-1024 (~AES-256). ML-KEM-768 is the common enterprise default; CNSA 2.0 requires ML-KEM-1024. Q: What are the alternative algorithms and why should I care? A: FrodoKEM, BIKE, and HQC are non-NIST-primary algorithms that provide algorithm diversity. If a vulnerability is discovered in lattice-based cryptography (which ML-KEM and ML-DSA use), code-based alternatives like HQC could provide a backup. HQC is actually NIST's selected backup to ML-KEM and will become a FIPS standard in 2027. Q: What's the difference between BIKE and HQC? A: Both are code-based KEMs. BIKE has smaller key sizes but wasn't selected by NIST. HQC has larger keys and was selected as NIST's official backup to ML-KEM. Q: Why do European agencies recommend FrodoKEM? A: FrodoKEM uses unstructured lattices (standard LWE) rather than the structured lattices used in ML-KEM. This provides more conservative security assumptions at the cost of larger key sizes. Germany's BSI and France's ANSSI specifically recommend FrodoKEM for high-security applications. Q: Is this guide suitable for production use? A: NOPE. While the guide teaches production-ready techniques and compliance requirements, always use Hardware Security Modules (HSMs) and air-gapped systems for production Root CAs (cold storage too). The lab is great for internal environments or test harnesses where you may need to test against new quantum-resistant signatures. ALWAYS rely on trusted public PKI infrastructure for production cryptography. 🤓 Happy PKI'ing! Reference Links NIST Post-Quantum Cryptography Standards - Official NIST PQC project page FIPS 203: ML-KEM Standard - Module-Lattice Key Encapsulation Mechanism FIPS 204: ML-DSA Standard - Module-Lattice Digital Signature Algorithm FIPS 205: SLH-DSA Standard - Stateless Hash-Based Digital Signature Algorithm NSA CNSA 2.0 Algorithm Requirements - NSA's official CNSA 2.0 announcement Open Quantum Safe Project - Home of the OQS provider for alternative algorithms OQS Provider for OpenSSL 3 - GitHub repository for OQS provider HQC Specification - Official HQC algorithm documentation BIKE Specification - Official BIKE algorithm documentation OpenSSL 3.5 Documentation - Comprehensive OpenSSL documentation1.5KViews4likes0CommentsEnforcing a Single Connection Max to Pool Members
I like finding jewels and nuggets of clarity in problems presented to the community at large, whether it’s here on DevCentral or in third party communities like Reddit, where member macallen posed the following problem in r/sysadmin a couple months back (paraphrased here, check the link for full context). Problem Statement I have a pool of five servers, and I need a maximum of one connection per server strictly enforced. When I set the connection limit to 1 at the node level, I’m still seeing a second connection offered when the 6th active request comes in. Any ideas on how I can accomplish this? Diagnosing the Problem First, I’ll mock this up in my lab, only on a smaller scale of two servers rather than five, and setting the connection limit on each server to one. Using curl from two virtual machines, I run curl 192.168.102.50/ several times and notice that I am seeing a max of two per server being enforced, not one as anticipated. The problem here is not that TMM is failing to honor the connection limits. The problem, at least on my test system, is that there are two TMMs present. Each TMM is limiting the servers to a maximum of one connection, so in this case, two connections are allowed instead of the required one. And just like the statistical representation of a family consisting of 2.3 kids, well, there’s no such thing as .3 of a kid, and there’s no such thing as .5 of a connection, so setting that doesn’t make much sense and isn’t allowed anyway. The good news is that for almost all use cases at scale the BIG-IP does the math, taking maximum configured connections and dividing by the number of TMMs. Note that this can lead to unexpected issues if for some reason the disaggregator (DAG) has an uneven connection distribution, and it is generally recommended NOT to have a connection maximum less than the active number of TMM instances. See K8457 for additional details. But now that the problem is known, what do I do about it? Solutions Option #1 - Duct Tape & Chewing Gum! In the Reddit thread, the original poster solved his own problem by, in his words, "I created a duct tape solution. I wrote a service that opens a port. When the user connects, it closes the port, when they disconnect it opens it back up. Then I created a contract in F5 for that port so it disables the node when the port is down. Cheap and dirty, but works." Glad to hear that works, but not a process I’d recommend. If someone else takes over ownership of that application and has no idea why that service exists and thus removes it…outage city! Option #2 - Configure BIG-IP VE for a Single Core I call this the machete mode, where I just whack some compute cycles away to solve the problem. That’s an easy one! Shut down the image, strip it down to a single core, fire it back up, and presto! And if this was the only application in service, that would be fantastic. But that’s not likely, and so punishing the rest of the application delivery needs to meet this need is not a great solution. Option #3 - Pin the Virtual Server to a Single Core with an iRule This option requires no system changes at all, just a simple iRule using a global variable, as they are not CMP compatible and thus will demote any virtual server to a single TMM, effectively pinning it and solving the problem. The iRule could look something like this: when RULE_INIT { set ::global_pin_tmm } This iRule is clean and compact, with no impact to traffic since its only engagement is at initialization. It also has a useful name, indicating it’s a global variable and its purpose is to pin the virtual server to a single TMM. Effective, but it feels a little icky to use an iRule with global variables in any version after 11.4 and one of my biggest messages when I speak at user groups is that “iRules are great! But don’t use them!” I always suggest the use of a configuration option when available, and only when iRules are necessary should they be utilized. Option #4 - Pin the Virtual Server to a Single Core with a TMSH Command That brings me to the final option I’ll explore, and that is to use a TMSH command to pin the virtual server. It’s an option on the virtual server (not available in the GUI) to disable CMP: tmsh modify ltm virtual <virtual name> cmp-enabled no Super simple, crystal clear in the configuration, no Tcl-machine necessary. That sounds like a winner to me and is evident now in a new screen capture. Conclusion With BIG-IP, there are often many ways to approach a problem. Sometimes there are no clear advantages amongst solutions, but this problem has a clear winner and that is the final option presented here: using the tmsh command to disable CMP.936Views0likes0CommentsLeverage BIG-IP 17.1 Distributed Cloud Services to Integrate F5 Distributed Cloud Bot Defense
Introduction: The F5 Distributed Cloud (XC) Bot Defense protects web and mobile properties from automated attacks by identifying and mitigating malicious bots. The Bot Defense uses JavaScript and API calls to collect telemetry and mitigate malicious users. The F5 Distributed Cloud (XC) Bot Defense is available in Standard and Enterprise service levels. In both the service levels the Bot Defense is available for traffic form web, web scarping, and mobile. The web scrapping is only applicable to web endpoints. This article will show you how to configure and use F5 Distributed Cloud Bot Defense (XC Bot Defense) on BIG-IP version 17.1 and above and monitor the solution on F5 Distributed Cloud Console (XC Console). Prerequisites: A valid XC Console account. If you don't have an account, visit Create a Distributed Cloud Console Account. An Organization plan. If you don't have an Organization plan, upgrade your plan. Getting Started: Log In to F5 XC Console: If XC Bot Defense isn't enabled, a Bot Defense landing page appears. Select Request Service to enable XC Bot Defense. If XC Bot Defense is enabled, you will see the tiles. Select Bot Defense. Verify you are in the correct Namespace. If your Namespace does not have any Protected Applications you will see the following page. Click Add Protected Application When you select a Namespace that has been configured with Protected Applications you will see this page. Scroll down to Manage Click Applications Click Add Application The Protected Application page is presented. Enter: Name Labels Description Select the Application Region - US in this example Connector Type - BIG-IP iApp for this demo. Cloudfront and Custom are other available connectors Scroll to the bottom and Click Save and Exit That will take you back to the Protected Applications Page. Verify your Application is listed with all the Metadata you supplied. Click the three ellipses to the right. Scroll down into the highlighted area and click and Copy App ID, Tenant ID and API Key Copy and save each value to a location where you can access it in the next steps. That completes the configuartion of F5 XC Console. Log In to your BIG-IP You will Notice in version 17.1 and above you will have a new selection along the left pane called Distributed Cloud Services. Expand and you will see all the latest integrations F5 provides. Application Traffic Insight Bot Defense Client-Side Defense Account Protection & Authentication Intelligence Cloud Services This article as stated before will focus on Bot Defense. Look for future articles that will focus on the other integrations. On the Main tab, Click Distributed Cloud Services > Bot Defense > Bot Profiles and Select Create This will bring up the General Properties page where you will enter required and optional information. Mandatory items have a Blue line on the edge. Supply a Name Application ID - From previous step Tenant ID - From previous step API Hostname - Web is filled in for you API Key - from previous step In the JS Injection Configuration section, the BIG-IP Handles JS Injectionsfield is checked by default, if you uncheck the field then follow the Note given in the Web UI. Protected Endpoint(s) - Web - Supply either the URI or IP of the Host Application along with the path and method you are protecting on the protected endpoint. In the following image, I have selected Advanced to show more detail of what is available. Again Mandatory fields have a blue indicator. Here the Protection Pool and SSL Profile. Click Finished when complete. One final step to complete the setup. Go to the Main tab, Local Traffic > Virtual Servers > Virtual Serves List Select the Virtual Server you are going to apply the Bot Defense profile to. Click on Distributed Cloud Services on the top banner Under Service Settings > Bot Defense set to Enable and then select the Bot Defense Profile you created in the above steps. The click Update. You have now sucessfully integrated BIG-IP Distributed Cloud Service on version 17.1 with F5 Distributed Coud Bot Defense. One final visual is the dashboard for F5 Distributed Cloud Bot Defense. This is where you will observe and monitor what bots and actions have been taken against bots and your protected applications. F5 XC Bot Defense on BIG-IP 17.1 Demo: Conclusion: I hope you were able to benefit from this tutorial. I was able to show how quickly and easlity it is to configure F5 Dsitributed Cloud Bot Defense on BIG-IP v17.1 using the built in Distributed Cloud Services integration. Related Links: https://www.f5.com/cloud https://www.f5.com/cloud/products/bot-defense BIG-IP Bot Defense on 14.x-16.x4.9KViews3likes4CommentsUsing Client Subnet in DNS Requests
BIG-IP DNS 14.0 now supports edns-client-subnet (ECS) for both responding to client requests (GSLB) or forwarding client requests (screening). The following is a quick start on using this feature. What is EDNS-Client-Subnet (ECS) If you are familiar with X-Forwarded-For headers in HTTP requests, ECS solves a similar problem. The problem is how to forward a DNS request through a proxy and preserve information about the original request (IP Address). Some of this discussion I also cover in a previous article,Implementing Client Subnet in DNS Requests . Traditional DNS Requests When a traditional DNS request is made, a client makes a request to a “local” DNS server (LDNS), and that request is forwarded to the authoritative DNS server for that domain. When a topology (send different responses based on the source address) record is evaluated it will use the source IP of the LDNS server. Usually this is OK for most applications, but it would be ideal to be able to forward more precise information from the LDNS server. ECS DNS Requests Using ECS a LDNS server can inject additional meta-data about the request that includes information about the source IP address of the client. In the following example a “Client Subnet” of 192.0.2.0/24 is forwarded to the DNS server. ECS on BIG-IP DNS F5 BIG-IP DNS can use ECS in two ways. Use ECS when handling topology requests Inject ECS when “screening” a DNS server Using ECS with BIG-IP DNS Topology There are two methods of configuring BIG-IP DNS to use ECS. Either at the wide-ip or globally. To configure ECS on a wide-ip: To configure ECS globally. Under DNS Settings. Injecting ECS records BIG-IP DNS can also proxy requests to other DNS servers (BIG-IP DNS or other vendors). When you modify the DNS profile to insert an ECS record. You will observe that the original /32 address will be forwarded to any DNS servers that are in the pool for that particular Virtual Server. The following is a diagram of the above.13KViews2likes28Comments