Add Obfuscation features support and udp over tcp obfuscator on Linux and Android#11275
Add Obfuscation features support and udp over tcp obfuscator on Linux and Android#11275encrypt94 wants to merge 49 commits into
Conversation
cbd6d7e to
ba41012
Compare
|
I've had kind of a love/hate relationship with building rust binaries over the years, but this might be a good case for splitting the obfuscator into a standalone binary that can be invoked by the daemon as needed rather than baking it into the client. The obfuscator should only ever operate on unprivileged information, should require no root permissions, and it probably has a pretty heavy workload given that it needs to live in the packet processing loop. QProcess * obfuscator = new QProcess(this);
QStringList args;
args << "--method" << "lwo";
args << "--pubkey" << config.m_serverPublicKey;
args << "--server" << config.m_serverIpv4AddrIn;
obfuscator->start("/usr/bin/mozillavpn-obfuscator", args);
connect(obfuscator, &QProcess::started, this, &Example::handleObfuscatorStarted);
connect(obfuscator, &QProcess::finished, this, &Example::handleObfuscatorFinished); |
ba41012 to
6b6f676
Compare
5eb093d to
dbfe054
Compare
5005e81 to
ef8ab9b
Compare
…nder privacy features
…hevron is more consistent with the rest of the view
…wn is reset when obfuscation is enabled or changed
…ite users to enable obfuscation or use a different obfuscation method
143cfd0 to
0f2aee9
Compare
| add_go_library(netfilter ${CMAKE_SOURCE_DIR}/linux/netfilter/netfilter.go) | ||
| target_link_libraries(mozillavpn PRIVATE netfilter) | ||
|
|
||
| # Add the obfuscator binary |
There was a problem hiding this comment.
Is there a reason why we can't use the obfuscator on Flatpaks? Or is that work for a future PR?
There was a problem hiding this comment.
planned for a future PR!
| obfuscationShadowsocksTitle: | ||
| value: Shadowsocks | ||
| comment: Shadowsocks is a protocol name, it should NOT be translated. | ||
| obfuscationShadowsocksBody: May help bypass restrictive or heavily filtered networks, and could work when all other approaches do not. |
There was a problem hiding this comment.
Compared to the other obfuscation methods, this text does little to explain what Shadowsocks does, it reads more as a generic recommendation to use it rather than any kind of technical explanation.
| lineHeight: MZTheme.theme.labelLineHeight | ||
| wrapMode: Text.Wrap | ||
| color: MZTheme.colors.fontColor | ||
| opacity: enabled ? 1 : 0.5 |
There was a problem hiding this comment.
I'd rather change the color than add opacity - we've run into issues before, as it looks different depending on the background color.
We could create a fontColorMuted, similar to how we use fontColorInvertedMuted.
| // MZTextBlock | ||
| Text { | ||
| color: MZTheme.colors.fontColor | ||
| opacity: enabled ? 1 : 0.5 |
There was a problem hiding this comment.
Same as above - would prefer a color rather than opacity
| bodyText: This server location is temporarily unavailable. Choose a new location. | ||
| bodyText1: | ||
| value: This server location is temporarily unavailable. | ||
| comment: First part of the server unavailable modal body. Followed by bodyText2NoObfuscation when obfuscation is disabled, or bodyText2Obfuscation when obfuscation is enabled. |
There was a problem hiding this comment.
Please don't use this approach. You end up with 3 strings and poorer localizability, instead of 2 full strings.
This server location is temporarily unavailable. Choose a new location or try a different obfuscation method.This server location is temporarily unavailable. Choose a new location or try to enable obfuscation.
| bodyText: This server location is temporarily unavailable. Please open the app to choose a new location. | ||
| bodyText1: | ||
| value: This server location is temporarily unavailable. | ||
| comment: First part of the server unavailable notification. Followed by bodyText2NoObfuscation when obfuscation is disabled, or bodyText2Obfuscation when obfuscation is enabled. |
There was a problem hiding this comment.
Same here, use 2 full sentences.
…acing in top warning as suggested in review
| // The exit hop never needs an obfuscator, assign the empty obfuscator to | ||
| // allow changing of the obfuscation method on server switch. | ||
| if (config.m_hopType != InterfaceConfig::MultiHopExit) { | ||
| m_obfuscator = std::move(obfuscator); |
There was a problem hiding this comment.
When m_obfuscator is assigned and updatePeer(peerConfig) is called later, what happens if updatePeer fails, e.g. because of network error? would it be safer to call updatePeer first and move obfuscator if that succeeds?
e11d496 to
0b78fd5
Compare
| sudo mk-build-deps --tool 'apt-get -y -o Debug::pkgProblemResolver=yes --no-install-recommends' \ | ||
| --install --remove $MK_BUILD_DEPS_ARGS "$(pwd)/mozillavpn-source/debian/control" | ||
|
|
||
| # /usr/bin/cargo and /usr/bin/rustc may be installed as cargo-<version> and rustc-<version> |
There was a problem hiding this comment.
Is this still necessary after the update to debian/rules for Rust 1.91?
Description
This PR adds support for obfuscation features and udp over tcp obfuscators.
A new "Obfuscation" option in "Privacy Features" , allows users to configure the following obfuscation features when available on the platform (the menu item will be hidden if a feature is not available.)
CONNECT-UDPThis menu lets users select the
ObfuscationPolicyto use. An obfuscation policy can specify a port selection, an obfuscation method, or a combination of both.SettingsHolder::ObfuscationPolicyis converted toServer::ObfuscationMethodinControllerandServerData. This allows the server selection logic to be obfuscation method aware.When obfuscation is turned on or changed, servers that were previously unreachable may become available again so this action triggers a reset on all server in cooldown.
In the unlikely event that no server in a city matches the selected obfuscation configuration, a "Server Unavailable" dialog is displayed.
When a server is not available the modal will propose user to enable obfuscation or try a different obfuscation method.
Obfuscators
Obfuscators are implemented in a Rust crate located under the
obfuscators/directory.An obfuscator acts as a local UDP proxy running on a local UDP port, the outbound sockets must be protected to avoid traffic loops.
On Linux (and Windows in the future except for the marking part):
mozilla-obfuscator) installed alongside the daemon.CAP_NET_ADMINprivileges to setSO_MARK.On Android (and likely iOS in a similar way):
VPNActivitystarts the obfuscator.VPNActivitycallsprotecton the obfuscator's sockets.VPNActivityrewrites the local port in the configuration.This architecture was chosen because most of the libraries required to implement obfuscation protocols are available in the Rust ecosystem: UDP-over-TCP, Shadowsocks, and QUIC stacks.
Impacts on the rust build bits:
add_rust_binaryinrustlang.cmakeand refactoredadd_rust_libraryto split out shared partsudp-over-tcprequires rust >= 1.87debian:bookwormso is now installed using rustup inlinux-qt6-buildUI
When Obfuscation features are enabled, a “Obfuscation is on” label appears below the timer.


A new Obfuscation menu is available in Settings > Privacy Features.
When Anti-Censorship features are available on the platform, a radio will be displayed in the menu with name and brief description


Disabled


Help text

Server unavailable dialog and notification show when obfuscation is enabled


Server unavailable dialog and notification show when obfuscation is not enabled


Reference
VPN-7588 - Create generic obfuscation interface for anti censorship features
VPN-7566 - Create anti censorship features menu
VPN-7582 - Implement UDP over TCP on Linux
VPN-7583 - Implement UDP over TCP on Android
Checklist