From 4674f7d97bfcdab906dc152fbf643330e52fb090 Mon Sep 17 00:00:00 2001 From: Miguel Jacq Date: Mon, 11 Dec 2017 14:53:13 +1100 Subject: [PATCH] Add bridge support (obfs4 or user-supplied) --- onionshare/onion.py | 9 ++++ onionshare/settings.py | 5 +- onionshare_gui/settings_dialog.py | 78 ++++++++++++++++++++++++++++++- share/locale/en.json | 4 ++ share/torrc_template-obfs4 | 27 +++++++++++ 5 files changed, 120 insertions(+), 3 deletions(-) create mode 100644 share/torrc_template-obfs4 diff --git a/onionshare/onion.py b/onionshare/onion.py index 2f79719b..d420692e 100644 --- a/onionshare/onion.py +++ b/onionshare/onion.py @@ -205,6 +205,15 @@ class Onion(object): with open(self.tor_torrc, 'w') as f: f.write(torrc_template) + # Bridge support + if self.settings.get('tor_bridges_use_obfs4'): + f.write('\n') + with open(common.get_resource_path('torrc_template-obfs4')) as o: + for line in o: + f.write(line) + if self.settings.get('tor_bridges_use_custom_bridges'): + f.write(self.settings.get('tor_bridges_use_custom_bridges')) + # Execute a tor subprocess start_ts = time.time() if self.system == 'Windows': diff --git a/onionshare/settings.py b/onionshare/settings.py index 408c8bdc..d262aab8 100644 --- a/onionshare/settings.py +++ b/onionshare/settings.py @@ -60,7 +60,10 @@ class Settings(object): 'systray_notifications': True, 'use_stealth': False, 'use_autoupdate': True, - 'autoupdate_timestamp': None + 'autoupdate_timestamp': None, + 'no_bridges': True, + 'tor_bridges_use_obfs4': False, + 'tor_bridges_use_custom_bridges': '' } self._settings = {} self.fill_in_defaults() diff --git a/onionshare_gui/settings_dialog.py b/onionshare_gui/settings_dialog.py index df806a06..1280b342 100644 --- a/onionshare_gui/settings_dialog.py +++ b/onionshare_gui/settings_dialog.py @@ -194,6 +194,18 @@ class SettingsDialog(QtWidgets.QDialog): self.authenticate_group = QtWidgets.QGroupBox(strings._("gui_settings_authenticate_label", True)) self.authenticate_group.setLayout(authenticate_group_layout) + # Bridges support + self.tor_bridges_no_bridges_radio = QtWidgets.QRadioButton(strings._('gui_settings_tor_bridges_no_bridges_radio_option', True)) + self.tor_bridges_no_bridges_radio.toggled.connect(self.tor_bridges_no_bridges_radio_toggled) + + self.tor_bridges_use_obfs4_radio = QtWidgets.QRadioButton(strings._('gui_settings_tor_bridges_obfs4_radio_option', True)) + self.tor_bridges_use_custom_radio = QtWidgets.QRadioButton(strings._('gui_settings_tor_bridges_custom_radio_option', True)) + self.tor_bridges_use_custom_radio.toggled.connect(self.tor_bridges_use_custom_radio_toggled) + + self.tor_bridges_use_custom_textbox = QtWidgets.QPlainTextEdit() + self.tor_bridges_use_custom_textbox.setPlaceholderText('Bridge [address:port] [identifier]') + self.tor_bridges_use_custom_textbox.hide() + # Test tor settings button self.connection_type_test_button = QtWidgets.QPushButton(strings._('gui_settings_connection_type_test_button', True)) self.connection_type_test_button.clicked.connect(self.test_tor_clicked) @@ -213,10 +225,19 @@ class SettingsDialog(QtWidgets.QDialog): connection_type_group_layout.addWidget(self.connection_type_socket_file_extras) connection_type_group_layout.addWidget(self.connection_type_socks) connection_type_group_layout.addWidget(self.authenticate_group) - connection_type_group_layout.addWidget(self.connection_type_test_button) connection_type_group = QtWidgets.QGroupBox() connection_type_group.setLayout(connection_type_group_layout) + # The Bridges options are not exclusive (enabling Bridges offers obfs4 or custom bridges) + connection_type_bridges_radio_group_layout = QtWidgets.QVBoxLayout() + connection_type_bridges_radio_group_layout.addWidget(self.tor_bridges_no_bridges_radio) + connection_type_bridges_radio_group_layout.addWidget(self.tor_bridges_use_obfs4_radio) + connection_type_bridges_radio_group_layout.addWidget(self.tor_bridges_use_custom_radio) + connection_type_bridges_radio_group_layout.addWidget(self.tor_bridges_use_custom_textbox) + connection_type_bridges_radio_group_layout.addWidget(self.connection_type_test_button) + connection_type_bridges_radio_group = QtWidgets.QGroupBox(strings._("gui_settings_tor_bridges", True)) + connection_type_bridges_radio_group.setLayout(connection_type_bridges_radio_group_layout) + # Buttons self.save_button = QtWidgets.QPushButton(strings._('gui_settings_button_save', True)) self.save_button.clicked.connect(self.save_clicked) @@ -245,6 +266,7 @@ class SettingsDialog(QtWidgets.QDialog): right_col_layout = QtWidgets.QVBoxLayout() right_col_layout.addWidget(connection_type_radio_group) right_col_layout.addWidget(connection_type_group) + right_col_layout.addWidget(connection_type_bridges_radio_group) right_col_layout.addWidget(self.tor_status) right_col_layout.addStretch() @@ -315,6 +337,17 @@ class SettingsDialog(QtWidgets.QDialog): self.authenticate_password_radio.setChecked(True) self.authenticate_password_extras_password.setText(self.old_settings.get('auth_password')) + if self.old_settings.get('no_bridges'): + self.tor_bridges_no_bridges_radio.setChecked(True) + self.tor_bridges_use_obfs4_radio.setChecked(False) + self.tor_bridges_use_custom_radio.setChecked(False) + else: + self.tor_bridges_no_bridges_radio.setChecked(False) + self.tor_bridges_use_obfs4_radio.setChecked(self.old_settings.get('tor_bridges_use_obfs4')) + if self.old_settings.get('tor_bridges_use_custom_bridges'): + self.tor_bridges_use_custom_radio.setChecked(True) + self.tor_bridges_use_custom_textbox.setPlainText(self.old_settings.get('tor_bridges_use_custom_bridges')) + def connection_type_bundled_toggled(self, checked): """ Connection type bundled was toggled. If checked, hide authentication fields. @@ -324,6 +357,31 @@ class SettingsDialog(QtWidgets.QDialog): self.authenticate_group.hide() self.connection_type_socks.hide() + def tor_bridges_no_bridges_radio_toggled(self, checked): + """ + 'No bridges' option was toggled. If checked, enable other bridge options. + """ + if checked: + self.tor_bridges_use_obfs4_radio.setEnabled(True) + self.tor_bridges_use_custom_radio.setEnabled(True) + self.tor_bridges_use_custom_textbox.hide() + + def tor_bridges_use_obfs4_radio_toggled(self, checked): + """ + obfs4 bridges option was toggled. If checked, disable custom bridge options. + """ + if checked: + self.tor_bridges_use_custom_radio.setEnabled(False) + self.tor_bridges_use_custom_textbox.hide() + + def tor_bridges_use_custom_radio_toggled(self, checked): + """ + Custom bridges option was toggled. If checked, show custom bridge options. + """ + if checked: + self.tor_bridges_use_obfs4_radio.setEnabled(False) + self.tor_bridges_use_custom_textbox.show() + def connection_type_automatic_toggled(self, checked): """ Connection type automatic was toggled. If checked, hide authentication fields. @@ -473,7 +531,9 @@ class SettingsDialog(QtWidgets.QDialog): if changed(settings, self.old_settings, [ 'connection_type', 'control_port_address', 'control_port_port', 'socks_address', 'socks_port', - 'socket_file_path', 'auth_type', 'auth_password']): + 'socket_file_path', 'auth_type', 'auth_password', + 'no_bridges', 'tor_bridges_use_obfs4', + 'tor_bridges_use_custom_bridges']): reboot_onion = True @@ -554,6 +614,20 @@ class SettingsDialog(QtWidgets.QDialog): settings.set('auth_password', self.authenticate_password_extras_password.text()) + # Whether we use bridges + if self.tor_bridges_no_bridges_radio.isChecked(): + settings.set('no_bridges', True) + settings.set('tor_bridges_use_obfs4', False) + settings.set('tor_bridges_use_custom_bridges', '') + if self.tor_bridges_use_obfs4_radio.isChecked(): + settings.set('no_bridges', False) + settings.set('tor_bridges_use_obfs4', True) + settings.set('tor_bridges_use_custom_bridges', '') + if self.tor_bridges_use_custom_radio.isChecked(): + settings.set('no_bridges', False) + settings.set('tor_bridges_use_obfs4', False) + settings.set('tor_bridges_use_custom_bridges', self.tor_bridges_use_custom_textbox.toPlainText()) + return settings def closeEvent(self, e): diff --git a/share/locale/en.json b/share/locale/en.json index 0756843e..f853295c 100644 --- a/share/locale/en.json +++ b/share/locale/en.json @@ -90,6 +90,10 @@ "gui_settings_authenticate_cookie_option": "Cookie", "gui_settings_password_label": "Password", "gui_settings_cookie_label": "Cookie path", + "gui_settings_tor_bridges": "Tor Bridge support", + "gui_settings_tor_bridges_no_bridges_radio_option": "Don't use bridges", + "gui_settings_tor_bridges_obfs4_radio_option": "Use obfs4 pluggable transports", + "gui_settings_tor_bridges_custom_radio_option": "Use custom bridges", "gui_settings_button_save": "Save", "gui_settings_button_cancel": "Cancel", "gui_settings_button_help": "Help", diff --git a/share/torrc_template-obfs4 b/share/torrc_template-obfs4 new file mode 100644 index 00000000..306c456c --- /dev/null +++ b/share/torrc_template-obfs4 @@ -0,0 +1,27 @@ +Bridge obfs4 154.35.22.10:80 8FB9F4319E89E5C6223052AA525A192AFBC85D55 cert=GGGS1TX4R81m3r0HBl79wKy1OtPPNR2CZUIrHjkRg65Vc2VR8fOyo64f9kmT1UAFG7j0HQ iat-mode=0 +Bridge obfs4 83.212.101.3:50002 A09D536DD1752D542E1FBB3C9CE4449D51298239 cert=lPRQ/MXdD1t5SRZ9MquYQNT9m5DV757jtdXdlePmRCudUU9CFUOX1Tm7/meFSyPOsud7Cw iat-mode=0 +Bridge obfs4 109.105.109.165:10527 8DFCD8FB3285E855F5A55EDDA35696C743ABFC4E cert=Bvg/itxeL4TWKLP6N1MaQzSOC6tcRIBv6q57DYAZc3b2AzuM+/TfB7mqTFEfXILCjEwzVA iat-mode=1 +Bridge obfs4 154.35.22.11:80 A832D176ECD5C7C6B58825AE22FC4C90FA249637 cert=YPbQqXPiqTUBfjGFLpm9JYEFTBvnzEJDKJxXG5Sxzrr/v2qrhGU4Jls9lHjLAhqpXaEfZw iat-mode=0 +Bridge obfs4 37.218.245.14:38224 D9A82D2F9C2F65A18407B1D2B764F130847F8B5D cert=bjRaMrr1BRiAW8IE9U5z27fQaYgOhX1UCmOpg2pFpoMvo6ZgQMzLsaTzzQNTlm7hNcb+Sg iat-mode=0 +Bridge obfs4 154.35.22.9:443 C73ADBAC8ADFDBF0FC0F3F4E8091C0107D093716 cert=gEGKc5WN/bSjFa6UkG9hOcft1tuK+cV8hbZ0H6cqXiMPLqSbCh2Q3PHe5OOr6oMVORhoJA iat-mode=0 +Bridge obfs4 154.35.22.11:443 A832D176ECD5C7C6B58825AE22FC4C90FA249637 cert=YPbQqXPiqTUBfjGFLpm9JYEFTBvnzEJDKJxXG5Sxzrr/v2qrhGU4Jls9lHjLAhqpXaEfZw iat-mode=0 +Bridge obfs4 154.35.22.13:443 FE7840FE1E21FE0A0639ED176EDA00A3ECA1E34D cert=fKnzxr+m+jWXXQGCaXe4f2gGoPXMzbL+bTBbXMYXuK0tMotd+nXyS33y2mONZWU29l81CA iat-mode=0 +Bridge obfs4 154.35.22.10:443 8FB9F4319E89E5C6223052AA525A192AFBC85D55 cert=GGGS1TX4R81m3r0HBl79wKy1OtPPNR2CZUIrHjkRg65Vc2VR8fOyo64f9kmT1UAFG7j0HQ iat-mode=0 +Bridge obfs4 154.35.22.9:80 C73ADBAC8ADFDBF0FC0F3F4E8091C0107D093716 cert=gEGKc5WN/bSjFa6UkG9hOcft1tuK+cV8hbZ0H6cqXiMPLqSbCh2Q3PHe5OOr6oMVORhoJA iat-mode=0 +Bridge obfs4 192.99.11.54:443 7B126FAB960E5AC6A629C729434FF84FB5074EC2 cert=VW5f8+IBUWpPFxF+rsiVy2wXkyTQG7vEd+rHeN2jV5LIDNu8wMNEOqZXPwHdwMVEBdqXEw iat-mode=0 +Bridge obfs4 154.35.22.13:16815 FE7840FE1E21FE0A0639ED176EDA00A3ECA1E34D cert=fKnzxr+m+jWXXQGCaXe4f2gGoPXMzbL+bTBbXMYXuK0tMotd+nXyS33y2mONZWU29l81CA iat-mode=0 +Bridge obfs4 85.31.186.26:443 91A6354697E6B02A386312F68D82CF86824D3606 cert=PBwr+S8JTVZo6MPdHnkTwXJPILWADLqfMGoVvhZClMq/Urndyd42BwX9YFJHZnBB3H0XCw iat-mode=0 +Bridge obfs4 38.229.33.83:80 0BAC39417268B96B9F514E7F63FA6FBA1A788955 cert=VwEFpk9F/UN9JED7XpG1XOjm/O8ZCXK80oPecgWnNDZDv5pdkhq1OpbAH0wNqOT6H6BmRQ iat-mode=1 +Bridge obfs4 154.35.22.11:16488 A832D176ECD5C7C6B58825AE22FC4C90FA249637 cert=YPbQqXPiqTUBfjGFLpm9JYEFTBvnzEJDKJxXG5Sxzrr/v2qrhGU4Jls9lHjLAhqpXaEfZw iat-mode=0 +Bridge obfs4 154.35.22.9:12166 C73ADBAC8ADFDBF0FC0F3F4E8091C0107D093716 cert=gEGKc5WN/bSjFa6UkG9hOcft1tuK+cV8hbZ0H6cqXiMPLqSbCh2Q3PHe5OOr6oMVORhoJA iat-mode=0 +Bridge obfs4 109.105.109.147:13764 BBB28DF0F201E706BE564EFE690FE9577DD8386D cert=KfMQN/tNMFdda61hMgpiMI7pbwU1T+wxjTulYnfw+4sgvG0zSH7N7fwT10BI8MUdAD7iJA iat-mode=2 +Bridge obfs4 38.229.1.78:80 C8CBDB2464FC9804A69531437BCF2BE31FDD2EE4 cert=Hmyfd2ev46gGY7NoVxA9ngrPF2zCZtzskRTzoWXbxNkzeVnGFPWmrTtILRyqCTjHR+s9dg iat-mode=1 +Bridge obfs4 [2001:470:b381:bfff:216:3eff:fe23:d6c3]:443 CDF2E852BF539B82BD10E27E9115A31734E378C2 cert=qUVQ0srL1JI/vO6V6m/24anYXiJD3QP2HgzUKQtQ7GRqqUvs7P+tG43RtAqdhLOALP7DJQ iat-mode=1 +Bridge obfs4 85.17.30.79:443 FC259A04A328A07FED1413E9FC6526530D9FD87A cert=RutxZlu8BtyP+y0NX7bAVD41+J/qXNhHUrKjFkRSdiBAhIHIQLhKQ2HxESAKZprn/lR3KA iat-mode=0 +Bridge obfs4 154.35.22.10:15937 8FB9F4319E89E5C6223052AA525A192AFBC85D55 cert=GGGS1TX4R81m3r0HBl79wKy1OtPPNR2CZUIrHjkRg65Vc2VR8fOyo64f9kmT1UAFG7j0HQ iat-mode=0 +Bridge obfs4 37.218.240.34:40035 88CD36D45A35271963EF82E511C8827A24730913 cert=eGXYfWODcgqIdPJ+rRupg4GGvVGfh25FWaIXZkit206OSngsp7GAIiGIXOJJROMxEqFKJg iat-mode=1 +Bridge obfs4 192.95.36.142:443 CDF2E852BF539B82BD10E27E9115A31734E378C2 cert=qUVQ0srL1JI/vO6V6m/24anYXiJD3QP2HgzUKQtQ7GRqqUvs7P+tG43RtAqdhLOALP7DJQ iat-mode=1 +Bridge obfs4 154.35.22.12:80 00DC6C4FA49A65BD1472993CF6730D54F11E0DBB cert=N86E9hKXXXVz6G7w2z8wFfhIDztDAzZ/3poxVePHEYjbKDWzjkRDccFMAnhK75fc65pYSg iat-mode=0 +Bridge obfs4 85.31.186.98:443 011F2599C0E9B27EE74B353155E244813763C3E5 cert=ayq0XzCwhpdysn5o0EyDUbmSOx3X/oTEbzDMvczHOdBJKlvIdHHLJGkZARtT4dcBFArPPg iat-mode=0 +Bridge obfs4 154.35.22.12:4304 00DC6C4FA49A65BD1472993CF6730D54F11E0DBB cert=N86E9hKXXXVz6G7w2z8wFfhIDztDAzZ/3poxVePHEYjbKDWzjkRDccFMAnhK75fc65pYSg iat-mode=0 +UseBridges 1