Skip to content

feat: support HTTP CONNECT proxy connection for built-in MQTT bridge#3531

Merged
jarhodes314 merged 16 commits intothin-edge:mainfrom
jarhodes314:feat/mqtt-proxy-poc
Apr 30, 2025
Merged

feat: support HTTP CONNECT proxy connection for built-in MQTT bridge#3531
jarhodes314 merged 16 commits intothin-edge:mainfrom
jarhodes314:feat/mqtt-proxy-poc

Conversation

@jarhodes314
Copy link
Copy Markdown
Contributor

@jarhodes314 jarhodes314 commented Apr 3, 2025

Proposed changes

Attempts to provide a solution to #3228 using HTTP CONNECT.

Adds support for HTTP CONNECT proxying to the Cumulocity bridge config in the built-in bridge as well as support for websocket connections, so we can use standard HTTPS proxying. Initially intended for enabling a customer to test this solves their issue.

MQTT proxying is only supported with the built-in bridge. If proxying is configured with the mosquitto bridge enabled, a warning will be displayed by tedge connect/tedge-mapper, and the direct connection will not use the proxy (since this matches the behaviour of the bridge we are creating in this instance).

I've tested this locally with go-gost and it works as intended both for MQTT and HTTP.

To enable proxy support:

tedge config set proxy.address http://localhost:8080
tedge config set proxy.username user
tedge config set proxy.password pass
tedge config set proxy.no_proxy "google.com"

Still TODO (now all done):

  • Support tedge connect direct c8y connection
  • Combine scheme and address fields in tedge config
  • Make sure tedge config docs don't refer to Cumulocity
  • Replace unwraps in HTTP proxy configuration with a result-based solution
  • Check the behaviour of HTTP/MQTT proxying with regard to HTTP_PROXY/NO_PROXY environment variables
  • Log proxy settings in the tedge connect output
  • Add a no_proxy configuration to allow users not

Types of changes

  • Bugfix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Improvement (general improvements like code refactoring that doesn't explicitly fix a bug or add any new functionality)
  • Documentation Update (if none of the other choices apply)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)

Paste Link to the issue

Checklist

  • I have read the CONTRIBUTING doc
  • I have signed the CLA (in all commits with git commit -s. You can activate automatic signing by running just prepare-dev once)
  • I ran just format as mentioned in CODING_GUIDELINES
  • I used just check as mentioned in CODING_GUIDELINES
  • I have added tests that prove my fix is effective or that my feature works
  • I have added necessary documentation (if appropriate)

Further comments

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 3, 2025

@jarhodes314 jarhodes314 temporarily deployed to Test Pull Request April 4, 2025 13:34 — with GitHub Actions Inactive
@jarhodes314 jarhodes314 changed the title PoC proxy connection for MQTT bridge PoC proxy/websocket connection for built-in MQTT bridge Apr 4, 2025
@jarhodes314 jarhodes314 force-pushed the feat/mqtt-proxy-poc branch from 774416a to 748ab85 Compare April 4, 2025 13:45
@jarhodes314 jarhodes314 force-pushed the feat/mqtt-proxy-poc branch from 748ab85 to 6284826 Compare April 4, 2025 13:45
@jarhodes314 jarhodes314 force-pushed the feat/mqtt-proxy-poc branch from 6284826 to 0d9a6d5 Compare April 17, 2025 14:54
@jarhodes314 jarhodes314 force-pushed the feat/mqtt-proxy-poc branch from 0d9a6d5 to 21a1269 Compare April 23, 2025 14:18
@jarhodes314 jarhodes314 force-pushed the feat/mqtt-proxy-poc branch from 21a1269 to 8092d8a Compare April 23, 2025 14:23
@jarhodes314 jarhodes314 changed the title PoC proxy/websocket connection for built-in MQTT bridge PoC HTTP CONNECT proxy connection for built-in MQTT bridge Apr 23, 2025
@reubenmiller reubenmiller changed the title PoC HTTP CONNECT proxy connection for built-in MQTT bridge feat: support HTTP CONNECT proxy connection for built-in MQTT bridge Apr 24, 2025
@jarhodes314 jarhodes314 temporarily deployed to Test Pull Request April 24, 2025 11:46 — with GitHub Actions Inactive
@jarhodes314 jarhodes314 marked this pull request as ready for review April 24, 2025 11:50
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 24, 2025

Robot Results

✅ Passed ❌ Failed ⏭️ Skipped Total Pass % ⏱️ Duration
626 0 3 626 100 1h50m30.815964s

@reubenmiller
Copy link
Copy Markdown
Contributor

reubenmiller commented Apr 24, 2025

Update There seems to still be some communication that does not go through the proxy. I've pushed a commit (9004271) which adds a system test which also sets iptables rules to block any traffic not coming from the gost proxy (excluding loopback traffic of course).

The problem occurs somewhere within the tedge connect c8y command. If the rules are enabled only after the connection is enabled, then the tedge-mapper-c8y built-in bridge can connect successfully via the proxy.

$ tedge connect c8y
connect to Cumulocity cloud.:
        device id: TST_tweak_piercing_rasp
        cloud profile: <none>
        cloud host: iot.latest.stage.c8y.io:8883
        auth type: Certificate
        certificate file: /etc/tedge/device-certs/tedge-certificate.pem
        cryptoki: false
        bridge: built-in
        service manager: systemd
        mosquitto version: 2.0.11
Creating device in Cumulocity cloud... ✗

I've also been able to partially verify the connection and it seems to be ok though I'm still trying to get a setup which blocks all traffic that does not go through the proxy to confirm all aspects are covered.

Though whilst exploring two things came up:

  1. Add proxy info to the tedge connect c8y output to make it easier to debug

  2. Would it be better to remove the need for proxy.type and just let the user specify the kind of proxy in the proxy.address config?

    If it would be supported then it would make it easier to configure as it only needs one setting. Separating the username password is still ok
    as it allows users to protect that information if necessary.

    tedge config set proxy.address https://127.0.0.1:8080
    
    tedge config set proxy.address http://127.0.0.1:8080
    

@reubenmiller reubenmiller requested a review from a team as a code owner April 25, 2025 07:54
@reubenmiller reubenmiller added the theme:connectivity Generic connectivity related stuff like HTTP proxy etc. label Apr 30, 2025
jarhodes314 and others added 14 commits April 30, 2025 13:15
mappers

Signed-off-by: James Rhodes <jarhodes314@gmail.com>
Signed-off-by: James Rhodes <jarhodes314@gmail.com>
Signed-off-by: reubenmiller <reuben.d.miller@gmail.com>
Signed-off-by: James Rhodes <jarhodes314@gmail.com>
Migrate cloud_root_certs to return a result rather than unwrapping
Use a proxy.address configuration for scheme, host & port together
Log proxy configuration on `tedge connect`

Signed-off-by: James Rhodes <jarhodes314@gmail.com>
Signed-off-by: James Rhodes <jarhodes314@gmail.com>
Signed-off-by: James Rhodes <jarhodes314@gmail.com>
Signed-off-by: James Rhodes <jarhodes314@gmail.com>
Signed-off-by: James Rhodes <jarhodes314@gmail.com>
Copy link
Copy Markdown
Contributor

@reubenmiller reubenmiller left a comment

Choose a reason for hiding this comment

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

Approved. Please wait for a Rust review though.

I'm ok with adding the user documentation in a follow up PR which can be created by someone else.

Signed-off-by: James Rhodes <jarhodes314@gmail.com>
Signed-off-by: James Rhodes <jarhodes314@gmail.com>
Copy link
Copy Markdown
Contributor

@didier-wenzek didier-wenzek left a comment

Choose a reason for hiding this comment

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

Approved. Thank you for this sustained effort. Yet another reason to prefer the builtin bridge!

Comment on lines +636 to +644
auth: match all_or_nothing((
config.proxy.username.clone(),
config.proxy.password.clone(),
))
.map_err(|e| anyhow::anyhow!(e))?
{
Some((username, password)) => rumqttc::ProxyAuth::Basic { username, password },
None => rumqttc::ProxyAuth::None,
},
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.

cargo fmt is sometime confusing. I failed at first to read this as a regular match expression!

@jarhodes314 jarhodes314 added this pull request to the merge queue Apr 30, 2025
Merged via the queue into thin-edge:main with commit 5e543a4 Apr 30, 2025
51 of 52 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

theme:connectivity Generic connectivity related stuff like HTTP proxy etc.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants