Skip to content

CVPN-2559: Handle expresslane flags and session id tampering#425

Open
kp-mariappan-ramasamy wants to merge 13 commits into
mainfrom
expresslane-flags
Open

CVPN-2559: Handle expresslane flags and session id tampering#425
kp-mariappan-ramasamy wants to merge 13 commits into
mainfrom
expresslane-flags

Conversation

@kp-mariappan-ramasamy
Copy link
Copy Markdown
Contributor

@kp-mariappan-ramasamy kp-mariappan-ramasamy commented May 14, 2026

Description

Changes:

  • Add expresslane flags in AAD to detect the flags tampering and update expresslane version to v2
  • Make the Protocol Version mismatch as nonfatal since it is a plaintext header
  • Make expresslane keys rotation interval as configurable
  • Make connection expiration interval and stats report interval also as configurable

Motivation and Context

Since expresslane flags are not included in AAD, a onpath attacker can modfiy expresslane flags without being detected and close the connection. We got notified by a researcher about this bug.

Also the protocol version in UDP lightway packets can be tampered by on-path attacker and make server close the client connection. Ignore protocol version error too since it is a plaintext header.

How Has This Been Tested?

Added unit test to verify this tampering

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change. This would break compat with existing clients. But we have not deploy any clients yet, also clients will fallback to DTLS.

Checklist:

  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • The correct base branch is being used, if not main

Looks like, cargo lock update is missed in previous PR
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 14, 2026

Code coverage summary for d45bf53:

