Skip to content

Multipath TCP (MPTCP) + wstunnel #508

Description

@devalexqt

Describe the bug

In reverse tunnel mode i have strange bug: Start to download 1Gig file (on wstunnel server) over reverse tunnel via curl but it starts at low speed up to 3Mbit/sec for up to 20-60 seconds then speed drop to zero for 2-3 seconds and after that speed quickly jump up to 1000Mbit/sec and stay at this value to the end of file download.
This only happening for the download speed! Upload speed is fine and has fast start up to the max channel speed.

To Reproduce

Build wstunnel from source (wstunnel-cli 10.5.5) and run reverse tunnel with mptcp via mptcpize run, because wstunnel don't support natively mptcp:

mptcpize run  /root/wstunnel/target/release/wstunnel server --restrict-http-upgrade-path-prefix htaz........................q4JNoycsW  wss://0.0.0.0:8443


mptcpize run /root/wstunnel/target/release/wstunnel client --http-upgrade-path-prefix htaz...............................q4JNoycsW -R 'tcp://[::]:8001:localhost:8000' wss://xxx.xxx.xxx.xxx6:8443

Run file transfer upload/download (on the server side what utilize reverse proxy tunnel to local server)

#fast start up and fast speed
/snap/bin/curl  -k -X POST -T local_test_1000.bin https://localhost:8001/upload -o /dev/null --http1.1

#start at low speed around 3Mbit/sec for up to 60 seconds and then drop speed to zero and then start to transfer at up to 1000Mbit/speed.

/snap/bin/curl -k https://localhost:8001/download -o /dev/null --http1.1
Image Image

Expected behavior

File transfer upload/download must fast start up to the max channel speed.

Your wstunnel setup

Paste your logs of wstunnel, started with --log-lvl=DEBUG, and with the command line used

  • client
2026-05-21T14:12:26.516206Z  INFO wstunnel: Starting wstunnel client v10.5.5
2026-05-21T14:12:26.516262Z  INFO wstunnel::protocols::tcp::server: Opening TCP connection to XXX.XXX.XXX.XXX:8443
2026-05-21T14:12:26.516292Z DEBUG wstunnel::protocols::tcp::server: Connecting to XXX.XXX.XXX.XXX:8443
2026-05-21T14:12:26.555047Z DEBUG wstunnel::protocols::tcp::server: Connected to tcp endpoint XXX.XXX.XXX.XXX:8443, aborted all other connection attempts
2026-05-21T14:12:26.555064Z  INFO wstunnel::protocols::tls::server: Doing TLS handshake using SNI IpAddress(V4(Ipv4Addr([XXX,XXX,XXX,XXX]))) with the server XXX.XXX.XXX.XXX:8443
2026-05-21T14:12:26.555076Z DEBUG rustls::client::hs: No cached session for IpAddress(V4(Ipv4Addr([XXX,XXX,XXX,XXX])))
2026-05-21T14:12:26.555081Z DEBUG rustls::client::hs: Not resuming any session
2026-05-21T14:12:26.621693Z DEBUG rustls::client::hs: Using ciphersuite TLS13_AES_256_GCM_SHA384
2026-05-21T14:12:26.621720Z DEBUG rustls::client::tls13: Not resuming
2026-05-21T14:12:26.621816Z DEBUG rustls::client::tls13: TLS1.3 encrypted extensions: ServerExtensions { selected_protocol: SingleProtocolName(ProtocolName(687474702f312e31)), unknown_extensions: {}, .. }
2026-05-21T14:12:26.621824Z DEBUG rustls::client::hs: ALPN protocol is Some(b"http/1.1")
2026-05-21T14:12:26.621931Z DEBUG tunnel{id="019e4ae1-6714-70a0-9e6a-5b28c74d1f79" remote="[::]:8001"}: wstunnel::tunnel::transport::websocket: with HTTP upgrade request Request { method: GET, uri: /htazCc4nNc5kDH8f4Q.......................Zq4JNoycsW/events, version: HTTP/1.1, headers: {"host": "XXX.XXX.XXX.XXX:8443", "upgrade": "websocket", "connection": "upgrade", "sec-websocket-key": "2TdWMcd2DCgakDmTp398Og==", "sec-websocket-version": "13", "sec-websocket-protocol": "v1, authorization.bearer.eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjAxOWU0YWUxLTY3MTQtNzBhMC0.............kMWY3OSIsInAiOiJSZXZlcnNlVGNwIiwiciI6Ils6Ol0iLCJycCI6ODAwMX0.XNErq3eOcxDr8HPDRrRS57A5X_ZN2v3tKPxxYKpWOl4"}, body: Empty }
2026-05-21T14:12:28.848539Z DEBUG tunnel{id="019e4ae1-6714-70a0-9e6a-5b28c74d1f79" remote="[::]:8001"}: wstunnel::tunnel::client::client: Server response: Parts { status: 101, version: HTTP/1.1, headers: {"connection": "upgrade", "upgrade": "websocket", "sec-websocket-accept": "dj6AycxJ4jFAbcN/skRbmreD2Fc=", "sec-websocket-protocol": "v1", "date": "Thu, 21 May 2026 14:12:28 GMT"} }
2026-05-21T14:12:28.848560Z  INFO tunnel{id="019e4ae1-6714-70a0-9e6a-5b28c74d1f79" remote="[::]:8001"}: wstunnel::protocols::tcp::server: Opening TCP connection to localhost:8000
2026-05-21T14:12:28.848632Z DEBUG wstunnel::protocols::tcp::server: Connecting to [::1]:8000
2026-05-21T14:12:28.848730Z DEBUG tunnel{id="019e4ae1-6714-70a0-9e6a-5b28c74d1f79" remote="[::]:8001"}: wstunnel::protocols::tcp::server: Cannot connect to tcp endpoint [::1]:8000 reason Connection refused (os error 111)
2026-05-21T14:12:29.099667Z DEBUG wstunnel::protocols::tcp::server: Connecting to 127.0.0.1:8000
2026-05-21T14:12:29.099797Z DEBUG tunnel{id="019e4ae1-6714-70a0-9e6a-5b28c74d1f79" remote="[::]:8001"}: wstunnel::protocols::tcp::server: Connected to tcp endpoint 127.0.0.1:8000, aborted all other connection attempts
2026-05-21T14:12:29.099845Z  INFO wstunnel::protocols::tcp::server: Opening TCP connection to XXX.XXX.XXX.XXX:8443
2026-05-21T14:12:29.099868Z DEBUG wstunnel::protocols::tcp::server: Connecting to XXX.XXX.XXX.XXX:8443
2026-05-21T14:12:29.138506Z DEBUG wstunnel::protocols::tcp::server: Connected to tcp endpoint XXX.XXX.XXX.XXX:8443, aborted all other connection attempts
2026-05-21T14:12:29.138523Z  INFO wstunnel::protocols::tls::server: Doing TLS handshake using SNI IpAddress(V4(Ipv4Addr([XXX,XXX,XXX,XXX]))) with the server XXX.XXX.XXX.XXX:8443
2026-05-21T14:12:29.138536Z DEBUG rustls::client::hs: Resuming session
2026-05-21T14:12:29.179748Z DEBUG rustls::client::hs: Using ciphersuite TLS13_AES_256_GCM_SHA384
2026-05-21T14:12:29.179764Z DEBUG rustls::client::tls13: Resuming using PSK
2026-05-21T14:12:29.179822Z DEBUG rustls::client::tls13: TLS1.3 encrypted extensions: ServerExtensions { selected_protocol: SingleProtocolName(ProtocolName(687474702f312e31)), unknown_extensions: {}, .. }
2026-05-21T14:12:29.179829Z DEBUG rustls::client::hs: ALPN protocol is Some(b"http/1.1")
2026-05-21T14:12:29.179906Z DEBUG tunnel{id="019e4ae1-712b-7da2-ba9a-8151cab1f7ed" remote="[::]:8001"}: wstunnel::tunnel::transport::websocket: with HTTP upgrade request Request { method: GET, uri: /htazCc4nNc5kDH8f4Q.......................Zq4JNoycsW/events, version: HTTP/1.1, headers: {"host": "XXX.XXX.XXX.XXX:8443", "upgrade": "websocket", "connection": "upgrade", "sec-websocket-key": "SUpbl9I/QyHfLB1zAH9sww==", "sec-websocket-version": "13", "sec-websocket-protocol": "v1, authorization.bearer.eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjAxOWU0YWUxLTcxMmItN2RhMi1iYTlhLTgxNTFjYWIxZjdlZCIsInAiOiJSZXZlcnNlVGNwIiwiciI6Ils6Ol0iLCJycCI6ODAwMX0.cnUWWGSd3Ku9-8-QTTbQ6KXh1YAo7CT5bzvPbxU25Co"}, body: Empty }
2026-05-21T14:12:47.606099Z  INFO tunnel{id="019e4ae1-6714-70a0-9e6a-5b28c74d1f79" remote="[::]:8001"}: wstunnel::tunnel::transport::io: Closing local => remote tunnel
2026-05-21T14:12:47.606206Z  INFO tunnel{id="019e4ae1-6714-70a0-9e6a-5b28c74d1f79" remote="[::]:8001"}: wstunnel::tunnel::transport::io: Closing local <= remote tunnel
  • server
2026-05-21T14:12:24.066233Z  INFO wstunnel::embedded_certificate: Generating self-signed tls certificate
2026-05-21T14:12:24.110394Z  INFO wstunnel: Starting wstunnel server v10.5.5 with config WsServerConfig { socket_so_mark: SoMark { inner: None }, bind: 0.0.0.0:8443, websocket_ping_frequency: Some(30s), timeout_connect: 10s, websocket_mask_frame: false, restriction_config: None, tls: true, remote_server_idle_timeout: 180s, mTLS: false }
2026-05-21T14:12:24.110407Z DEBUG wstunnel: Restriction rules: RestrictionsRules {
   restrictions: [
       RestrictionConfig {
           name: "Allow path prefix XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
           match: [
               PathPrefix(
                   Regex(
                       "^XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX$",
                   ),
               ),
           ],
           allow: [
               Tunnel(
                   AllowTunnelConfig {
                       protocol: [],
                       port: [],
                       host: Regex(
                           "^.*$",
                       ),
                       cidr: [
                           0.0.0.0/0,
                           ::/0,
                       ],
                   },
               ),
               ReverseTunnel(
                   AllowReverseTunnelConfig {
                       protocol: [],
                       port: [],
                       port_mapping: {},
                       cidr: [
                           0.0.0.0/0,
                           ::/0,
                       ],
                       unix_path: Regex(
                           "^.*$",
                       ),
                   },
               ),
           ],
       },
   ],
}
2026-05-21T14:12:24.110471Z  INFO wstunnel::tunnel::server::server: Starting wstunnel server listening on 0.0.0.0:8443
2026-05-21T14:12:26.554304Z  INFO cnx{peer="91.226.253.193:55532"}: wstunnel::tunnel::server::server: Accepting connection
2026-05-21T14:12:26.554445Z  INFO cnx{peer="91.226.253.193:55532"}: wstunnel::tunnel::server::server: Doing TLS handshake
2026-05-21T14:12:26.575858Z DEBUG cnx{peer="91.226.253.193:55532"}: rustls::server::hs: decided upon suite TLS13_AES_256_GCM_SHA384
2026-05-21T14:12:26.576280Z DEBUG cnx{peer="91.226.253.193:55532"}: rustls::server::hs: Chosen ALPN protocol ProtocolName(687474702f312e31)
2026-05-21T14:12:26.618902Z  INFO cnx{peer="91.226.253.193:55532"}:tunnel{id="019e4ae1-6714-70a0-9e6a-5b28c74d1f79" remote="[::]:8001"}: wstunnel::tunnel::server::server: Tunnel accepted due to matched restriction: Allow path prefix XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
2026-05-21T14:12:26.618987Z  INFO cnx{peer="91.226.253.193:55532"}:tunnel{id="019e4ae1-6714-70a0-9e6a-5b28c74d1f79" remote="[::]:8001"}: wstunnel::protocols::tcp::server: Starting TCP server listening cnx on [::]:8001
2026-05-21T14:12:28.804960Z  INFO cnx{peer="91.226.253.193:55532"}:tunnel{id="019e4ae1-6714-70a0-9e6a-5b28c74d1f79" remote="[::]:8001"}: wstunnel::tunnel::server::server: connected to ReverseTcp [::]:8001
2026-05-21T14:12:29.134538Z  INFO cnx{peer="91.226.253.193:40664"}: wstunnel::tunnel::server::server: Accepting connection
2026-05-21T14:12:29.134577Z  INFO cnx{peer="91.226.253.193:40664"}: wstunnel::tunnel::server::server: Doing TLS handshake
2026-05-21T14:12:29.136402Z DEBUG cnx{peer="91.226.253.193:40664"}: rustls::server::hs: decided upon suite TLS13_AES_256_GCM_SHA384
2026-05-21T14:12:29.136553Z DEBUG cnx{peer="91.226.253.193:40664"}: rustls::server::hs: Chosen ALPN protocol ProtocolName(687474702f312e31)
2026-05-21T14:12:29.176693Z  INFO cnx{peer="91.226.253.193:40664"}:tunnel{id="019e4ae1-712b-7da2-ba9a-8151cab1f7ed" remote="[::]:8001"}: wstunnel::tunnel::server::server: Tunnel accepted due to matched restriction: Allow path prefix XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
2026-05-21T14:12:47.563081Z  INFO cnx{peer="91.226.253.193:55532"}:tunnel{id="019e4ae1-6714-70a0-9e6a-5b28c74d1f79" remote="[::]:8001"}: wstunnel::tunnel::transport::io: Closing local => remote tunnel
2026-05-21T14:12:47.563179Z  INFO cnx{peer="91.226.253.193:55532"}:tunnel{id="019e4ae1-6714-70a0-9e6a-5b28c74d1f79" remote="[::]:8001"}: wstunnel::tunnel::transport::io: Closing local <= remote tunnel

Desktop (please complete the following information):

Client/server:

Description:    Ubuntu 24.04.2 LTS
Release:        24.04
Codename:       noble
kernel: 6.8.0-117-generic

Additional context
Without mptcp, wstunnel works fine.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions