Add KNX IP Secure server-side TCP tunnelling#5
Draft
evgeny-boger wants to merge 8 commits intofix/max-apdu-length-v2from
Draft
Add KNX IP Secure server-side TCP tunnelling#5evgeny-boger wants to merge 8 commits intofix/max-apdu-length-v2from
evgeny-boger wants to merge 8 commits intofix/max-apdu-length-v2from
Conversation
18ad1df to
0833c0a
Compare
0833c0a to
0cba4de
Compare
Implement KNX IP Secure (03_08_09) for the TCP tunnel server, allowing encrypted and authenticated KNXnet/IP connections from ETS and other KNX IP Secure clients. Protocol implementation: - SESSION_REQUEST/RESPONSE: X25519 ECDH key exchange with device authentication MAC (PBKDF2-derived key) - SESSION_AUTHENTICATE: User password verification via CCM MAC - SECURE_WRAPPER: AES-128-CCM encryption/authentication of all subsequent KNXnet/IP frames (16-byte MAC) - Session state machine: IDLE → UNAUTHENTICATED → AUTHENTICATED - Sequence number tracking for replay protection - Session keepalive and close handling Configuration: [mytcp] server = tcptunsrv device-auth = <device authentication password> user-password = <user password> Or load from .knxkeys keyring file: keyring = /path/to/project.knxkeys keyring-password = <keyring password> Tested end-to-end with XKNX Python library as KNX IP Secure client. Full session lifecycle verified: handshake, authentication, tunnel establishment, data exchange, and clean disconnect. Also fixes tools/version.sh to work in git worktrees. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Clear session_key and xor_client_server in SecureSession destructor - Clear xor_client_server after successful authentication - Remove dead code: aes_ctr_stream(), unused includes (openssl/rand.h, openssl/x509.h) - Fix sequence number: initialize recv_seq to UINT64_MAX so first frame (seq=0) is accepted, replays properly rejected - Add session cleanup in TcpTunConn::stop() to prevent session leaks - Limit concurrent sessions to IPSEC_MAX_SESSIONS (16) - Fix user_id logging: read after handleSessionAuthenticate() succeeds - Move service type constants from header to .cpp (only used internally) - Filter keyring Interface elements by Type="Tunneling" or "Backbone" Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add Security service family (0x09) to DESCRIPTION_RESPONSE on TCP tunnel server when IP Secure is enabled, so ETS discovers the secure tunnelling capability. Add `secure` config option to ets_router (UDP server) to include SF_SECURITY in SEARCH_RESPONSE for multicast discovery. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
f25d994 to
9d345ad
Compare
Advertise SF_SECURITY in SEARCH_RESPONSE_EXTENDED when IP Secure is enabled, matching DESCRIPTION_RESPONSE behavior. Do not reject plain CONNECT_REQUESTs — ETS decides whether to use IP Secure based on its project configuration, not server rejection. Both plain and secure connections are accepted on the same port. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
9d345ad to
07d651f
Compare
- Replace hand-rolled XML parsing with pugixml DOM parser - Fix keyring password extraction: skip 8-byte random prefix, remove PKCS7 padding, PBKDF2-derive keys from plaintext passwords - Load management password (user 1) from Device elements - Add Secure Service Families DIB (type 0x06) to all responses (DESCRIPTION_RESPONSE, SEARCH_RESPONSE, SEARCH_RESPONSE_EXTENDED) - Add Tunnelling Info DIB (type 0x07) with tunnel slot addresses - Advertise service families v2 when secure is enabled - Add pugixml link dependency Tested end-to-end with ETS 6 connecting via KNX IP Secure. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add detailed comments in tcptunserver.cpp explaining password roles: user-password (ETS "Commissioning Password") is mandatory, device-auth is optional (client MITM prevention only) - Document that ETS initiates IP Secure from Secure Service Families DIB without requiring a KNX IP Router in the project - Add BUILD.md with cross-compile and deploy instructions Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
c613abf to
cba3c2f
Compare
Remove all keyring XML parsing code (pugixml dependency, base64 decode, AES-CBC decrypt, password extraction). The keyring loading was unreliable because ETS prompts the user for the "Commissioning Password" regardless of whether the keyring is loaded — ETS matches credentials by device serial number, not by individual address. The simplest and most reliable approach: - Set user-password in knxd config - Enter the same password in ETS when prompted - Optionally set device-auth for MITM prevention Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add --enable-ipsecure / --disable-ipsecure configure option. When disabled, knxd builds without libcrypto dependency and all IP Secure code is compiled out via #ifdef HAVE_IPSECURE. Also adds serial-number config option for discovery DIBs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Add KNX IP Secure (03_08_09) support for the TCP tunnel server, allowing encrypted and authenticated KNXnet/IP connections from ETS and other clients.
How it works
Passwords
user-password(mandatory) — authenticates the client to the server. ETS calls this "Commissioning Password". Set for both management (user 1) and tunnelling (user 2) access.device-auth(optional) — the Device Authentication Code. Authenticates the server to the client to prevent MITM attacks. The client may skip verification if it doesn't know the code. IP Secure works without it.Configuration
Simple (recommended):
With device authentication and custom serial number:
For UDP discovery with security advertisement:
Build options
Dependencies
--enable-ipsecure(default)Note on .knxkeys keyring files
Keyring loading was intentionally not implemented. ETS prompts the user for the "Commissioning Password" when connecting to an IP Secure device, regardless of whether the keyring is loaded. Since knxd is not a real KNX device, ETS never programs passwords into it. The simplest approach is to set
user-passworddirectly in the config and enter the same password in ETS when prompted.Test plan
🤖 Generated with Claude Code