Filename                                                          Regions    Missed Regions     Cover   Functions  Missed Functions  Executed       Lines      Missed Lines     Cover    Branches   Missed Branches     Cover
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
lightway-app-utils/src/args/cipher.rs                                   5                 5     0.00%           1                 1     0.00%           5                 5     0.00%           0                 0         -
lightway-app-utils/src/args/connection_type.rs                          8                 8     0.00%           2                 2     0.00%           8                 8     0.00%           0                 0         -
lightway-app-utils/src/args/duration.rs                               121                22    81.82%          11                 5    54.55%          64                15    76.56%           0                 0         -
lightway-app-utils/src/args/ip_map.rs                                  27                27     0.00%           5                 5     0.00%          19                19     0.00%           0                 0         -
lightway-app-utils/src/args/keyshare.rs                                 5                 5     0.00%           1                 1     0.00%           5                 5     0.00%           0                 0         -
lightway-app-utils/src/args/logging.rs                                 37                37     0.00%           3                 3     0.00%          31                31     0.00%           0                 0         -
lightway-app-utils/src/args/nonzero_duration.rs                       128                24    81.25%          10                 4    60.00%          68                16    76.47%           0                 0         -
lightway-app-utils/src/connection_ticker.rs                           229                17    92.58%          28                 4    85.71%         126                15    88.10%           0                 0         -
lightway-app-utils/src/dplpmtud_timer.rs                              209                13    93.78%          22                 4    81.82%         117                11    90.60%           0                 0         -
lightway-app-utils/src/event_stream.rs                                 19                 0   100.00%           3                 0   100.00%          11                 0   100.00%           0                 0         -
lightway-app-utils/src/packet_codec.rs                                  2                 2     0.00%           1                 1     0.00%           1                 1     0.00%           0                 0         -
lightway-app-utils/src/sockopt/ip_mtu_discover.rs                      81                81     0.00%           6                 6     0.00%          72                72     0.00%           0                 0         -
lightway-app-utils/src/sockopt/ip_pktinfo.rs                           14                14     0.00%           1                 1     0.00%          16                16     0.00%           0                 0         -
lightway-app-utils/src/tun.rs                                         280               280     0.00%          31                31     0.00%         174               174     0.00%           0                 0         -
lightway-app-utils/src/utils.rs                                        21                21     0.00%           1                 1     0.00%          11                11     0.00%           0                 0         -
lightway-client/src/config.rs                                         235                39    83.40%          12                 5    58.33%         173                34    80.35%           0                 0         -
lightway-client/src/dns_manager.rs                                     18                18     0.00%           4                 4     0.00%          16                16     0.00%           0                 0         -
lightway-client/src/io/inside/tun.rs                                   82                82     0.00%          12                12     0.00%          60                60     0.00%           0                 0         -
lightway-client/src/io/outside.rs                                      14                14     0.00%           2                 2     0.00%          12                12     0.00%           0                 0         -
lightway-client/src/io/outside/tcp.rs                                  89                89     0.00%          12                12     0.00%          56                56     0.00%           0                 0         -
lightway-client/src/io/outside/udp.rs                                 167               167     0.00%          17                17     0.00%         108               108     0.00%           0                 0         -
lightway-client/src/io/outside/udp_batch_receiver.rs                   61                11    81.97%           6                 1    83.33%          56                12    78.57%           0                 0         -
lightway-client/src/keepalive.rs                                      615                44    92.85%          55                 6    89.09%         330                25    92.42%           0                 0         -
lightway-client/src/lib.rs                                           1246               670    46.23%         102                53    48.04%         835               489    41.44%           0                 0         -
lightway-client/src/main.rs                                           361               361     0.00%          20                20     0.00%         228               228     0.00%           0                 0         -
lightway-client/src/platform/linux/dns_manager.rs                     118                91    22.88%          14                 9    35.71%          87                62    28.74%           0                 0         -
lightway-client/src/platform/linux/dns_manager/direct_file.rs         106                42    60.38%          12                 6    50.00%          65                29    55.38%           0                 0         -
lightway-client/src/platform/linux/dns_manager/resolvconf.rs           61                61     0.00%           8                 8     0.00%          52                52     0.00%           0                 0         -
lightway-client/src/platform/linux/dns_manager/resolvectl.rs           41                41     0.00%           5                 5     0.00%          34                34     0.00%           0                 0         -
lightway-client/src/route_manager.rs                                 1190               212    82.18%          77                 8    89.61%         663               117    82.35%           0                 0         -
lightway-core/src/borrowed_bytesmut.rs                                373                 0   100.00%          24                 0   100.00%         185                 0   100.00%           0                 0         -
lightway-core/src/builder_predicates.rs                                24                12    50.00%           4                 2    50.00%          24                12    50.00%           0                 0         -
lightway-core/src/cipher.rs                                            13                 0   100.00%           2                 0   100.00%          10                 0   100.00%           0                 0         -
lightway-core/src/connection.rs                                      1663               826    50.33%          72                27    62.50%        1173               552    52.94%           0                 0         -
lightway-core/src/connection/builders.rs                              244                46    81.15%          21                 8    61.90%         252                53    78.97%           0                 0         -
lightway-core/src/connection/dplpmtud.rs                             1741                81    95.35%          63                 0   100.00%         830                 7    99.16%           0                 0         -
lightway-core/src/connection/expresslane.rs                            27                11    59.26%           4                 1    75.00%          36                 7    80.56%           0                 0         -
lightway-core/src/connection/fragment_map.rs                          366                 6    98.36%          25                 0   100.00%         254                 3    98.82%           0                 0         -
lightway-core/src/connection/io_adapter.rs                            526                23    95.63%          34                 5    85.29%         276                21    92.39%           0                 0         -
lightway-core/src/connection/key_update.rs                             34                13    61.76%           5                 0   100.00%          38                19    50.00%           0                 0         -
lightway-core/src/context.rs                                          214                51    76.17%          28                11    60.71%         235                64    72.77%           0                 0         -
lightway-core/src/context/ip_pool.rs                                    8                 3    62.50%           1                 0   100.00%           5                 0   100.00%           0                 0         -
lightway-core/src/context/server_auth.rs                               32                24    25.00%           4                 3    25.00%          24                20    16.67%           0                 0         -
lightway-core/src/encoding_request_states.rs                            3                 0   100.00%           1                 0   100.00%           3                 0   100.00%           0                 0         -
lightway-core/src/io.rs                                                10                10     0.00%           3                 3     0.00%           9                 9     0.00%           0                 0         -
lightway-core/src/keyshare.rs                                           5                 0   100.00%           1                 0   100.00%           5                 0   100.00%           0                 0         -
lightway-core/src/lib.rs                                                9                 0   100.00%           3                 0   100.00%           9                 0   100.00%           0                 0         -
lightway-core/src/metrics.rs                                           51                41    19.61%          21                17    19.05%          47                37    21.28%           0                 0         -
lightway-core/src/packet.rs                                            38                10    73.68%           4                 1    75.00%          30                 6    80.00%           0                 0         -
lightway-core/src/plugin.rs                                           303                13    95.71%          21                 3    85.71%         145                 7    95.17%           0                 0         -
lightway-core/src/tls/mod.rs                                            4                 4     0.00%           1                 1     0.00%           3                 3     0.00%           0                 0         -
lightway-core/src/utils.rs                                            334                26    92.22%          22                 2    90.91%         165                17    89.70%           0                 0         -
lightway-core/src/version.rs                                           93                 0   100.00%          17                 0   100.00%          82                 0   100.00%           0                 0         -
lightway-core/src/wire.rs                                             438                42    90.41%          29                 1    96.55%         235                12    94.89%           0                 0         -
lightway-core/src/wire/auth_failure.rs                                 27                 1    96.30%           3                 0   100.00%          17                 0   100.00%           0                 0         -
lightway-core/src/wire/auth_request.rs                                472                12    97.46%          26                 0   100.00%         241                 0   100.00%           0                 0         -
lightway-core/src/wire/auth_success_with_config_ipv4.rs               222                 3    98.65%          11                 0   100.00%         124                 0   100.00%           0                 0         -
lightway-core/src/wire/data.rs                                         51                 1    98.04%           5                 0   100.00%          33                 0   100.00%           0                 0         -
lightway-core/src/wire/data_frag.rs                                   127                 1    99.21%          14                 0   100.00%          80                 0   100.00%           0                 0         -
lightway-core/src/wire/encoding_request.rs                             82                 2    97.56%           6                 0   100.00%          42                 1    97.62%           0                 0         -
lightway-core/src/wire/encoding_response.rs                            82                 2    97.56%           6                 0   100.00%          42                 1    97.62%           0                 0         -
lightway-core/src/wire/expresslane_config.rs                          192                 1    99.48%          10                 0   100.00%         110                 0   100.00%           0                 0         -
lightway-core/src/wire/expresslane_data.rs                           1330                69    94.81%          48                 5    89.58%         679                37    94.55%           0                 0         -
lightway-core/src/wire/ping.rs                                         95                 2    97.89%           7                 0   100.00%          59                 0   100.00%           0                 0         -
lightway-core/src/wire/pong.rs                                        109                 2    98.17%           8                 0   100.00%          72                 0   100.00%           0                 0         -
lightway-core/src/wire/server_config.rs                                69                 2    97.10%           4                 0   100.00%          37                 0   100.00%           0                 0         -
lightway-server/src/auth.rs                                           273                49    82.05%          22                 6    72.73%         171                28    83.63%           0                 0         -
lightway-server/src/config.rs                                          26                26     0.00%           1                 1     0.00%          44                44     0.00%           0                 0         -
lightway-server/src/connection.rs                                     137               137     0.00%          11                11     0.00%         110               110     0.00%           0                 0         -
lightway-server/src/connection_manager.rs                             339               339     0.00%          40                40     0.00%         294               294     0.00%           0                 0         -
lightway-server/src/connection_manager/connection_map.rs              407                16    96.07%          21                 1    95.24%         228                 7    96.93%           0                 0         -
lightway-server/src/io/inside/tun.rs                                   44                44     0.00%           9                 9     0.00%          30                30     0.00%           0                 0         -
lightway-server/src/io/outside/tcp.rs                                  90                90     0.00%           9                 9     0.00%          65                65     0.00%           0                 0         -
lightway-server/src/io/outside/udp.rs                                 320               320     0.00%          16                16     0.00%         206               206     0.00%           0                 0         -
lightway-server/src/io/outside/udp/cmsg.rs                            197                53    73.10%          14                 5    64.29%         158                43    72.78%           0                 0         -
lightway-server/src/ip_manager.rs                                     542                50    90.77%          22                 4    81.82%         242                23    90.50%           0                 0         -
lightway-server/src/ip_manager/ip_pool.rs                             545                 0   100.00%          28                 0   100.00%         257                 0   100.00%           0                 0         -
lightway-server/src/lib.rs                                            292               292     0.00%          15                15     0.00%         194               194     0.00%           0                 0         -
lightway-server/src/main.rs                                           246               246     0.00%          10                10     0.00%         129               129     0.00%           0                 0         -
lightway-server/src/metrics.rs                                        254               250     1.57%          85                83     2.35%         215               211     1.86%           0                 0         -
lightway-server/src/statistics.rs                                     132                59    55.30%           8                 4    50.00%          90                39    56.67%           0                 0         -
uniffi-bindgen/src/uniffi-bindgen.rs                                    3                 3     0.00%           1                 1     0.00%           3                 3     0.00%           0                 0         -
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TOTAL                                                               18848              5812    69.16%        1354               542    59.97%       11550              4047    64.96%           0                 0         -

✅ Region coverage 69% passes
✅ Line coverage 64% passes

Make EXPRESSLANE_KEYS_ROTATION_INTERVAL to a per-connection setting
and exposed in client and server configs.
@kp-mariappan-ramasamy kp-mariappan-ramasamy marked this pull request as ready for review May 15, 2026 06:08
@kp-mariappan-ramasamy kp-mariappan-ramasamy requested a review from a team as a code owner May 15, 2026 06:08
@kp-mariappan-ramasamy kp-mariappan-ramasamy changed the title Expresslane flags CVPN-2558: CVPN-2559: Handle expresslane flags and session id tampering May 15, 2026
@kp-mariappan-ramasamy kp-mariappan-ramasamy changed the title CVPN-2558: CVPN-2559: Handle expresslane flags and session id tampering CVPN-2559: Handle expresslane flags and session id tampering May 15, 2026
Forged UDP packet with the same session id but a different
protocol version byte could tear down an established session. Drop
the packet instead.

There are two distinct error paths:

  * ConnectionError::InvalidProtocolVersion
    Header parsed successfully but its version does not match the
    session's tunnel_protocol_version. Was fatal in the Datagram arm.

  * WireError(FromWireError::InvalidProtocolVersion(..))
    Header parse itself rejects the version bytes as not a known
    protocol version at all. Previously caught by the WireError(_)
    catch-all, which is fatal. An attacker who garbles the version
    bytes (e.g. 99.99) instead of just mismatching them would still
    have killed the session via this path.

Header bytes are plaintext on the wire by design (the server needs
session id to route to the right Connection before DTLS decryption),
so any destructive action keyed off header content alone is an
unauthenticated-input DoS. Both paths now drop the packet and keep
the session alive.
The test currently fails to demonstrate the issue. Will be fixed
in next commit
The flags field is transmitted in clear on the wire. Without including
it in the AEAD associated data, an on-path attacker could flip the
encoded bit without invalidating the auth tag, steering the receiver
down the wrong packet-codec path. Extend auth_vec from 16 to 18 bytes
to cover session_id || wire_counter || flags.
Comment thread lightway-core/src/connection.rs
Comment on lines 234 to 273
@@ -249,7 +245,6 @@ impl ConnectionError {
match self {
TimedOut => true,
Unauthorized => true,
InvalidProtocolVersion => true,
InvalidMode => true,
InvalidConnectionType => true,
NoAvailableClientIp => true,
@@ -259,7 +254,6 @@ impl ConnectionError {
PacketCodecDoesNotExist => true,
PacketCodecError(_) => true,
Disconnected => true,
EncodingReqRetransmitCbDoesNotExist => true,
PathMtuDiscoveryRequired { .. } => true,
Tls(crate::tls::Error::Fatal(ErrorKind::DomainNameMismatch)) => true,
Tls(crate::tls::Error::Fatal(ErrorKind::DuplicateMessage)) => true,
@@ -270,8 +264,10 @@ impl ConnectionError {
WireError(wire::FromWireError::InsufficientData) => false,
WireError(wire::FromWireError::InvalidExpressData) => false,
WireError(wire::FromWireError::ReplayedExpressData) => false,
WireError(wire::FromWireError::InvalidProtocolVersion(..)) => false,
WireError(_) => true,

InvalidProtocolVersion => false,
InvalidState => false, // Can be due to out of order or repeated messages
InvalidInsideIo => false, // Can be used for test only test control plane
UnknownSessionID => false,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit concerned about this one - does this mean older Lightway client can now connect to a newer server without any issue in the future if we bumped Lightway version to a newer one?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it is a general rule to make server backward compatible with client. Even now, without expresslane older clients 1.2 will still be able to connect to 1.3 server.
This change should not impact that, and is targeted to ignore tampered protocol version.

I did not understand your exact concern though, can you explain a bit more

Comment thread lightway-core/src/connection.rs Outdated
Replace the strict equality check 'config.version != tunnel_protocol_version'
with a forward-compatible negotiation:

  * peer advertised our local max or below → take min(local_max, peer).
  * peer advertised an Unknown byte (byte 0, or any byte we do not
    recognise — e.g. a future version we have not seen yet) → fall
    back to our local max.

Net effect: V_n peer talking to V_m build (n != m) negotiates to
min(n, m) in both directions. Lets us ship new protocol versions
later without breaking expresslane interop with the binaries
already in the field.

A peer that genuinely sends byte 0 (never advertised) is treated
the same as a future version: we reply with our local max. The
peer won't be able to reciprocate, expresslane simply won't
establish — same outcome as a reject.
Bump the expresslane wire version to Version2. V2 binds the flags
field into the AEAD AAD so an on-path attacker cannot flip flags
without invalidating the auth tag. V1 keeps the original layout (no
flags in AAD) for interoperability with legacy V1 peers that
predate the AAD change.

Outgoing config now advertises whatever version was negotiated with
the peer instead of always advertising LOCAL_MAX. A V2 server talking
to a V1 client thus downgrades its own outgoing config to V1, and
the V1 wire path stays compatible with the legacy peer. The initial
outgoing config (before any peer reply) still uses LOCAL_MAX.

Net effect: V2 endpoints talking to each other get full flag
protection. V2 endpoints talking to legacy V1 peers continue to
interoperate (no protection on flags for those sessions, same posture
as before the AAD change). No silent AEAD failures between old and
new endpoints; mismatches surface at config exchange time.
@kp-mariappan-ramasamy kp-mariappan-ramasamy force-pushed the expresslane-flags branch 2 times, most recently from 6082d8c to c6eb712 Compare May 18, 2026 04:12
Found when running clippy enabling all features.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants