<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Why do meters reject fresh DLMS connections after TCP keep-alive disconnects with frame-counter-out-of-sequence?]]></title><description><![CDATA[<blockquote>
<p dir="auto">[!WARNING]<br />
<strong>Technical Redaction &amp; Safe Harbor Notice</strong>:<br />
All communication captures, system titles, and cryptographic parameters in this thread have been sanitized and neutralized. Real utility meter identifiers, production encryption keys (GUEK/GAK/MK), SIM IMSIs, and proprietary network envelopes have been substituted with standard IEC 62056 synthetic test vectors. Do not post unredacted production captures or live cryptographic keys.</p>
</blockquote>
<p dir="auto">We are managing a fleet of 50,000 smart meters communicating over cellular NB-IoT to a centralized Head-End System (HES). When an active TCP connection drops due to cellular network tower handovers or keep-alive timeouts, the meter reconnects to HES and establishes a fresh TCP socket on port 4059.</p>
<p dir="auto">Upon reconnecting, HES sends an initial <code>AARQ</code> followed by an encrypted <code>Get-Request</code> using Security Suite 1 (<code>0xDB</code> General-Glo-Ciphering).<br />
However, the meter immediately drops the frame or returns <code>action-response-with-service-error: frame-counter-out-of-sequence</code>!</p>
<p dir="auto">Our HES server maintains a stateful database, but whenever a worker thread restarts, it re-initializes the Invocation Counter ($IC$) to <code>1</code>. Why does the meter permanently reject connections after socket restarts?</p>
]]></description><link>https://dlms.sharur.org/topic/60/why-do-meters-reject-fresh-dlms-connections-after-tcp-keep-alive-disconnects-with-frame-counter-out-of-sequence</link><generator>RSS for Node</generator><lastBuildDate>Fri, 16 Oct 2026 19:14:34 GMT</lastBuildDate><atom:link href="https://dlms.sharur.org/topic/60.rss" rel="self" type="application/rss+xml"/><pubDate>Sat, 22 Aug 2026 17:22:00 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Why do meters reject fresh DLMS connections after TCP keep-alive disconnects with frame-counter-out-of-sequence? on Sat, 22 Aug 2026 17:22:27 GMT]]></title><description><![CDATA[<p dir="auto">To synthesize for the community, here is the complete Python Gurux script demonstrating automated $IC$ synchronization:</p>
<pre><code class="language-python">from gurux_dlms.objects import GXDLMSSecuritySetup
from gurux_dlms.enums import Security, Authentication

def synchronize_invocation_counter(reader, client, security_obis="0.0.43.1.0.255"):
    # 1. Connect temporarily as Public Client (SAP 16)
    client.clientAddress = 16
    client.authentication = Authentication.NONE
    client.ciphering.security = Security.NONE
    
    # 2. Read Global Invocation Counter (Class 64, Attribute 4)
    ss = GXDLMSSecuritySetup(security_obis)
    current_ic = reader.read(ss, 4)
    print(f"[+] Current Meter Persisted Invocation Counter: {current_ic}")
    
    # 3. Synchronize Management Client with Safety Advance (+50)
    client.clientAddress = 1 # Management Client SAP 1
    client.authentication = Authentication.HIGH_GMAC
    client.ciphering.security = Security.AUTHENTICATION_ENCRYPTION
    client.ciphering.invocation_counter = current_ic + 50
    
    print(f"[+] Management Client IC synchronized to {client.ciphering.invocation_counter}. Ready for AARQ.")
</code></pre>
<h3>Summary Checklist:</h3>
<ol>
<li><strong>$IC$ Persistence</strong>: Invocation Counters survive reboots and socket disconnects (Green Book Section 9.2.5.3).</li>
<li><strong>Cold-Start Sync</strong>: Read Attribute 4 of Class 64 via Public Client (SAP 16).</li>
<li><strong>Safety Advance</strong>: Set $IC = IC_{\text{meter}} + 50$ to avoid race conditions.</li>
</ol>
]]></description><link>https://dlms.sharur.org/post/219</link><guid isPermaLink="true">https://dlms.sharur.org/post/219</guid><dc:creator><![CDATA[marcus_vance]]></dc:creator><pubDate>Sat, 22 Aug 2026 17:22:27 GMT</pubDate></item><item><title><![CDATA[Reply to Why do meters reject fresh DLMS connections after TCP keep-alive disconnects with frame-counter-out-of-sequence? on Sat, 22 Aug 2026 17:22:20 GMT]]></title><description><![CDATA[<p dir="auto">Always ensure that your HES advances the counter by a small margin (+10 to +100) before transmitting the first ciphered APDU to absorb any unacknowledged frames in transit.</p>
]]></description><link>https://dlms.sharur.org/post/218</link><guid isPermaLink="true">https://dlms.sharur.org/post/218</guid><dc:creator><![CDATA[elena_rostova]]></dc:creator><pubDate>Sat, 22 Aug 2026 17:22:20 GMT</pubDate></item><item><title><![CDATA[Reply to Why do meters reject fresh DLMS connections after TCP keep-alive disconnects with frame-counter-out-of-sequence? on Sat, 22 Aug 2026 17:22:17 GMT]]></title><description><![CDATA[<p dir="auto">Notice how the Public Client read solves the cold-start problem cleanly without exposing any secret keys!</p>
]]></description><link>https://dlms.sharur.org/post/217</link><guid isPermaLink="true">https://dlms.sharur.org/post/217</guid><dc:creator><![CDATA[alex_turner]]></dc:creator><pubDate>Sat, 22 Aug 2026 17:22:17 GMT</pubDate></item><item><title><![CDATA[Reply to Why do meters reject fresh DLMS connections after TCP keep-alive disconnects with frame-counter-out-of-sequence? on Sat, 22 Aug 2026 17:22:15 GMT]]></title><description><![CDATA[<p dir="auto">Here is the verified Public Client read request for the Invocation Counter:</p>
<pre><code class="language-hex">00 01 00 10 00 01 00 0D C0 01 C1 00 40 00 00 2B 01 00 FF 04 00
</code></pre>
<ul>
<li>Client SAP: <code>0x0010</code> (Public Client 16)</li>
<li>Class ID: <code>0x0040</code> (Class 64 Security Setup)</li>
<li>OBIS: <code>0.0.43.1.0.255</code></li>
<li>Attribute: <code>4</code> (<code>global_invocation_counter</code>)</li>
</ul>
<p dir="auto">And the meter's response returning current $IC = 14{,}280$ (<code>0x000037C8</code><img src="https://dlms.sharur.org/assets/plugins/nodebb-plugin-emoji/emoji/android/1f61e.png?v=666d1e6b6e4" class="not-responsive emoji emoji-android emoji--disappointed" style="height:23px;width:auto;vertical-align:middle" title="):" alt="😞" /></p>
<pre><code class="language-hex">00 01 00 10 00 01 00 09 C4 01 C1 00 06 00 00 37 C8
</code></pre>
]]></description><link>https://dlms.sharur.org/post/216</link><guid isPermaLink="true">https://dlms.sharur.org/post/216</guid><dc:creator><![CDATA[marcus_vance]]></dc:creator><pubDate>Sat, 22 Aug 2026 17:22:15 GMT</pubDate></item><item><title><![CDATA[Reply to Why do meters reject fresh DLMS connections after TCP keep-alive disconnects with frame-counter-out-of-sequence? on Sat, 22 Aug 2026 17:22:13 GMT]]></title><description><![CDATA[<p dir="auto">We tested the Public Client pre-read in the field across 200 failing meters:<br />
In every single case, reading Attribute 4 of <code>0.0.43.1.0.255</code> showed the meter was at $IC = 14{,}280$, while our restarted HES was trying to send $IC = 1$.<br />
Once we synced HES to $14{,}300$, all 200 meters reconnected instantly without a single drop!</p>
]]></description><link>https://dlms.sharur.org/post/215</link><guid isPermaLink="true">https://dlms.sharur.org/post/215</guid><dc:creator><![CDATA[carlos_mendez]]></dc:creator><pubDate>Sat, 22 Aug 2026 17:22:13 GMT</pubDate></item><item><title><![CDATA[Reply to Why do meters reject fresh DLMS connections after TCP keep-alive disconnects with frame-counter-out-of-sequence? on Sat, 22 Aug 2026 17:22:11 GMT]]></title><description><![CDATA[<p dir="auto">Let's look at the OBIS code for the Invocation Counter across different Security Setup instances:</p>
<ul>
<li><strong>Management Security Setup (Client SAP 1)</strong>: <code>0.0.43.1.0.255</code></li>
<li><strong>Firmware Upgrade Security Setup (Client SAP 2)</strong>: <code>0.0.43.1.1.255</code></li>
<li><strong>Customer Gateway Security Setup (Client SAP 3)</strong>: <code>0.0.43.1.2.255</code></li>
</ul>
<p dir="auto">Each logical client has an independent, non-overlapping Invocation Counter tracking sequence!</p>
]]></description><link>https://dlms.sharur.org/post/214</link><guid isPermaLink="true">https://dlms.sharur.org/post/214</guid><dc:creator><![CDATA[sarah_jenkins]]></dc:creator><pubDate>Sat, 22 Aug 2026 17:22:11 GMT</pubDate></item><item><title><![CDATA[Reply to Why do meters reject fresh DLMS connections after TCP keep-alive disconnects with frame-counter-out-of-sequence? on Sat, 22 Aug 2026 17:22:09 GMT]]></title><description><![CDATA[<p dir="auto">From the firmware implementation side, we write the latest $IC$ to Flash every $N$ transactions (and cache in battery-backed RAM) with an anti-wear leveling algorithm.</p>
<p dir="auto">When the meter powers on or re-establishes an association, it loads $IC_{\text{persisted}}$. If a client attempts a brute-force connection with lower $IC$, the meter will lock out the association after 3 failed attempts per Class 65 (<code>Single Port Protection</code>).</p>
]]></description><link>https://dlms.sharur.org/post/213</link><guid isPermaLink="true">https://dlms.sharur.org/post/213</guid><dc:creator><![CDATA[elena_rostova]]></dc:creator><pubDate>Sat, 22 Aug 2026 17:22:09 GMT</pubDate></item><item><title><![CDATA[Reply to Why do meters reject fresh DLMS connections after TCP keep-alive disconnects with frame-counter-out-of-sequence? on Sat, 22 Aug 2026 17:22:07 GMT]]></title><description><![CDATA[<p dir="auto">How should HES synchronize its Invocation Counter when state is lost?</p>
<p dir="auto">Per <strong>DLMS Blue Book Ed. 17 Section 4.6.2 (Security Setup Class 64)</strong>:<br />
Class 64 defines Attribute 4: <strong><code>global_invocation_counter</code></strong> (Double-Long-Unsigned).</p>
<h3>The Standard Synchronization Handshake:</h3>
<ol>
<li><strong>Connect via Public Client (<code>Client SAP 0x0010</code>)</strong>:<br />
Public Client requires no encryption and allows reading Public objects;</li>
<li><strong>Read Current Meter IC</strong>:<br />
Issue <code>Get-Request-Normal</code> for OBIS <code>0.0.43.1.0.255</code> (or associated Security Setup object) Attribute 4;</li>
<li><strong>Synchronize HES Counter</strong>:<br />
$$\text{HES } IC = \text{Meter } IC + 100$$ (advance by a safety margin);</li>
<li><strong>Connect via Management Client (<code>Client SAP 0x0001</code>)</strong>:<br />
Transmit <code>AARQ</code> and ciphered APDUs using the newly synchronized $IC$.</li>
</ol>
]]></description><link>https://dlms.sharur.org/post/212</link><guid isPermaLink="true">https://dlms.sharur.org/post/212</guid><dc:creator><![CDATA[david_miller]]></dc:creator><pubDate>Sat, 22 Aug 2026 17:22:07 GMT</pubDate></item><item><title><![CDATA[Reply to Why do meters reject fresh DLMS connections after TCP keep-alive disconnects with frame-counter-out-of-sequence? on Sat, 22 Aug 2026 17:22:03 GMT]]></title><description><![CDATA[<p dir="auto">Marcus, this is the core security invariant of DLMS Security Suite 1: <strong>The Invocation Counter ($IC$) is persistent across connection lifetimes.</strong></p>
<p dir="auto">Per <strong>DLMS Green Book 10th Ed Section 9.2.5.3 (Invocation Counter Management)</strong> and <strong>IEC 62056-53 Section 8.4.2</strong>:<br />
The 4-byte Invocation Counter ($IC$) is a strictly monotonic anti-replay sequence number.</p>
<h3>The Meter's Non-Volatile Persistence:</h3>
<p dir="auto">In the meter's security engine (Class 64 <code>Security Setup</code>), the meter stores the last verified Invocation Counter from Client SAP <code>0x0001</code> in <strong>non-volatile memory (EEPROM / Flash)</strong>:<br />
$$\text{Condition: } IC_{\text{rx}} &gt; IC_{\text{persisted}}$$</p>
<p dir="auto">If your HES worker thread restarts and resets $IC$ to <code>1</code> (or any value $\le IC_{\text{persisted}}$), the meter's AES-GCM decryption engine flags an active replay attack and drops the frame by design!</p>
]]></description><link>https://dlms.sharur.org/post/211</link><guid isPermaLink="true">https://dlms.sharur.org/post/211</guid><dc:creator><![CDATA[alex_turner]]></dc:creator><pubDate>Sat, 22 Aug 2026 17:22:03 GMT</pubDate></item></channel></rss>