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

VPN-6626: Install socks proxy as a service #9952

Merged
merged 24 commits into from
Nov 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
9e0c42b
Add curlpipe tool to test named pipe support on Windows
oskirby Oct 11, 2024
92d8bf2
Add code to set our own firewall rules
oskirby Oct 11, 2024
2cc7f04
Implement windows service thread
oskirby Oct 11, 2024
a335462
Add file logging when started as a service
oskirby Oct 11, 2024
8263cfe
Some debugging of service startup
oskirby Oct 11, 2024
686628e
Install the socks proxy as a Windows service
oskirby Oct 11, 2024
52ccc15
Split log levels (always write debug to file)
oskirby Oct 11, 2024
9d10a3a
Add logfile option to enable logging manually
oskirby Oct 11, 2024
6072d13
Attack of the killer lint
oskirby Oct 11, 2024
7543007
Even more lint!
oskirby Oct 11, 2024
413bfc7
Fix Linux compile fail
oskirby Oct 11, 2024
26cd711
Fix windows include ordering
oskirby Oct 11, 2024
f4b7a3a
Try again to make the linter happy
oskirby Oct 12, 2024
946dbd5
Add WFP policy to restrict proxy access only to browsers
oskirby Nov 1, 2024
7ab602e
Split windows firewall stuff into its own class
oskirby Nov 1, 2024
8682050
Install socksproxy as a systemd service
oskirby Oct 25, 2024
a9fa489
Install/enable/start proxy service on debian installation
oskirby Oct 25, 2024
9cb8b16
Add proxy service assets to RPM package too
oskirby Oct 25, 2024
83ef667
O Glorious Lint!
oskirby Nov 1, 2024
ef650c0
Automatically start proxy on installation
oskirby Nov 1, 2024
a6da57a
Add a WinFwPolicy::create() method to handle WFP setup failure
oskirby Nov 13, 2024
0b19b8b
Make proxy systemd installation optional
oskirby Nov 13, 2024
359750b
Some lint
oskirby Nov 13, 2024
bc47fd9
Don't install systemd service in containerized environment
oskirby Nov 13, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 26 additions & 6 deletions extension/socks5proxy/bin/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

qt_add_executable(socksproxy
main.cpp
verboselogger.cpp
verboselogger.h
sockslogger.cpp
sockslogger.h
)

target_link_libraries(socksproxy PUBLIC
Expand All @@ -15,15 +15,23 @@ target_link_libraries(socksproxy PUBLIC
)

if(WIN32)
target_compile_definitions(socksproxy PRIVATE PROXY_OS_WIN)
target_sources(socksproxy PRIVATE
windowsbypass.cpp
windowsbypass.h)
windowsbypass.h
winfwpolicy.cpp
winfwpolicy.h
winsvcthread.cpp
winsvcthread.h
winutils.cpp
winutils.h)
target_link_libraries(socksproxy PRIVATE Iphlpapi.lib)

install(FILES
${CMAKE_CURRENT_BINARY_DIR}/socksproxy.exe
DESTINATION .)
elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
target_compile_definitions(socksproxy PRIVATE PROXY_OS_LINUX)
target_sources(socksproxy PRIVATE
linuxbypass.cpp
linuxbypass.h)
Expand All @@ -32,9 +40,21 @@ elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
pkg_check_modules(LIBCAP REQUIRED IMPORTED_TARGET libcap)
target_link_libraries(socksproxy PRIVATE PkgConfig::LIBCAP)

# TODO: not install that yet.
#install(FILES ${CMAKE_CURRENT_BINARY_DIR}/socksproxy
# DESTINATION ${CMAKE_INSTALL_DATADIR}/socksproxy)
# Install a Systemd service to run the proxy, if supported.
pkg_check_modules(SYSTEMD systemd)
if("${SYSTEMD_FOUND}" EQUAL 1)
pkg_get_variable(SYSTEMD_UNIT_DIR systemd systemdsystemunitdir)
elseif(NOT DEFINED ENV{container})
set(SYSTEMD_UNIT_DIR /lib/systemd/system)
endif()
if(SYSTEMD_UNIT_DIR)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/socksproxy.service.in
${CMAKE_CURRENT_BINARY_DIR}/socksproxy.service)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/socksproxy.service
DESTINATION ${SYSTEMD_UNIT_DIR})
endif()

install(TARGETS socksproxy)
else()
# TODO: This is currently pointless on macos,
# so no point in shipping it.
Expand Down
80 changes: 66 additions & 14 deletions extension/socks5proxy/bin/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,23 @@

#include <QCommandLineParser>
#include <QCoreApplication>
#include <QDir>
#include <QLocalServer>
#include <QRandomGenerator>
#include <QStandardPaths>
#include <QString>
#include <QTcpServer>
#include <QTimer>

#include "socks5.h"
#include "verboselogger.h"
#include "sockslogger.h"

#ifdef __linux__
#if defined(PROXY_OS_LINUX)
# include "linuxbypass.h"
#endif
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
#elif defined(PROXY_OS_WIN)
# include "windowsbypass.h"
# include "winfwpolicy.h"
# include "winsvcthread.h"
#endif

struct CliOptions {
Expand All @@ -27,6 +30,10 @@ struct CliOptions {
QString username = {};
QString password = {};
bool verbose = false;
bool logfile = false;
#if defined(PROXY_OS_WIN)
bool service = false;
#endif
};

static CliOptions parseArgs(const QCoreApplication& app) {
Expand All @@ -48,11 +55,25 @@ static CliOptions parseArgs(const QCoreApplication& app) {
QCommandLineOption passOption({"P", "password"}, "The password", "password");
parser.addOption(passOption);

QCommandLineOption localOption({"l", "local"}, "Local socket name", "name");
#if defined(PROXY_OS_WIN)
QCommandLineOption localOption({"n", "pipe"}, "SOCKS proxy over named pipe",
"name");
#else
QCommandLineOption localOption({"n", "unix"},
"SOCKS proxy over UNIX domain socket", "path");
#endif
parser.addOption(localOption);

QCommandLineOption logfileOption({"l", "logfile"}, "Save logs to file");
parser.addOption(logfileOption);

QCommandLineOption verboseOption({"v", "verbose"}, "Verbose");
parser.addOption(verboseOption);

#if defined(PROXY_OS_WIN)
QCommandLineOption serviceOption({"s", "service"}, "Windows service mode");
parser.addOption(serviceOption);
#endif
parser.process(app);

CliOptions out = {};
Expand All @@ -77,9 +98,19 @@ static CliOptions parseArgs(const QCoreApplication& app) {
if (parser.isSet(localOption)) {
out.localSocketName = parser.value(localOption);
}
if (parser.isSet(logfileOption)) {
out.logfile = true;
}
if (parser.isSet(verboseOption)) {
out.verbose = true;
}
#if defined(PROXY_OS_WIN)
if (parser.isSet(serviceOption)) {
out.service = true;
// Enforce logging when started as a service.
out.logfile = true;
}
#endif
return out;
};

Expand All @@ -95,10 +126,29 @@ int main(int argc, char** argv) {
return 1;
}

auto* logger = new SocksLogger(&app);
logger->setVerbose(config.verbose);
if (config.logfile) {
auto location = QStandardPaths::AppLocalDataLocation;
QDir logdir(QStandardPaths::writableLocation(location));
logger->setLogfile(logdir.filePath("socksproxy.log"));
}

#if defined(PROXY_OS_WIN)
if (config.service) {
WinSvcThread* svc = new WinSvcThread("Mozilla VPN Proxy");
svc->start();
}
#endif

Socks5* socks5;
if (!config.localSocketName.isEmpty()) {
QLocalServer* server = new QLocalServer();
QLocalServer* server = new QLocalServer(&app);
QObject::connect(&app, &QCoreApplication::aboutToQuit, server,
&QLocalServer::close);

socks5 = new Socks5(server);
server->setSocketOptions(QLocalServer::WorldAccessOption);
if (server->listen(config.localSocketName)) {
qDebug() << "Starting on local socket" << server->fullServerName();
} else if ((server->serverError() == QAbstractSocket::AddressInUseError) &&
Expand All @@ -112,24 +162,26 @@ int main(int argc, char** argv) {
return 1;
}
} else {
QTcpServer* server = new QTcpServer();
QTcpServer* server = new QTcpServer(&app);
QObject::connect(&app, &QCoreApplication::aboutToQuit, server,
&QTcpServer::close);

socks5 = new Socks5(server);
if (server->listen(config.addr, config.port)) {
qDebug() << "Starting on port" << config.port;
qDebug() << "Starting on port" << server->serverPort();
} else {
qWarning() << "Unable to listen to the proxy port" << config.port;
return 1;
}
}
QObject::connect(socks5, &Socks5::incomingConnection, logger,
&SocksLogger::incomingConnection);

if (config.verbose) {
new VerboseLogger(socks5);
}

#ifdef __linux__
#if defined(PROXY_OS_LINUX)
new LinuxBypass(socks5);
#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
#elif defined(PROXY_OS_WIN)
new WindowsBypass(socks5);
WinFwPolicy::create(socks5);
#endif

return app.exec();
Expand Down
Loading
Loading