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

Tor bridges support [Client part] #13290

Merged
merged 40 commits into from
Aug 3, 2022
Merged

Tor bridges support [Client part] #13290

merged 40 commits into from
Aug 3, 2022

Conversation

boocmp
Copy link
Contributor

@boocmp boocmp commented May 11, 2022

Resolves brave/brave-browser#1138

Sec review:

https://github.com/brave/security/issues/858

Desc

  1. Added a new component updater that handles the pluggable transport executables
  2. Added support for configuring pluggable transport via Tor bridges

Submitter Checklist:

  • I confirm that no security/privacy review is needed, or that I have requested one
  • There is a ticket for my issue
  • Used Github auto-closing keywords in the PR description above
  • Wrote a good PR/commit description
  • Squashed any review feedback or "fixup" commits before merge, so that history is a record of what happened in the repo, not your PR
  • Added appropriate labels (QA/Yes or QA/No; release-notes/include or release-notes/exclude; OS/...) to the associated issue
  • Checked the PR locally: npm run test -- brave_browser_tests, npm run test -- brave_unit_tests, npm run lint, npm run gn_check, npm run tslint
  • Ran git rebase master (if needed)

Reviewer Checklist:

  • A security review is not needed, or a link to one is included in the PR description
  • New files have MPL-2.0 license header
  • Adequate test coverage exists to prevent regressions
  • Major classes, functions and non-trivial code blocks are well-commented
  • Changes in component dependencies are properly reflected in gn
  • Code follows the style guide
  • Test plan is specified in PR before merging

After-merge Checklist:

Test Plan:

tor_tp.txt

Settings

  1. Open Privacy & Security

  2. 'Tor Windows' should exist:

    • Private window with Tor
    • Automatically redirect .onion sites
    • Use Bridges
  3. Disabling 'Private window with Tor' should gray other settings

  4. Enabling Use Bridges should expand additional settings

    • Select a built-in bridge
    • Request a bridge from torproject.org
    • Provide a bridge

NOTE: Changing the bridge settings should show 'Apply changes' button.

  1. Built-in bridges:

    • snowflake
    • obfs4
    • meek-azure
  2. Request a bridge:

    • Click on 'Request a New Bridge...' button.
      Request dialog with captcha should be displayed.

    • 'Renew' button should renew the captcha.

    • Providing wrong captcha should renew it.

    • Captcha is case insensitive.

    • Providing right captcha should close dialog and insert bridges credentials in the text area

  3. Provide a bridge

    • If text area is empty the 'Apply changes' button shouldn't appear

Checking bridges:

NOTE: It's useful to open 'brave://tor-internals' and see Logs for activities.

Enable 'Private window with Tor' and launch Tor Window (Alt + Shift + N)

Check brave://components, 'Brave Tor Client Updater' should appear.

  1. Go to settings and enable bridges
    Refresh & Check brave://components, 'Brave Pluggable Transports (OS)' should appear
    Check OS Task manager, new process should start
    'tor-snowflake-brave' for snowflake proxies
    'tor-obfs4-brave' for obfs and meek-azure proxies

  2. Disabling bridges should stop the corresponding process and delete component from Profile.

  3. Changing the bridge settings may change your IP address for sites.

    Open f.e. https://yandex.com/internet and see on IP and region fields.
    After changing the bridge settings the IP may change in a few seconds. (Need to refresh page to see it)

  4. Provide bad bridge (f.e. obfs4 99.124.226.90:9998 8BFDDB7D7D2D4BDD4169170C818B175C6B60F799 cert=fmp+hf7s1QH6Crg+FW39P5KTxy57NCfXs+t1vBrNuYrHGebGtbRrdkKfk+pcgZhBdbrVcw iat-mode=0)
    Open Tor window.
    Tor connection will get stuck and you will see 'Tor connection failed' in 30 seconds.
    Check the 'contact support' link opens page in regular browser (not in the Tor as it was in previous versions)

TP component ids:
windows: dnkcahhmfcanmkjhnjejoomdihffoefm
mac os : einfndjnccmoohcngmlldpmellegjjnk
linux : apfggiafobakjahnkchiecbomjgigkkn

Tor component ids:
windows: cpoalefficncklhjfpglfiplenlpccdb
mac os : cldoidikboihgcjfkhdeidbpclkineef
linux : biahpgbdmdkfgndcmfiipgcebobojjkp

@boocmp boocmp requested a review from a team as a code owner May 11, 2022 11:52
@github-actions github-actions bot added the potential-layer-violation-fixes This PR touches a BUILD.gn file with check_includes=false label May 11, 2022
@boocmp boocmp requested review from iefremov and simonhong May 11, 2022 13:55
@iefremov iefremov requested a review from darkdh May 11, 2022 14:18
@iefremov
Copy link
Contributor

@diracdeltas @fmarier I guess we would need an official security review?

@diracdeltas
Copy link
Member

@diracdeltas @fmarier I guess we would need an official security review?

yes please

@diracdeltas diracdeltas added the CI/run-network-audit Run network-audit label May 11, 2022
static const base::NoDestructor<std::vector<std::string>> kSnowflakeBridges(
{"snowflake 192.0.2.3:1 2B280B23E1107BB62ABFC40DDCC8824814F80A72"});

static const base::NoDestructor<std::vector<std::string>> kObfs4Briges({
Copy link
Member

Choose a reason for hiding this comment

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

where are all these bridge IPs from? not sure if it's worth having the builtins at all because wouldn't they just get blocked soon?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is taken from the Tor browser, but I agree that this is not a very good solution, perhaps we should get a "predefined" list of bridges from a file in the component or from some network api.

Copy link
Member

Choose a reason for hiding this comment

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

If TBB uses these then does that mean that they're not always blocked?

@iefremov
Copy link
Contributor

components/tor/tor_control.cc Outdated Show resolved Hide resolved
components/tor/pref_names.h Show resolved Hide resolved
components/tor/brave_tor_pluggable_transport_updater.cc Outdated Show resolved Hide resolved
components/tor/pref_names.h Outdated Show resolved Hide resolved
components/tor/tor_control.cc Outdated Show resolved Hide resolved
components/tor/tor_profile_service_impl.cc Outdated Show resolved Hide resolved
browser/tor/brave_local_state_browsertest.cc Show resolved Hide resolved

} // namespace

class BraveTorTest : public InProcessBrowserTest {
Copy link
Member

Choose a reason for hiding this comment

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

nice browser test rework

@boocmp boocmp force-pushed the tor_bridge branch 3 times, most recently from ff4795e to 181f4dc Compare May 25, 2022 07:54
@boocmp boocmp requested a review from petemill June 7, 2022 08:12
@boocmp boocmp force-pushed the tor_bridge branch 2 times, most recently from 725ff82 to fd015ba Compare June 14, 2022 07:37
@iefremov
Copy link
Contributor

@petemill ptal

@iefremov iefremov requested a review from darkdh June 15, 2022 18:06
overflow-x: scroll;
}
</style>
<div id="torBridgesControls">
Copy link
Member

@petemill petemill Jun 15, 2022

Choose a reason for hiding this comment

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

Can you please attach screenshots of this (and the dialog and the addition to the privacy section) to the PR description? This is for the purpose of Design (and QA) review.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Video uploaded. (See Test plan section)

Copy link
Member

@petemill petemill left a comment

Choose a reason for hiding this comment

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

This needs some changes for the Settings page, please see specific comments.

In general, we can have the JS class be functional - let it set a state via properties, and have that state be easy to read so that we can see certain events change certain properties (e.g. receive data from server or user -> change specific property). The UI can simply reflect the values of those properties.

sub-label="$i18n{torUseBridgesDesc}" learn-more-url="https://tb-manual.torproject.org/en-US/bridges/"
checked="[[isUsingBridges_]]" on-change="onUseBridgesChange_">
</settings-toggle-button>
<settings-radio-group id="brigdesGroup" no-set-pref selectable-elements="settings-collapse-radio-button"
Copy link
Member

Choose a reason for hiding this comment

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

Seems like we can use <cr-radio-group> here as settings-radio-group just wraps to add pref binding which isn't being used here?

switch (this.$.brigdesGroup.selected) {
case 'useBuiltIn':
this.UpdateUseBridges_(Usage.USE_BUILT_IN)
this.OnBuiltInBridgesSelect_()
Copy link
Member

Choose a reason for hiding this comment

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

A handler (OnBuiltInBridgesSelect_) that is tied to a UI element (builtInBridgesType) event should probably only be called by that event, otherwise the flow can get confusing. Instead try to set a property and use observers.

This particular function (onUsageSelect_) also can be more minimal - just set the relevant properties that the user has changed from the UI, and let the rest of the class properties and observers handle side-effects.

Comment on lines 77 to 88
switch (this.useBridges_) {
case Usage.NOT_USED:
case Usage.USE_BUILT_IN:
this.$.brigdesGroup.selected = 'useBuiltIn'
break
case Usage.USE_REQUESTED:
this.$.brigdesGroup.selected = 'useRequestedBridges'
break
case Usage.USE_PROVIDED:
this.$.brigdesGroup.selected = 'useProvidedBridges'
break
}
Copy link
Member

Choose a reason for hiding this comment

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

Referring to DOM elements from the JS part of the component should be last result. The default pattern should be inverted where DOM attributes are bound to properties in the JS.

Looks like you should provide DOM-bindable properties for:

  • the value for the brigdesGroup (aside: spelling of brigdes bridges)
  • requestedBridges
  • providedBridges

For example (but not limited to):

<settings-radio-group selected={{useBridgesValue_}}
// property
    useBridgesValue_: {
      type: String,
      computed: 'computeUseBridgesValue_(useBridges_)' // useBridgesValue_ observes useBridges_ changes
    },
// ...
// Function
computeUseBridgesValue_() {
    switch (this.useBridges_) {
       case Usage.NOT_USED:
       case Usage.USE_BUILT_IN:
            return 'useBuiltIn'
       case Usage.USE_REQUESTED:
            return 'useRequestedBridges'
       case Usage.USE_PROVIDED:
            return 'useProvidedBridges'
      }
}

note that this example will be different if you want to do 2-way binding for the selected attribute. Then you won't even need to on-change handler.

Comment on lines 94 to 96
this.$.useBuiltIn.expanded = true
this.$.useRequestedBridges.expanded = true
this.$.useProvidedBridges.expanded = true
Copy link
Member

Choose a reason for hiding this comment

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

Can put expanded attribute directly on html element since this is constant and doesn't seem to be changed anywhere

Comment on lines 98 to 101
this.$.providedBridges.oninput = (event) => {
this.providedBridges_ = this.onProvidedBridgesChange_(event)
this.handleChanged_()
}
Copy link
Member

Choose a reason for hiding this comment

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

  1. You don't need reference to DOM element directly, you can set this event in the html
  2. You don't need a custom JS event for this, you can use 2-way data-binding directly to the value html attribute, e.g. <textarea value="{{providedBridges_::input}}". Please see brave_sync_code_dialog.html (and JS) for an example of better data binding and more readable flow of data.


setBridgesConfig_() {
this.loadedConfig_ = this.getCurrentConfig_()
this.$.apply.hidden = true
Copy link
Member

Choose a reason for hiding this comment

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

make this bound to a property

components/tor/tor_utils.h Outdated Show resolved Hide resolved
components/tor/tor_profile_service_impl.cc Outdated Show resolved Hide resolved
components/tor/tor_profile_service_impl.cc Show resolved Hide resolved
@boocmp boocmp force-pushed the tor_bridge branch 2 times, most recently from c913843 to 70d0c37 Compare June 29, 2022 12:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CI/run-network-audit Run network-audit potential-layer-violation-fixes This PR touches a BUILD.gn file with check_includes=false
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add pluggable transports and bridges support for Tor
9 participants