Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix statefulness #8

Merged
merged 3 commits into from
Jul 30, 2018
Merged

Fix statefulness #8

merged 3 commits into from
Jul 30, 2018

Conversation

sergeyfrolov
Copy link
Member

@sergeyfrolov sergeyfrolov commented Jul 28, 2018

With last refactoring, that enabled flexible external configs(and ultimately enabled effortless use of auto-generated code for any fingerprint, including recently integrated iOS 11 one), we introduced a regression:
Various connections, using same ClientHelloSpec may share state.

To provide more info on what state was erroneously shared, here are some examples:

  • Shared slice with curves for SupportedCurvesExtension - should only change, if manually changed by user, which I don't think anyone does.
  • List of ALPN values in extensions might be realistically be changed by user(albeit, it shouldn't be! danger! Chrome-like fingerprint without h2 looks weird and sticks out!). Such change would persist for all subsequent usages of same fingerprint spec.
  • SNI, however, does change regularly, and could start defaulting to a wrong thing, but only if not set explicitly with SetSNI.

This PR fixes statefulness by making utls generate a new ClientHelloSpec for each usage of default ClientHelloSpecs. Custom ClientHelloSpecs (which no one uses atm as far as I know), may still share some state, so I added a disclaimer for that to advise users to create a new custom ClientHelloSpec for each UConn.

@sergeyfrolov sergeyfrolov requested a review from bemasc July 28, 2018 23:37
@nikitaborisov
Copy link
Member

This fixes the shared state problem I was seeing in gotapdance

u_parrots.go Outdated
@@ -208,6 +209,7 @@ func (uconn *UConn) applyPresetByID(id ClientHelloID) (err error) {
}

// ApplyPreset should only be used in conjunction with HelloCustom to apply custom specs.
// Separate ClientHelloSpec for each UConn is advised, to avoid state sharing.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this because ApplyPreset modifies p? If so, that could be made explicit here.

Copy link
Member Author

@sergeyfrolov sergeyfrolov Jul 30, 2018

Choose a reason for hiding this comment

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

It doesn't modify state of p anymore.

@@ -250,15 +252,17 @@ func (uconn *UConn) ApplyPreset(p *ClientHelloSpec) error {
uconn.greaseSeed[ssl_grease_extension2] ^= 0x1010
}

hello.CipherSuites = p.CipherSuites
hello.CipherSuites = make([]uint16, len(p.CipherSuites))
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is confusing. Are you deep-copying the input (in which case it's safe to use the same input for many calls) or are you requiring the input to be independent for each call (in which case there's no need to make a copy).

Copy link
Member Author

Choose a reason for hiding this comment

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

The only reliable way to deepcopy all the extensions I found is to add Clone() method to TLSExtension interface. Which I didn't quite want to do.
Current solution simply makes a new preset for built-in parrots. For custom ones, only shared state is pointers and slices in fields of TLSExtensions, which I indeed could be more explicit about.

Copy link
Collaborator

@bemasc bemasc left a comment

Choose a reason for hiding this comment

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

In the long term, I think we should consider creating a richer type for ClientHelloSpec, with explicit setter functions and locking to avoid mutating specs that are in use, but for now this is OK.

@sergeyfrolov sergeyfrolov merged commit 4c28dcf into master Jul 30, 2018
@sergeyfrolov sergeyfrolov deleted the fix-statefulness branch July 30, 2018 18:29
gaukas added a commit that referenced this pull request Nov 1, 2022
* Create go.yml

* adding Build Status badge
adotkhan pushed a commit to Psiphon-Labs/utls that referenced this pull request Dec 10, 2024
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.

3 participants