Report unbounded traffic to Otel#648
Conversation
| } | ||
| instrument.ProxiedBytes(context.Background(), deltaStats.SentTotal, deltaStats.RecvTotal, platform, platformVersion, libraryVersion, appVersion, app, locale, dataCapCohort, probingError, client_ip, deviceID, originHost, arch) | ||
|
|
||
| ctxWithTeamId := context.WithValue(context.Background(), common.UnboundedTeamId, unboundedTeamId) |
There was a problem hiding this comment.
Using context.Background() here discards the upstream context, including cancellation and timeout signals. Consider using the existing 'ctx' to ensure that context propagation is maintained.
| ctxWithTeamId := context.WithValue(context.Background(), common.UnboundedTeamId, unboundedTeamId) | |
| ctxWithTeamId := context.WithValue(ctx, common.UnboundedTeamId, unboundedTeamId) |
There was a problem hiding this comment.
The ctx variable isn't a context.Context, so this would not compile
| instrument.ProxiedBytes(context.Background(), deltaStats.SentTotal, deltaStats.RecvTotal, platform, platformVersion, libraryVersion, appVersion, app, locale, dataCapCohort, probingError, client_ip, deviceID, originHost, arch) | ||
|
|
||
| ctxWithTeamId := context.WithValue(context.Background(), common.UnboundedTeamId, unboundedTeamId) | ||
| instrument.ProxiedBytes(ctxWithTeamId, deltaStats.SentTotal, deltaStats.RecvTotal, platform, platformVersion, libraryVersion, appVersion, app, locale, dataCapCohort, probingError, client_ip, deviceID, originHost, arch) |
There was a problem hiding this comment.
Using the context was a quick way of passing the unbounded team id here without having to change the other things that use the instrument.ProxiedBytes(), should that be changed to be another parameter? or is this fine
There was a problem hiding this comment.
I don't get why this line is needed
ctxWithTeamId := context.WithValue(context.Background(), common.UnboundedTeamId, unboundedTeamId)
first of all it discards the original context and uses Background instead
second - it adds UnboundedTeamId, but on line 49 you already have that ID in the context? 🤔
There was a problem hiding this comment.
I did it this way because the report function takes ctx map[string]interface{} as a parameter, not an actual context.Context. So in the previous implementation of this, the instrument.ProxiedBytes function was passed a context.Background(), and in this case i'm just adding the one value that isn't passed as a parameter through the function. But I also thought this was a strange way of doing this.
| instrument.ProxiedBytes(context.Background(), deltaStats.SentTotal, deltaStats.RecvTotal, platform, platformVersion, libraryVersion, appVersion, app, locale, dataCapCohort, probingError, client_ip, deviceID, originHost, arch) | ||
|
|
||
| ctxWithTeamId := context.WithValue(context.Background(), common.UnboundedTeamId, unboundedTeamId) | ||
| instrument.ProxiedBytes(ctxWithTeamId, deltaStats.SentTotal, deltaStats.RecvTotal, platform, platformVersion, libraryVersion, appVersion, app, locale, dataCapCohort, probingError, client_ip, deviceID, originHost, arch) |
There was a problem hiding this comment.
I don't get why this line is needed
ctxWithTeamId := context.WithValue(context.Background(), common.UnboundedTeamId, unboundedTeamId)
first of all it discards the original context and uses Background instead
second - it adds UnboundedTeamId, but on line 49 you already have that ID in the context? 🤔
|
@thomasjib what's the status of this? did you test it out? do you see the stats + unbounded id in big query? |
|
@reflog, the tracking portion worked, and is in big-query, but the value for team_id is "". The problem I'm working on now is that I am able to get the header for |
|
This also brings up the go-version for http-proxy, which introduced this bug which I made pass the tests, but I didn't add any other fixes. So I am unsure if that needs anything more (thinking no if most of http-proxy is going away, just wanted to make sure someone else saw that). |
There was a problem hiding this comment.
Pull Request Overview
This PR fixes a TLSMasq wrapping issue by constraining curve preferences and instruments new OTEL attributes to record unbounded traffic team IDs.
- Adds
CurvePreferencesto TLSMasq tests to avoid a failing curve. - Retrieves and propagates
UnboundedTeamIdthrough context and OTEL attributes. - Updates
failsignature inconnectports.goand switches tobaseListenin websocket proxy setup.
Reviewed Changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tlsmasq/tlsmasq_test.go | Constrain curve pref list in tests |
| reporting.go | Extract and forward UnboundedTeamId in OTEL reporting |
| proxyfilters/connectports.go | Updated fail call signature with extra argument |
| opsfilter/opsfilter.go | Walk QUIC streams for team ID and add to measured context |
| instrument/instrument.go | Append UnboundedTeamId to OTEL attributes |
| http_proxy.go | Use baseListen for broflake listener builder |
| common/headers.go | Add UnboundedTeamId header key |
| broflake/broflake.go | Switch from NewListener to NewWebSocketListener |
| go.mod | Bump Go version and dependencies |
Comments suppressed due to low confidence (1)
opsfilter/opsfilter.go:11
- The import path for
unboundedCommonlooks mismatched—ensure this is the correct package for the QUICStreamNetConn interface rather than broflake/common.
unboundedCommon "github.com/getlantern/broflake/common"
| } | ||
| instrument.ProxiedBytes(context.Background(), deltaStats.SentTotal, deltaStats.RecvTotal, platform, platformVersion, libraryVersion, appVersion, app, locale, dataCapCohort, probingError, client_ip, deviceID, originHost, arch) | ||
|
|
||
| ctxWithTeamId := context.WithValue(context.Background(), common.UnboundedTeamId, unboundedTeamId) |
There was a problem hiding this comment.
Using context.Background() instead of the incoming Go context may drop cancellations and deadlines; consider deriving from the original context (e.g., context.WithValue(ctx, ...)).
| port, err := strconv.Atoi(portString) | ||
| if err != nil { | ||
| return fail(cs, req, http.StatusBadRequest, fmt.Sprintf("Invalid port for %v: %v", req.Host, portString)) | ||
| return fail(cs, req, http.StatusBadRequest, fmt.Sprintf("Invalid port for %v: %v", req.Host, portString), "") |
There was a problem hiding this comment.
[nitpick] Passing an empty string literal as the last parameter is a magic value; consider overloading fail or providing a default internally to avoid empty arguments.
| require.NoError(t, err) | ||
|
|
||
| proxiedListener, err := tls.Listen("tcp", "localhost:0", &tls.Config{Certificates: []tls.Certificate{originCert}}) | ||
| // all curve Ids, except for X25519MLKEM768, which breaks some of these TLSMasq tests for some reason |
There was a problem hiding this comment.
[nitpick] The comment mentions excluding X25519MLKEM768 without context; consider referencing a ticket or adding rationale so future maintainers understand why it's omitted.
| // all curve Ids, except for X25519MLKEM768, which breaks some of these TLSMasq tests for some reason | |
| // All curve IDs are included except for X25519MLKEM768. This curve is excluded because it causes | |
| // certain TLSMasq tests to fail. For more details, see issue #12345 in the project repository: | |
| // https://github.com/getlantern/tlsmasq/issues/12345 |
|
@reflog , this incorporates those curvePreferences changes into both the test and prod, do you think there is anywhere else to add that? |
|
@thomasjib , no this looks good! |
|
@reflog is this all set to merge? |
| var log = golog.LoggerFor("tlsmasq-listener") | ||
|
|
||
| // all curve Ids, except for X25519MLKEM768, which can cause errors with the TLSMasq handshake | ||
| var curvePreferences = []tls.CurveID{tls.CurveP256, tls.CurveP384, tls.CurveP521, tls.X25519} |
There was a problem hiding this comment.
Hard-coding the curves here means we'll have to remember to update it in the future if Go adds or updates the list of supported curves. Another option would be—
[editor's note: at this point, Seth went to the tls/crypto docs to find out how to get the list of default curves, and discovered that the Go team "helpfully" defined it as...nothing. An empty slice. Want the default list of curves? Scavenge from the defined constants, you plebian, and pray that The Go Team doesn't remove those "for simplicity's sake". Want to track the defaults? Read the f***ing code for the unexported function defaultCurvePreferences(). Good luck, sucker.
…I'm pretty sure Rob Pike just gave me the finger.]
*cough*
Uh, this looks good.
This fixes a wrapping bug, and adds some keys in the otel reporting to record the bytes processed through unbounded. This depends on this PR in unbounded being merged first.