{"id":70,"date":"2026-08-29T10:52:17","date_gmt":"2026-08-29T10:52:17","guid":{"rendered":"https:\/\/networkguard360.com\/?p=70"},"modified":"2026-08-29T10:52:17","modified_gmt":"2026-08-29T10:52:17","slug":"f5-vip-reachable-application-down","status":"publish","type":"post","link":"https:\/\/networkguard360.com\/?p=70","title":{"rendered":"Application Down Behind F5: VIP Reachable, Pool Healthy &#8211; So Where Did the Traffic Stop?"},"content":{"rendered":"<p><strong>Category:<\/strong> F5<br \/>\n<strong>Technologies:<\/strong> F5 BIG-IP LTM, FortiGate, TCP, SNAT<br \/>\n<strong>Incident type:<\/strong> Application connectivity<br \/>\n<strong>Difficulty:<\/strong> Intermediate<\/p>\n<blockquote>\n<p><strong>Sanitization notice:<\/strong> The IP addresses are<br \/>\nrepresentative private values. Customer names, hostnames, credentials,<br \/>\nand sensitive topology details have been removed or changed.<\/p>\n<\/blockquote>\n<h2 id=\"incident-summary\">Incident summary<\/h2>\n<p>The application team reported that their service was down. Connection<br \/>\ntests to TCP ports <strong>20055<\/strong>, <strong>30055<\/strong>, and<br \/>\n<strong>40055<\/strong> failed through the F5 VIP<br \/>\n<code>10.200.252.190<\/code>.<\/p>\n<p>FortiGate logs showed a <strong>server reset (RST)<\/strong>, which<br \/>\ninitially suggested a backend issue. The server team found something<br \/>\ndifferent: all three ports were listening, but no connection attempt<br \/>\nreached the servers and no session entered the <code>ESTABLISHED<\/code><br \/>\nstate.<\/p>\n<p>The pool was healthy and the VIP was receiving traffic. The<br \/>\ninvestigation therefore focused on one question: <strong>where did the<br \/>\nflow stop between the F5 and the backend servers?<\/strong><\/p>\n<h2 id=\"environment\">Environment<\/h2>\n<table>\n<thead>\n<tr class=\"header\">\n<th>Component<\/th>\n<th>Details<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr class=\"odd\">\n<td>F5 BIG-IP LTM<\/td>\n<td>VIP <code>10.200.252.190<\/code><\/td>\n<\/tr>\n<tr class=\"even\">\n<td>F5 internal addresses<\/td>\n<td><code>172.22.72.251-254<\/code><\/td>\n<\/tr>\n<tr class=\"odd\">\n<td>Backend servers<\/td>\n<td><code>192.168.10.20-23<\/code><\/td>\n<\/tr>\n<tr class=\"even\">\n<td>Application ports<\/td>\n<td>TCP <code>20055<\/code>, <code>30055<\/code>, <code>40055<\/code><\/td>\n<\/tr>\n<tr class=\"odd\">\n<td>Firewall<\/td>\n<td>FortiGate<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2 id=\"traffic-path\">Traffic path<\/h2>\n<pre class=\"text\"><code>Client -&gt; FortiGate -&gt; F5 VIP -&gt; F5 server-side leg -&gt; FortiGate -&gt; Backend server<\/code><\/pre>\n<p>This path contains two separate flows:<\/p>\n<ol type=\"1\">\n<li>Client to F5 VIP<\/li>\n<li>F5 to backend server<\/li>\n<\/ol>\n<p>Proving that the first flow works does not prove that the second flow<br \/>\nis permitted.<\/p>\n<h2 id=\"investigation\">Investigation<\/h2>\n<h3 id=\"1-check-the-vip-and-source-translation\">1. Check the VIP and<br \/>\nsource translation<\/h3>\n<p>The virtual server, pool, and SNAT behavior were reviewed. The server<br \/>\nteam then checked for connection attempts from the expected F5-side<br \/>\nsource addresses.<\/p>\n<p>No traffic was visible on the backend servers.<\/p>\n<p><strong>Finding:<\/strong> The servers were not rejecting the<br \/>\nconnection; they were not receiving it.<\/p>\n<h3 id=\"2-confirm-that-traffic-reaches-the-f5\">2. Confirm that traffic<br \/>\nreaches the F5<\/h3>\n<p>A packet capture was taken on the F5 for the VIP and affected<br \/>\nports:<\/p>\n<div class=\"sourceCode\" id=\"cb2\">\n<pre\nclass=\"sourceCode bash\"><code class=\"sourceCode bash\"><span id=\"cb2-1\"><a href=\"#cb2-1\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"ex\">tcpdump<\/span> <span class=\"at\">-nni<\/span> 0.0:nnn <span class=\"dt\"><\/span><\/span>\n<span id=\"cb2-2\"><a href=\"#cb2-2\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>  <span class=\"st\">&#39;host 10.200.252.190 and (port 20055 or port 30055 or port 40055)&#39;<\/span><\/span><\/code><\/pre>\n<\/div>\n<p>The capture showed client packets arriving at the F5 correctly.<\/p>\n<p><strong>Finding:<\/strong> Client routing and firewall policy up to<br \/>\nthe VIP were working.<\/p>\n<h3 id=\"3-trace-the-server-side-flow\">3. Trace the server-side flow<\/h3>\n<p>The next capture focused on the backend network:<\/p>\n<div class=\"sourceCode\" id=\"cb3\">\n<pre\nclass=\"sourceCode bash\"><code class=\"sourceCode bash\"><span id=\"cb3-1\"><a href=\"#cb3-1\" aria-hidden=\"true\" tabindex=\"-1\"><\/a><span class=\"ex\">tcpdump<\/span> <span class=\"at\">-nni<\/span> 0.0:nnn <span class=\"dt\"><\/span><\/span>\n<span id=\"cb3-2\"><a href=\"#cb3-2\" aria-hidden=\"true\" tabindex=\"-1\"><\/a>  <span class=\"st\">&#39;net 192.168.10.0\/24 and (port 20055 or port 30055 or port 40055)&#39;<\/span><\/span><\/code><\/pre>\n<\/div>\n<p>The expected connection did not reach the backend servers. The<br \/>\nfailure was on the internal leg after the F5 accepted the client<br \/>\nrequest.<\/p>\n<h3 id=\"4-eliminate-common-f5-causes\">4. Eliminate common F5 causes<\/h3>\n<table>\n<thead>\n<tr class=\"header\">\n<th>Check<\/th>\n<th>Result<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr class=\"odd\">\n<td>Route to backend network<\/td>\n<td>Correct<\/td>\n<\/tr>\n<tr class=\"even\">\n<td>Internal VLAN and trunk<\/td>\n<td>Correct<\/td>\n<\/tr>\n<tr class=\"odd\">\n<td>Self IP and Floating IP<\/td>\n<td>Correct<\/td>\n<\/tr>\n<tr class=\"even\">\n<td>Pool and pool members<\/td>\n<td>Correct<\/td>\n<\/tr>\n<tr class=\"odd\">\n<td>Backup member\/port settings<\/td>\n<td>Correct<\/td>\n<\/tr>\n<tr class=\"even\">\n<td>Pool member state<\/td>\n<td>Up<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Nothing on the F5 explained why the backend servers saw no SYN<br \/>\npackets.<\/p>\n<h3 id=\"5-do-not-rely-only-on-pool-health\">5. Do not rely only on pool<br \/>\nhealth<\/h3>\n<p>The pool showed <strong>UP<\/strong>, but the monitor did not prove<br \/>\nthat production traffic on all three application ports was allowed end<br \/>\nto end.<\/p>\n<p>Monitor traffic can use a different source address, port, policy, or<br \/>\npath. A successful monitor proves only that the configured monitor<br \/>\nsucceeded.<\/p>\n<h3 id=\"6-recheck-the-firewall-using-the-actual-server-side-flow\">6.<br \/>\nRecheck the firewall using the actual server-side flow<\/h3>\n<p>The FortiGate logs and policies were reviewed again with the correct<br \/>\nvalues:<\/p>\n<ul>\n<li><strong>Source:<\/strong> F5 internal addresses<br \/>\n<code>172.22.72.251-254<\/code><\/li>\n<li><strong>Destination:<\/strong> Backend servers<br \/>\n<code>192.168.10.20-23<\/code><\/li>\n<li><strong>Ports:<\/strong> TCP <code>20055<\/code>, <code>30055<\/code>,<br \/>\n<code>40055<\/code><\/li>\n<\/ul>\n<p>This exposed the missing part of the design.<\/p>\n<h2 id=\"root-cause\">Root cause<\/h2>\n<p>The FortiGate allowed client traffic to reach the F5 VIP, but there<br \/>\nwas no policy permitting the separate connection from the F5 internal<br \/>\naddresses to the backend servers on the required application ports.<\/p>\n<p>The firewall terminated the downstream flow. This produced the reset<br \/>\nseen in the logs, even though the backend servers never received the<br \/>\nconnection.<\/p>\n<h2 id=\"resolution\">Resolution<\/h2>\n<p>A FortiGate policy was added with the following scope:<\/p>\n<table>\n<thead>\n<tr class=\"header\">\n<th>Policy field<\/th>\n<th>Value<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr class=\"odd\">\n<td>Source<\/td>\n<td>F5 internal addresses <code>172.22.72.251-254<\/code><\/td>\n<\/tr>\n<tr class=\"even\">\n<td>Destination<\/td>\n<td>Backend servers <code>192.168.10.20-23<\/code><\/td>\n<\/tr>\n<tr class=\"odd\">\n<td>Service<\/td>\n<td>TCP <code>20055<\/code>, <code>30055<\/code>, <code>40055<\/code><\/td>\n<\/tr>\n<tr class=\"even\">\n<td>Action<\/td>\n<td>Accept<\/td>\n<\/tr>\n<tr class=\"odd\">\n<td>Logging<\/td>\n<td>Enabled<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The rule was limited to the required sources, destinations, and ports<br \/>\nrather than using broad <code>ANY<\/code> objects.<\/p>\n<h2 id=\"verification\">Verification<\/h2>\n<p>After the policy was applied:<\/p>\n<ul>\n<li>TCP connection tests succeeded on all three ports.<\/li>\n<li>F5 captures showed traffic on both client-side and server-side<br \/>\nlegs.<\/li>\n<li>FortiGate logs showed the new policy accepting the sessions.<\/li>\n<li>Backend servers received the connections and established<br \/>\nsessions.<\/li>\n<li>The application team confirmed that the service was working<br \/>\nnormally.<\/li>\n<\/ul>\n<h2 id=\"what-made-this-incident-misleading\">What made this incident<br \/>\nmisleading?<\/h2>\n<table>\n<thead>\n<tr class=\"header\">\n<th>Observation<\/th>\n<th>Incorrect assumption<\/th>\n<th>Correct interpretation<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr class=\"odd\">\n<td>FortiGate reported a server reset<\/td>\n<td>The backend server sent the RST<\/td>\n<td>An intermediate device may terminate the flow<\/td>\n<\/tr>\n<tr class=\"even\">\n<td>Pool members were UP<\/td>\n<td>Application traffic must be allowed<\/td>\n<td>Only the configured monitor was successful<\/td>\n<\/tr>\n<tr class=\"odd\">\n<td>VIP received client packets<\/td>\n<td>The complete path was working<\/td>\n<td>Only the client-to-VIP leg was proven<\/td>\n<\/tr>\n<tr class=\"even\">\n<td>Server ports were listening<\/td>\n<td>The server should establish a session<\/td>\n<td>The SYN still had to reach the host<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2 id=\"key-lessons\">Key lessons<\/h2>\n<h3 id=\"trace-each-segment-separately\">Trace each segment<br \/>\nseparately<\/h3>\n<pre class=\"text\"><code>Client -&gt; firewall -&gt; VIP -&gt; F5 server side -&gt; firewall -&gt; backend<\/code><\/pre>\n<p>At each step, confirm both packet arrival and departure.<\/p>\n<h3 id=\"verify-the-source-address-seen-by-the-backend\">Verify the source<br \/>\naddress seen by the backend<\/h3>\n<p>Depending on the F5 design, the server may see a SNAT, automap, Self<br \/>\nIP-related, or other translated source. Firewall rules must match the<br \/>\nactual server-side source.<\/p>\n<h3 id=\"a-healthy-pool-is-not-an-end-to-end-test\">A healthy pool is not<br \/>\nan end-to-end test<\/h3>\n<p>Monitor success does not validate every production source,<br \/>\ndestination port, firewall policy, or return path.<\/p>\n<h3 id=\"confirm-who-generated-the-reset\">Confirm who generated the<br \/>\nreset<\/h3>\n<p>Do not rely only on the session-end label in a firewall log.<br \/>\nCorrelate captures and logs to locate the packet carrying the RST.<\/p>\n<h2 id=\"prevention-checklist\">Prevention checklist<\/h2>\n<ul class=\"task-list\">\n<li><label><input type=\"checkbox\" \/>Document both client-side and<br \/>\nserver-side flows for every VIP.<\/label><\/li>\n<li><label><input type=\"checkbox\" \/>Record the source address the<br \/>\nbackend should see.<\/label><\/li>\n<li><label><input type=\"checkbox\" \/>Include monitor ports and<br \/>\napplication ports in firewall reviews.<\/label><\/li>\n<li><label><input type=\"checkbox\" \/>Verify zones, policy order, NAT, and<br \/>\nreturn routing.<\/label><\/li>\n<li><label><input type=\"checkbox\" \/>Capture on both sides of the F5<br \/>\nduring service validation.<\/label><\/li>\n<li><label><input type=\"checkbox\" \/>Confirm that backend servers receive<br \/>\nthe expected SYN packets.<\/label><\/li>\n<li><label><input type=\"checkbox\" \/>Enable logging on relevant allow and<br \/>\ndeny policies.<\/label><\/li>\n<\/ul>\n<h2 id=\"final-takeaway\">Final takeaway<\/h2>\n<p>The traffic appeared to fail around the F5, but the decisive evidence<br \/>\ncame from comparing its two traffic legs. The client reached the VIP,<br \/>\nwhile the backend never received a SYN.<\/p>\n<p>When a VIP is reachable, pool members are healthy, and servers see no<br \/>\nconnection attempt, trace the server-side flow using the <strong>actual<br \/>\nF5 source address<\/strong>. That check can quickly reveal the missing<br \/>\nlink.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The application team reported an outage, yet the F5 VIP was reachable and pool members were healthy. This field case shows how packet captures isolated the missing link.<\/p>\n","protected":false},"author":0,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[13],"tags":[],"class_list":["post-70","post","type-post","status-publish","format-standard","hentry","category-f5"],"_links":{"self":[{"href":"https:\/\/networkguard360.com\/index.php?rest_route=\/wp\/v2\/posts\/70","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/networkguard360.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/networkguard360.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/networkguard360.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=70"}],"version-history":[{"count":0,"href":"https:\/\/networkguard360.com\/index.php?rest_route=\/wp\/v2\/posts\/70\/revisions"}],"wp:attachment":[{"href":"https:\/\/networkguard360.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=70"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/networkguard360.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=70"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/networkguard360.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=70"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}