diff --git a/CMakeLists.txt b/CMakeLists.txt index 0561523..eaad8db 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,7 +34,7 @@ set(SOURCE_FILES mainwindow.cpp zjuconnectmode.cpp zjuconnectcontroller/zjuconnectcontroller.cpp - portforwardingwindow/portforwardingwindow.cpp + extrasettingwindow/extrasettingwindow.cpp settingwindow/settingwindow.cpp loginwindow/loginwindow.cpp utils/utils.cpp diff --git a/README.md b/README.md index ad2e71c..5dc4dab 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,7 @@ - [X] 支持 Linux 系统 - [X] 支持手动设置 Proxy Bypass - [ ] 上传 AUR 包 +- [ ] 使用密钥链存储密码等信息 ## 相关项目 diff --git a/portforwardingwindow/portforwardingwindow.cpp b/extrasettingwindow/extrasettingwindow.cpp similarity index 55% rename from portforwardingwindow/portforwardingwindow.cpp rename to extrasettingwindow/extrasettingwindow.cpp index ae2fdb5..4fa2aef 100644 --- a/portforwardingwindow/portforwardingwindow.cpp +++ b/extrasettingwindow/extrasettingwindow.cpp @@ -1,9 +1,9 @@ -#include "portforwardingwindow.h" -#include "ui_portforwardingwindow.h" +#include "extrasettingwindow.h" +#include "ui_extrasettingwindow.h" -PortForwardingWindow::PortForwardingWindow(QDialog *parent) : +ExtraSettingWindow::ExtraSettingWindow(QDialog *parent) : QDialog(parent), - ui(new Ui::PortForwardingWindow) + ui(new Ui::ExtraSettingWindow) { ui->setupUi(this); @@ -20,7 +20,7 @@ PortForwardingWindow::PortForwardingWindow(QDialog *parent) : QStringList tcpPortForwardingList; QStringList udpPortForwardingList; - QStringList portForwardingList = ui->textEdit->toPlainText().split("\n"); + QStringList portForwardingList = ui->forwardTextEdit->toPlainText().split("\n"); for (const auto &forwarding: portForwardingList) { @@ -43,17 +43,38 @@ PortForwardingWindow::PortForwardingWindow(QDialog *parent) : } } - emit applied(tcpPortForwardingList.join(","), udpPortForwardingList.join(",")); + QStringList customDnsList; + + for (const auto& hosts : ui->hostsTextEdit->toPlainText().split("\n")) + { + QStringList hostsItem = hosts.split(" "); + if (hostsItem.size() == 2) + { + customDnsList.append( + hostsItem[1].simplified() + ":" + hostsItem[0].simplified() + ); + } + } + + QStringList customProxyDomainsList = ui->proxyTextEdit->toPlainText().split("\n"); + + emit applied( + tcpPortForwardingList.join(","), + udpPortForwardingList.join(","), + customDnsList.join(","), + customProxyDomainsList.join(","), + ui->extraArgTextEdit->toPlainText().replace("\n", " ") + ); }); } -PortForwardingWindow::~PortForwardingWindow() +ExtraSettingWindow::~ExtraSettingWindow() { delete ui; } -void PortForwardingWindow::setPortForwarding(const QString &tcpPortForwarding, const QString &udpPortForwarding) +void ExtraSettingWindow::setup(const QString& tcpPortForwarding, const QString& udpPortForwarding, const QString& customDns, const QString& customProxyDomains, const QString& extraArguments) { QStringList tcpPortForwardingList = tcpPortForwarding.split(","); @@ -63,7 +84,7 @@ void PortForwardingWindow::setPortForwarding(const QString &tcpPortForwarding, c if (tcpPortForwardingItem.size() == 2) { - ui->textEdit->append( + ui->forwardTextEdit->append( "TCP," + tcpPortForwardingItem[0].simplified() + "," + tcpPortForwardingItem[1].simplified() ); } @@ -77,9 +98,32 @@ void PortForwardingWindow::setPortForwarding(const QString &tcpPortForwarding, c if (udpPortForwardingItem.size() == 2) { - ui->textEdit->append( + ui->forwardTextEdit->append( "UDP," + udpPortForwardingItem[0].simplified() + "," + udpPortForwardingItem[1].simplified() ); } } + + QStringList customDnsList = customDns.split(","); + + for (const auto& hosts : customDnsList) + { + QStringList hostsItem = hosts.split(":"); + + if (hostsItem.size() == 2) + { + ui->hostsTextEdit->append( + hostsItem[1].simplified() + " " + hostsItem[0].simplified() + ); + } + } + + QStringList customProxyDomainsList = customProxyDomains.split(","); + + for (const auto& domain : customProxyDomainsList) + { + ui->proxyTextEdit->append(domain.trimmed()); + } + + ui->extraArgTextEdit->setPlainText(extraArguments); } diff --git a/extrasettingwindow/extrasettingwindow.h b/extrasettingwindow/extrasettingwindow.h new file mode 100644 index 0000000..da19965 --- /dev/null +++ b/extrasettingwindow/extrasettingwindow.h @@ -0,0 +1,30 @@ +#ifndef EXTRASETTINGWINDOW_H +#define EXTRASETTINGWINDOW_H + +#include +#include "ui_extrasettingwindow.h" + +namespace Ui +{ + class ExtraSettingWindow; +} + +class ExtraSettingWindow : public QDialog +{ +Q_OBJECT + +public: + explicit ExtraSettingWindow(QDialog *parent = nullptr); + + ~ExtraSettingWindow() override; + + void setup(const QString &tcpPortForwarding, const QString &udpPortForwarding, const QString &customDns, const QString &customProxyDomains, const QString &extraArguments); + +signals: + void applied(const QString &tcpPortForwarding, const QString &udpPortForwarding, const QString& customDns, const QString& customProxyDomains, const QString& extraArguments); + +private: + Ui::ExtraSettingWindow *ui; +}; + +#endif //EXTRASETTINGWINDOW_H diff --git a/extrasettingwindow/extrasettingwindow.ui b/extrasettingwindow/extrasettingwindow.ui new file mode 100644 index 0000000..f18becb --- /dev/null +++ b/extrasettingwindow/extrasettingwindow.ui @@ -0,0 +1,202 @@ + + + ExtraSettingWindow + + + + 0 + 0 + 509 + 863 + + + + 其他设置 + + + + + + + + + 端口转发 + + + + + + <html><head/><body><p>在下面的输入框内输入端口转发规则,一行一条规则</p><p>例如,在内网主机 10.10.98.98 的 13389 端口上存在 RDP 远程桌面服务(TCP 协议),<br/>需要将其转发到本机 127.0.0.1:9850 使用,规则为:<br/><span style=" font-weight:700;">TCP,127.0.0.1:9850,10.10.98.98:13389</span></p><p>支持的协议:TCP、UDP</p></body></html> + + + true + + + Qt::TextInteractionFlag::LinksAccessibleByMouse|Qt::TextInteractionFlag::TextSelectableByMouse + + + + + + + + Consolas + + + + TCP,127.0.0.1:9850,10.10.98.98:13389 +UDP,127.0.0.1:25565,10.248.98.98:25565 + + + + + + + + + + 自定义 DNS 解析(Hosts) + + + + + + <html><head/><body><p>在下面的输入框内输入解析规则,一行一条规则</p><p>例如,将 google.com 解析为 127.0.0.1,规则为:<br/><span style=" font-weight:700;">127.0.0.1 google.com</span></p></body></html> + + + true + + + Qt::TextInteractionFlag::LinksAccessibleByMouse|Qt::TextInteractionFlag::TextSelectableByMouse + + + + + + + + Consolas + + + + 8.8.8.8 dns.google +127.0.0.1 www.mihoyo.com + + + + + + + + + + 强制 VPN 分流域名 + + + + + + <html><head/><body><p>在下面的输入框内输入强制 VPN 分流规则,一行一条规则</p><p>例如,要将 www.cnki.net 强制走 VPN 分流,规则为:<br/><span style=" font-weight:700;">www.cnki.net</span></p></body></html> + + + true + + + Qt::TextInteractionFlag::LinksAccessibleByMouse|Qt::TextInteractionFlag::TextSelectableByMouse + + + + + + + + Consolas + + + + www.cnki.net + + + + + + + + + + 额外参数 + + + + + + <html><head/><body><p>在下面的输入框内输入额外的内核参数,可以用回车代替空格</p></body></html> + + + true + + + Qt::TextInteractionFlag::LinksAccessibleByMouse|Qt::TextInteractionFlag::TextSelectableByMouse + + + + + + + + Consolas + + + + --version + + + + + + + + + + QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok + + + + + + + + + buttonBox + rejected() + ExtraSettingWindow + reject() + + + 244 + 295 + + + 244 + 158 + + + + + buttonBox + accepted() + ExtraSettingWindow + accept() + + + 244 + 295 + + + 244 + 158 + + + + + diff --git a/mainwindow.h b/mainwindow.h index eb46ba0..70e8e6e 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -9,7 +9,7 @@ #include #include "loginwindow/loginwindow.h" -#include "portforwardingwindow/portforwardingwindow.h" +#include "extrasettingwindow/extrasettingwindow.h" #include "zjuconnectcontroller/zjuconnectcontroller.h" #include "settingwindow/settingwindow.h" diff --git a/portforwardingwindow/portforwardingwindow.h b/portforwardingwindow/portforwardingwindow.h deleted file mode 100644 index 15cb9ec..0000000 --- a/portforwardingwindow/portforwardingwindow.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef PORTFORWARDINGWINDOW_H -#define PORTFORWARDINGWINDOW_H - -#include -#include "ui_portforwardingwindow.h" - -namespace Ui -{ - class PortForwardingWindow; -} - -class PortForwardingWindow : public QDialog -{ -Q_OBJECT - -public: - explicit PortForwardingWindow(QDialog *parent = nullptr); - - ~PortForwardingWindow() override; - - void setPortForwarding(const QString &tcpPortForwarding, const QString &udpPortForwarding); - -signals: - void applied(const QString &tcpPortForwarding, const QString &udpPortForwarding); - -private: - Ui::PortForwardingWindow *ui; -}; - -#endif //PORTFORWARDINGWINDOW_H diff --git a/portforwardingwindow/portforwardingwindow.ui b/portforwardingwindow/portforwardingwindow.ui deleted file mode 100644 index 095f4f8..0000000 --- a/portforwardingwindow/portforwardingwindow.ui +++ /dev/null @@ -1,91 +0,0 @@ - - - PortForwardingWindow - - - - 0 - 0 - 489 - 317 - - - - 端口转发 - - - - - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css"> -p, li { white-space: pre-wrap; } -hr { height: 1px; border-width: 0; } -li.unchecked::marker { content: "\2610"; } -li.checked::marker { content: "\2612"; } -</style></head><body style=" font-family:'Microsoft YaHei UI'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> - - - - - - - <html><head/><body><p>在下面的输入框内输入端口转发规则,一行一条规则</p><p>例如,在内网主机 10.10.98.98 的 13389 端口上存在 RDP 远程桌面服务(TCP 协议),<br/>需要将其转发到本机 127.0.0.1:9850 使用,规则为:<br/><span style=" font-weight:700;">TCP,127.0.0.1:9850,10.10.98.98:13389</span></p><p>例如,在内网主机 10.10.98.98 的 2222 端口上存在 SSH 服务(TCP 协议),<br/>需要将其转发到本机 9852 端口供本机和 LAN 下其他设备使用,规则为:<br/><span style=" font-weight:700;">TCP,0.0.0.0:9852,10.10.98.98:2222</span></p><p>支持的协议:TCP、UDP</p><p>输入后点击确定并应用,断开并重新连接后方可生效</p></body></html> - - - true - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - buttonBox - rejected() - PortForwardingWindow - reject() - - - 244 - 295 - - - 244 - 158 - - - - - buttonBox - accepted() - PortForwardingWindow - accept() - - - 244 - 295 - - - 244 - 158 - - - - - diff --git a/settingwindow/settingwindow.cpp b/settingwindow/settingwindow.cpp index 589a62e..28588ef 100644 --- a/settingwindow/settingwindow.cpp +++ b/settingwindow/settingwindow.cpp @@ -25,70 +25,34 @@ SettingWindow::SettingWindow(QWidget *parent, QSettings *inputSettings) : connect(ui->portForwardingPushButton, &QPushButton::clicked, [&]() { - portForwardingWindow = new PortForwardingWindow(this); - portForwardingWindow->setPortForwarding(tcpPortForwarding, udpPortForwarding); + extraSettingWindow = new ExtraSettingWindow(this); + extraSettingWindow->setup(tcpPortForwarding, udpPortForwarding, customDNS, customProxyDomain, extraArguments); - connect(portForwardingWindow, &PortForwardingWindow::applied, this, - [&](const QString &tcpForwarding, const QString &udpForwarding) - { - tcpPortForwarding = tcpForwarding; - udpPortForwarding = udpForwarding; - }); + connect(extraSettingWindow, &ExtraSettingWindow::applied, this, + [&](const QString& tcpForwarding, const QString& udpForwarding, const QString& customDNS_, const QString& customProxyDomain_, const QString& extraArg) + { + tcpPortForwarding = tcpForwarding; + udpPortForwarding = udpForwarding; + customDNS = customDNS_; + customProxyDomain = customProxyDomain_; + extraArguments = extraArg; + }); - portForwardingWindow->show(); + extraSettingWindow->show(); }); - auto applySettings = [&]() - { - if (settings->value("Common/AutoStart").toBool() != ui->autoStartCheckBox->isChecked()) - Utils::setAutoStart(ui->autoStartCheckBox->isChecked()); - - settings->setValue("Common/Username", ui->usernameLineEdit->text()); - settings->setValue("Common/Password", QString(ui->passwordLineEdit->text().toUtf8().toBase64())); - settings->setValue("Common/AutoStart", ui->autoStartCheckBox->isChecked()); - settings->setValue("Common/ConnectAfterStart", ui->connectAfterStartCheckBox->isChecked()); - settings->setValue("Common/CheckUpdateAfterStart", ui->checkUpdateAfterStartCheckBox->isChecked()); - - settings->setValue("ZJUConnect/ServerAddress", ui->serverAddressLineEdit->text()); - settings->setValue("ZJUConnect/ServerPort", ui->serverPortSpinBox->value()); - settings->setValue("ZJUConnect/DNS", ui->dnsLineEdit->text()); - settings->setValue("ZJUConnect/DNSAuto", ui->dnsAutoCheckBox->isChecked()); - settings->setValue("ZJUConnect/Socks5Port", ui->socks5PortSpinBox->value()); - settings->setValue("ZJUConnect/HttpPort", ui->httpPortSpinBox->value()); - settings->setValue("ZJUConnect/MultiLine", ui->multiLineCheckBox->isChecked()); - settings->setValue("ZJUConnect/ProxyAll", ui->proxyAllCheckBox->isChecked()); - settings->setValue("ZJUConnect/Debug", ui->debugCheckBox->isChecked()); - settings->setValue("ZJUConnect/TcpPortForwarding", tcpPortForwarding); - settings->setValue("ZJUConnect/UdpPortForwarding", udpPortForwarding); - settings->setValue("ZJUConnect/AutoReconnect", ui->autoReconnectCheckBox->isChecked()); - settings->setValue("ZJUConnect/ReconnectTime", ui->reconnectTimeSpinBox->value()); - settings->setValue("ZJUConnect/AutoSetProxy", ui->autoSetProxyCheckBox->isChecked()); - settings->setValue("ZJUConnect/Route", ui->routeCheckBox->isChecked()); - settings->setValue("ZJUConnect/SecondaryDNS", ui->secondaryDnsLineEdit->text()); - settings->setValue("ZJUConnect/ShadowsocksUrl", ui->shadowsocksUrlLineEdit->text()); - settings->setValue("ZJUConnect/SystemProxyBypass", ui->systemProxyBypassLineEdit->text()); - settings->setValue("ZJUConnect/KeepAlive", ui->keepAliveCheckBox->isChecked()); - settings->setValue("ZJUConnect/TunMode", ui->tunCheckBox->isChecked()); - settings->setValue("ZJUConnect/DNSHijack", ui->dnsHijackCheckBox->isChecked()); - settings->setValue("ZJUConnect/OutsideAccess", ui->outsideAccessCheckBox->isChecked()); - settings->setValue("ZJUConnect/SkipDomainResource", ui->skipDomainResourceCheckBox->isChecked()); - - settings->setValue("Common/ConfigVersion", Utils::CONFIG_VERSION); - - settings->sync(); - }; - - connect(ui->buttonBox->button(QDialogButtonBox::Ok), &QPushButton::clicked, [&, applySettings](){ + connect(ui->buttonBox->button(QDialogButtonBox::Ok), &QPushButton::clicked, [&](){ if (!Utils::credentialCheck(ui->usernameLineEdit->text(), ui->passwordLineEdit->text())) return; applySettings(); accept(); }); - connect(ui->buttonBox->button(QDialogButtonBox::Apply), &QPushButton::clicked, [&, applySettings](){ + connect(ui->buttonBox->button(QDialogButtonBox::Apply), &QPushButton::clicked, [&](){ if (!Utils::credentialCheck(ui->usernameLineEdit->text(), ui->passwordLineEdit->text())) return; applySettings(); + loadSettings(); }); connect(ui->resetDefaultPushButton, &QPushButton::clicked, @@ -98,7 +62,8 @@ SettingWindow::SettingWindow(QWidget *parent, QSettings *inputSettings) : if (status == QMessageBox::Ok) { settings->clear(); - settings->sync(); + loadSettings(); + applySettings(); loadSettings(); } }); @@ -156,6 +121,12 @@ SettingWindow::SettingWindow(QWidget *parent, QSettings *inputSettings) : { ui->passwordLineEdit->setEchoMode(state == Qt::Checked ? QLineEdit::Normal : QLineEdit::Password); }); + + connect(ui->totpSecretVisibleCheckBox, &QCheckBox::checkStateChanged, + [&](Qt::CheckState state) + { + ui->totpSecretLineEdit->setEchoMode(state == Qt::Checked ? QLineEdit::Normal : QLineEdit::Password); + }); } SettingWindow::~SettingWindow() @@ -165,41 +136,119 @@ SettingWindow::~SettingWindow() void SettingWindow::loadSettings() { - ui->usernameLineEdit->setText(settings->value("Common/Username", "").toString()); - ui->passwordLineEdit->setText( - QByteArray::fromBase64(settings->value("Common/Password", "").toString().toUtf8()) + ui->configVersionLabel->setText( + "当前配置文件版本:" + QString::number(settings->value("Common/ConfigVersion").toInt()) + + "\n程序配置文件版本:" + QString::number(Utils::CONFIG_VERSION) ); + ui->usernameLineEdit->setText(settings->value("Credential/Username", "").toString()); + ui->passwordLineEdit->setText( + QByteArray::fromBase64(settings->value("Credential/Password", "").toString().toUtf8()) + ); + ui->totpSecretLineEdit->setText(settings->value("Credential/TOTPSecret", "").toString()); ui->autoStartCheckBox->setChecked(settings->value("Common/AutoStart", false).toBool()); ui->connectAfterStartCheckBox->setChecked(settings->value("Common/ConnectAfterStart", false).toBool()); ui->checkUpdateAfterStartCheckBox->setChecked(settings->value("Common/CheckUpdateAfterStart", true).toBool()); + ui->autoSetProxyCheckBox->setChecked(settings->value("Common/AutoSetProxy", false).toBool()); + ui->reconnectTimeSpinBox->setValue(settings->value("Common/ReconnectTime", 1).toInt()); + ui->autoReconnectCheckBox->setChecked(settings->value("Common/AutoReconnect", false).toBool()); + ui->systemProxyBypassLineEdit->setText(settings->value("Common/SystemProxyBypass", "localhost").toString()); + ui->serverAddressLineEdit->setText(settings->value("ZJUConnect/ServerAddress", "vpn.hitsz.edu.cn").toString()); ui->serverPortSpinBox->setValue(settings->value("ZJUConnect/ServerPort", 443).toInt()); ui->dnsLineEdit->setText(settings->value("ZJUConnect/DNS").toString()); ui->dnsAutoCheckBox->setChecked(settings->value("ZJUConnect/DNSAuto", true).toBool()); + ui->secondaryDnsLineEdit->setText(settings->value("ZJUConnect/SecondaryDNS", "").toString()); + ui->dnsTTLSpinBox->setValue(settings->value("ZJUConnect/DNSTTL", 3600).toInt()); ui->socks5PortSpinBox->setValue(settings->value("ZJUConnect/Socks5Port", 11080).toInt()); ui->httpPortSpinBox->setValue(settings->value("ZJUConnect/HttpPort", 11081).toInt()); + ui->shadowsocksUrlLineEdit->setText(settings->value("ZJUConnect/ShadowsocksURL", "").toString()); + ui->dialDirectProxyLineEdit->setText(settings->value("ZJUConnect/DialDirectProxy", "").toString()); + + ui->multiLineCheckBox->setChecked(settings->value("ZJUConnect/MultiLine", false).toBool()); + ui->keepAliveCheckBox->setChecked(settings->value("ZJUConnect/KeepAlive", false).toBool()); + ui->outsideAccessCheckBox->setChecked(settings->value("ZJUConnect/OutsideAccess", false).toBool()); + + ui->skipDomainResourceCheckBox->setChecked(settings->value("ZJUConnect/SkipDomainResource", true).toBool()); + ui->disableServerConfigCheckBox->setChecked(settings->value("ZJUConnect/DisableServerConfig", false).toBool()); ui->proxyAllCheckBox->setChecked(settings->value("ZJUConnect/ProxyAll", false).toBool()); + + ui->zjuDefaultCheckBox->setChecked(settings->value("ZJUConnect/ZJUDefault", false).toBool()); + ui->disableDNSCheckBox->setChecked(settings->value("ZJUConnect/DisableZJUDNS", false).toBool()); ui->debugCheckBox->setChecked(settings->value("ZJUConnect/Debug", false).toBool()); + + ui->tunCheckBox->setChecked(settings->value("ZJUConnect/TunMode", false).toBool()); + ui->routeCheckBox->setChecked(settings->value("ZJUConnect/AddRoute", false).toBool()); + ui->dnsHijackCheckBox->setChecked(settings->value("ZJUConnect/DNSHijack", false).toBool()); + tcpPortForwarding = settings->value("ZJUConnect/TcpPortForwarding", "").toString(); udpPortForwarding = settings->value("ZJUConnect/UdpPortForwarding", "").toString(); - ui->autoReconnectCheckBox->setChecked(settings->value("ZJUConnect/AutoReconnect", false).toBool()); - ui->reconnectTimeSpinBox->setValue(settings->value("ZJUConnect/ReconnectTime", 1).toInt()); - ui->autoSetProxyCheckBox->setChecked(settings->value("ZJUConnect/AutoSetProxy", false).toBool()); - ui->routeCheckBox->setChecked(settings->value("ZJUConnect/Route", false).toBool()); - ui->secondaryDnsLineEdit->setText(settings->value("ZJUConnect/SecondaryDNS", "").toString()); - ui->shadowsocksUrlLineEdit->setText(settings->value("ZJUConnect/ShadowsocksUrl", "").toString()); - ui->systemProxyBypassLineEdit->setText(settings->value("ZJUConnect/SystemProxyBypass", "localhost").toString()); - ui->keepAliveCheckBox->setChecked(settings->value("ZJUConnect/KeepAlive", false).toBool()); - ui->tunCheckBox->setChecked(settings->value("ZJUConnect/TunMode", false).toBool()); - ui->dnsHijackCheckBox->setChecked(settings->value("ZJUConnect/DNSHijack", false).toBool()); - ui->outsideAccessCheckBox->setChecked(settings->value("ZJUConnect/OutsideAccess", false).toBool()); - ui->skipDomainResourceCheckBox->setChecked(settings->value("ZJUConnect/SkipDomainResource", true).toBool()); + customDNS = settings->value("ZJUConnect/CustomDNS", "").toString(); + customProxyDomain = settings->value("ZJUConnect/CustomProxyDomain", "").toString(); + extraArguments = settings->value("ZJUConnect/ExtraArguments", "").toString(); ui->routeCheckBox->setEnabled(ui->tunCheckBox->isChecked()); ui->dnsHijackCheckBox->setEnabled(ui->tunCheckBox->isChecked()); ui->dnsLineEdit->setEnabled(!ui->dnsAutoCheckBox->isChecked()); } + +void SettingWindow::applySettings() +{ + if (settings->value("Common/AutoStart", false).toBool() != ui->autoStartCheckBox->isChecked()) + Utils::setAutoStart(ui->autoStartCheckBox->isChecked()); + + settings->setValue("Credential/Username", ui->usernameLineEdit->text()); + settings->setValue("Credential/Password", QString(ui->passwordLineEdit->text().toUtf8().toBase64())); + settings->setValue("Credential/TOTPSecret", ui->totpSecretLineEdit->text()); + + settings->setValue("Common/AutoStart", ui->autoStartCheckBox->isChecked()); + settings->setValue("Common/ConnectAfterStart", ui->connectAfterStartCheckBox->isChecked()); + settings->setValue("Common/CheckUpdateAfterStart", ui->checkUpdateAfterStartCheckBox->isChecked()); + settings->setValue("Common/AutoSetProxy", ui->autoSetProxyCheckBox->isChecked()); + settings->setValue("Common/ReconnectTime", ui->reconnectTimeSpinBox->value()); + settings->setValue("Common/AutoReconnect", ui->autoReconnectCheckBox->isChecked()); + settings->setValue("Common/SystemProxyBypass", ui->systemProxyBypassLineEdit->text()); + + + settings->setValue("ZJUConnect/ServerAddress", ui->serverAddressLineEdit->text()); + settings->setValue("ZJUConnect/ServerPort", ui->serverPortSpinBox->value()); + settings->setValue("ZJUConnect/DNS", ui->dnsLineEdit->text()); + settings->setValue("ZJUConnect/DNSAuto", ui->dnsAutoCheckBox->isChecked()); + settings->setValue("ZJUConnect/SecondaryDNS", ui->secondaryDnsLineEdit->text()); + settings->setValue("ZJUConnect/DNSTTL", ui->dnsTTLSpinBox->value()); + settings->setValue("ZJUConnect/Socks5Port", ui->socks5PortSpinBox->value()); + settings->setValue("ZJUConnect/HttpPort", ui->httpPortSpinBox->value()); + settings->setValue("ZJUConnect/ShadowsocksURL", ui->shadowsocksUrlLineEdit->text()); + settings->setValue("ZJUConnect/DialDirectProxy", ui->dialDirectProxyLineEdit->text()); + + + settings->setValue("ZJUConnect/MultiLine", ui->multiLineCheckBox->isChecked()); + settings->setValue("ZJUConnect/KeepAlive", ui->keepAliveCheckBox->isChecked()); + settings->setValue("ZJUConnect/OutsideAccess", ui->outsideAccessCheckBox->isChecked()); + + settings->setValue("ZJUConnect/SkipDomainResource", ui->skipDomainResourceCheckBox->isChecked()); + settings->setValue("ZJUConnect/DisableServerConfig", ui->disableServerConfigCheckBox->isChecked()); + settings->setValue("ZJUConnect/ProxyAll", ui->proxyAllCheckBox->isChecked()); + + settings->setValue("ZJUConnect/DisableZJUDNS", ui->disableDNSCheckBox->isChecked()); + settings->setValue("ZJUConnect/ZJUDefault", ui->zjuDefaultCheckBox->isChecked()); + settings->setValue("ZJUConnect/Debug", ui->debugCheckBox->isChecked()); + + settings->setValue("ZJUConnect/TunMode", ui->tunCheckBox->isChecked()); + settings->setValue("ZJUConnect/AddRoute", ui->routeCheckBox->isChecked()); + settings->setValue("ZJUConnect/DNSHijack", ui->dnsHijackCheckBox->isChecked()); + + + settings->setValue("ZJUConnect/TcpPortForwarding", tcpPortForwarding); + settings->setValue("ZJUConnect/UdpPortForwarding", udpPortForwarding); + settings->setValue("ZJUConnect/CustomDNS", customDNS); + settings->setValue("ZJUConnect/CustomProxyDomain", customProxyDomain); + settings->setValue("ZJUConnect/ExtraArguments", extraArguments); + + settings->setValue("Common/ConfigVersion", Utils::CONFIG_VERSION); + + settings->sync(); +} diff --git a/settingwindow/settingwindow.h b/settingwindow/settingwindow.h index fc9329b..2b3f813 100644 --- a/settingwindow/settingwindow.h +++ b/settingwindow/settingwindow.h @@ -4,7 +4,7 @@ #include #include #include "ui_settingwindow.h" -#include "../portforwardingwindow/portforwardingwindow.h" +#include "../extrasettingwindow/extrasettingwindow.h" namespace Ui { @@ -22,15 +22,19 @@ public: private: void loadSettings(); + void applySettings(); Ui::SettingWindow *ui; QSettings *settings; - PortForwardingWindow *portForwardingWindow; + ExtraSettingWindow *extraSettingWindow; QString tcpPortForwarding; QString udpPortForwarding; + QString customDNS; + QString customProxyDomain; + QString extraArguments; }; #endif //SETTINGWINDOW_H diff --git a/settingwindow/settingwindow.ui b/settingwindow/settingwindow.ui index a5fc2fa..09ef5cf 100644 --- a/settingwindow/settingwindow.ui +++ b/settingwindow/settingwindow.ui @@ -7,7 +7,7 @@ 0 0 486 - 456 + 500 @@ -16,15 +16,8 @@ - - - - - QDialogButtonBox::StandardButton::Apply|QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok - - - - + + @@ -32,35 +25,40 @@ 0 - + 通用 - + 保存的信息 - - - - 账号 + + + + Qt::Orientation::Horizontal - + + QSizePolicy::Policy::Preferred + + + + 120 + 0 + + + - - + + + + QLineEdit::EchoMode::Password + - VPN 账号 - - - - - - - 显示密码 + 可选,以通过 TOTP 验证器 @@ -71,6 +69,20 @@ + + + + 账号 + + + + + + + TOTP 密钥 + + + @@ -81,81 +93,22 @@ - - - - Qt::Orientation::Horizontal - - - QSizePolicy::Policy::Preferred - - - - 100 - 20 - - - - - - - - - - - 启动时 - - - - - - 启动后检查更新 - - - - - - - 开机自启动 - - - - - - - Qt::Orientation::Horizontal - - - - 221 - 72 - - - - - - - - 启动后自动连接 - - - - - - - - - - - + - - + + + + VPN 账号 + + + + + @@ -164,7 +117,7 @@ - + Qt::Orientation::Vertical @@ -183,27 +136,170 @@ 配置文件 - + + + + 导出 + + + + + + + 当前配置文件版本:? +程序配置文件版本:? + + + + 恢复默认 - + 导入 - - + + + + + + + 常规 + + + + - 导出 + + + + + + + + + + + + 自动重连(秒) + + + + + + + 开机自启动 + + + + + + + 断线自动重连 + + + + + + false + + + + + + + Qt::Orientation::Horizontal + + + + + + + 与操作系统有关,一般用半角分号;进行分隔 + + + + + + + 自动连接 + + + + + + + 系统代理排除 + + + + + + + 自动检查更新 + + + + + + + 连接服务器后自动设置代理 + + + + + + + + + + + + + + + + + 自动设置系统代理 + + + + + + + 86400 + + + 1 + + + + + + + Qt::Orientation::Horizontal + + + QSizePolicy::Policy::Preferred + + + + 120 + 0 + + + + @@ -211,10 +307,10 @@ - 高级 + 核心 - + @@ -226,6 +322,23 @@ + + + + 忽略服务器配置 + + + + + + + TUN 模式下有效 + + + TUN 模式 + + + @@ -236,6 +349,30 @@ + + + + 忽略域名资源 + + + + + + + 代理全部流量 + + + + + + + TUN 模式下有效 + + + 设置路由(TUN) + + + @@ -249,51 +386,7 @@ - - - - 忽略域名资源 - - - - - - - 连接服务器后自动设置代理 - - - 自动设置系统代理 - - - - - - - 代理全部流量 - - - - - - - TUN 模式下有效 - - - TUN 模式 - - - - - - - TUN 模式下有效 - - - 设置路由(TUN) - - - - + TUN 模式下有效 @@ -303,10 +396,24 @@ - + - 核心调试模式(谨慎开启,日志量过大会导致 UI 崩溃) + 核心调试 + + + + + + + ZJU 默认配置 + + + + + + + 禁用内部 DNS @@ -319,7 +426,7 @@ - + 65535 @@ -329,7 +436,7 @@ - + Qt::Orientation::Horizontal @@ -343,6 +450,13 @@ + + + + 不填则不启用,格式:ss://chiper:password@server:port + + + @@ -357,14 +471,7 @@ - - - - 系统代理排除 - - - - + Qt::Orientation::Vertical @@ -377,14 +484,17 @@ - - - - Shadowsocks 服务器 + + + + 2147483647 + + + 3600 - + SOCKS5 代理端口 @@ -401,17 +511,14 @@ - - - - 86400 - - - 1 + + + + Shadowsocks 服务器 - + 65535 @@ -421,10 +528,10 @@ - - - - 与操作系统有关,一般用半角分号;进行分隔 + + + + HTTP 代理端口 @@ -435,23 +542,10 @@ - - - - 断线自动重连 - - - 启用 - - - false - - - - - - - HTTP 代理端口 + + + + 直连情况下走的代理,支持:socks://... 或 http://... @@ -462,24 +556,17 @@ - + - 设置端口转发 + 其他设置(端口转发、自定义参数等) - - + + - 自动重连时间(秒) - - - - - - - 不填则不启用,格式:ss://chiper:password@server:port + 直连代理 @@ -497,10 +584,24 @@ + + + + DNS TTL(秒) + + + + + + + QDialogButtonBox::StandardButton::Apply|QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok + + + @@ -513,9 +614,6 @@ secondaryDnsLineEdit socks5PortSpinBox httpPortSpinBox - shadowsocksUrlLineEdit - reconnectTimeSpinBox - autoReconnectCheckBox multiLineCheckBox keepAliveCheckBox outsideAccessCheckBox diff --git a/zjuconnectcontroller/zjuconnectcontroller.cpp b/zjuconnectcontroller/zjuconnectcontroller.cpp index 6894550..aa3975f 100644 --- a/zjuconnectcontroller/zjuconnectcontroller.cpp +++ b/zjuconnectcontroller/zjuconnectcontroller.cpp @@ -5,76 +5,52 @@ ZjuConnectController::ZjuConnectController() { zjuConnectProcess = new QProcess(this); - connect(zjuConnectProcess, &QProcess::readyReadStandardOutput, this, [&]() + auto outputProcess = [&](const QString& output) + { + emit outputRead(output); + + if (output.contains("Access is denied.")) + { + emit error(ZJU_ERROR::ACCESS_DENIED); + } + else if (output.contains("listen failed")) + { + emit error(ZJU_ERROR::LISTEN_FAILED); + } + else if (output.contains("Invalid username or password!")) + { + emit error(ZJU_ERROR::INVALID_DETAIL); + } + else if (output.contains("You are trying brute-force login on this IP address.")) + { + emit error(ZJU_ERROR::BRUTE_FORCE); + } + else if (output.contains("Login failed") || output.contains("too many login failures")) + { + emit error(ZJU_ERROR::OTHER_LOGIN_FAILED); + } + else if (output.contains("client setup error")) + { + emit error(ZJU_ERROR::CLIENT_FAILED); + } + else if (output.contains("panic")) + { + emit error(ZJU_ERROR::OTHER); + } + }; + + connect(zjuConnectProcess, &QProcess::readyReadStandardOutput, this, [&, outputProcess]() { QString output = Utils::ConsoleOutputToQString(zjuConnectProcess->readAllStandardOutput()); - emit outputRead(output); - - if (output.contains("Access is denied.")) - { - emit error(ZJU_ERROR::ACCESS_DENIED); - } - else if (output.contains("listen failed")) - { - emit error(ZJU_ERROR::LISTEN_FAILED); - } - else if (output.contains("Invalid username or password!")) - { - emit error(ZJU_ERROR::INVALID_DETAIL); - } - else if (output.contains("You are trying brute-force login on this IP address.")) - { - emit error(ZJU_ERROR::BRUTE_FORCE); - } - else if (output.contains("Login failed") || output.contains("too many login failures")) - { - emit error(ZJU_ERROR::OTHER_LOGIN_FAILED); - } - else if (output.contains("client setup error")) - { - emit error(ZJU_ERROR::CLIENT_FAILED); - } - else if (output.contains("panic")) - { - emit error(ZJU_ERROR::OTHER); - } + outputProcess(output); }); - connect(zjuConnectProcess, &QProcess::readyReadStandardError, this, [&]() + connect(zjuConnectProcess, &QProcess::readyReadStandardError, this, [&, outputProcess]() { QString output = Utils::ConsoleOutputToQString(zjuConnectProcess->readAllStandardError()); - emit outputRead(output); - - if (output.contains("Access is denied.")) - { - emit error(ZJU_ERROR::ACCESS_DENIED); - } - else if (output.contains("listen failed")) - { - emit error(ZJU_ERROR::LISTEN_FAILED); - } - else if (output.contains("client setup error")) - { - emit error(ZJU_ERROR::CLIENT_FAILED); - } - else if (output.contains("Invalid username or password!")) - { - emit error(ZJU_ERROR::INVALID_DETAIL); - } - else if (output.contains("You are trying brute-force login on this IP address.")) - { - emit error(ZJU_ERROR::BRUTE_FORCE); - } - else if (output.contains("Login failed") || output.contains("too many login failures")) - { - emit error(ZJU_ERROR::OTHER_LOGIN_FAILED); - } - else if (output.contains("panic")) - { - emit error(ZJU_ERROR::OTHER); - } + outputProcess(output); }); connect(zjuConnectProcess, &QProcess::errorOccurred, this, [&](QProcess::ProcessError err) @@ -100,24 +76,33 @@ void ZjuConnectController::start( const QString& program, const QString& username, const QString& password, + const QString& totpSecret, const QString& server, int port, const QString& dns, bool dnsAuto, const QString& secondaryDns, - bool disableMultiLine, - bool disableKeepAlive, - bool proxyAll, + int dnsTtl, const QString& socksBind, const QString& httpBind, const QString& shadowsocksUrl, + const QString& dialDirectProxy, + bool disableMultiLine, + bool disableKeepAlive, + bool skipDomainResource, + bool disableServerConfig, + bool proxyAll, + bool disableZjuDns, + bool disableZjuConfig, + bool debugDump, bool tunMode, bool addRoute, bool dnsHijack, - bool skipDomainResource, - bool debugDump, const QString& tcpPortForwarding, - const QString& udpPortForwarding + const QString& udpPortForwarding, + const QString& customDNS, + const QString& customProxyDomain, + const QString& extraArguments ) { QStringList args; @@ -147,6 +132,12 @@ void ZjuConnectController::start( } } + if (dnsTtl != 3600) + { + args.append("-dns-ttl"); + args.append(QString::number(dnsTtl)); + } + if (!secondaryDns.isEmpty()) { args.append("-secondary-dns-server"); @@ -163,11 +154,31 @@ void ZjuConnectController::start( args.append("-disable-keep-alive"); } + if (disableZjuConfig) + { + args.append("-disable-zju-config"); + } + + if (disableZjuDns) + { + args.append("-disable-zju-dns"); + } + + if (disableServerConfig) + { + args.append("-disable-server-config"); + } + if (proxyAll) { args.append("-proxy-all"); } + if (skipDomainResource) + { + args.append("-skip-domain-resource"); + } + if (tunMode) { args.append("-tun-mode"); @@ -206,6 +217,12 @@ void ZjuConnectController::start( args.append(shadowsocksUrl); } + if (!dialDirectProxy.isEmpty()) + { + args.append("-dial-direct-proxy"); + args.append(dialDirectProxy); + } + if (!tcpPortForwarding.isEmpty()) { args.append("-tcp-port-forwarding"); @@ -218,15 +235,39 @@ void ZjuConnectController::start( args.append(udpPortForwarding); } - if (skipDomainResource) - { - args.append("-skip-domain-resource"); - } + if (!customDNS.isEmpty()) + { + args.append("-custom-dns"); + args.append(customDNS); + } + + if (!customProxyDomain.isEmpty()) + { + args.append("-custom-proxy-domain"); + args.append(customProxyDomain); + } + + if (!extraArguments.isEmpty()) + { + args.append(extraArguments.split(" ")); + } QString timeString = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"); emit outputRead(timeString + " VPN 启动!参数:" + args.join(' ')); - zjuConnectProcess->start(program, QStringList({ "-username", username, "-password", password }) + args); + QStringList credentialList({ + "-username", username, + "-password", password, + }); + + if (!totpSecret.isEmpty()) + { + emit outputRead(timeString + " 使用了 TOTP"); + credentialList.append("-totp-secret"); + credentialList.append(totpSecret); + } + + zjuConnectProcess->start(program, credentialList + args); zjuConnectProcess->waitForStarted(); if (zjuConnectProcess->state() == QProcess::NotRunning) { diff --git a/zjuconnectcontroller/zjuconnectcontroller.h b/zjuconnectcontroller/zjuconnectcontroller.h index 59dc57e..e77dcc1 100644 --- a/zjuconnectcontroller/zjuconnectcontroller.h +++ b/zjuconnectcontroller/zjuconnectcontroller.h @@ -29,24 +29,33 @@ public: const QString& program, const QString& username, const QString& password, - const QString& server = "", - int port = 0, - const QString& dns = "", - bool dnsAuto = true, - const QString& secondaryDns = "", - bool disableMultiLine = false, - bool disableKeepAlive = true, - bool proxyAll = false, - const QString& socksBind = "", - const QString& httpBind = "", - const QString& shadowsocksUrl = "", - bool tunMode = false, - bool addRoute = false, - bool dnsHijack = false, - bool skipDomainResource = true, - bool debugDump = false, - const QString& tcpPortForwarding = "", - const QString& udpPortForwarding = "" + const QString& totpSecret, + const QString& server, + int port, + const QString& dns, + bool dnsAuto, + const QString& secondaryDns, + int dnsTtl, + const QString& socksBind, + const QString& httpBind, + const QString& shadowsocksUrl, + const QString& dialDirectProxy, + bool disableMultiLine, + bool disableKeepAlive, + bool skipDomainResource, + bool disableServerConfig, + bool proxyAll, + bool disableZjuDns, + bool disableZjuConfig, + bool debugDump, + bool tunMode, + bool addRoute, + bool dnsHijack, + const QString& tcpPortForwarding, + const QString& udpPortForwarding, + const QString& customDNS, + const QString& customProxyDomain, + const QString& extraArguments ); void stop(); diff --git a/zjuconnectmode.cpp b/zjuconnectmode.cpp index 3886709..d394b3a 100644 --- a/zjuconnectmode.cpp +++ b/zjuconnectmode.cpp @@ -38,11 +38,11 @@ void MainWindow::initZjuConnect() if ( zjuConnectError != ZJU_ERROR::NONE && zjuConnectError != ZJU_ERROR::OTHER && - settings->value("ZJUConnect/AutoReconnect", false).toBool() && + settings->value("Common/AutoReconnect", false).toBool() && isZjuConnectLinked ) { - QTimer::singleShot(settings->value("ZJUConnect/ReconnectTime", 1).toInt() * 1000, this, [&]() + QTimer::singleShot(settings->value("Common/ReconnectTime", 1).toInt() * 1000, this, [&]() { if (isZjuConnectLinked) { @@ -111,8 +111,8 @@ void MainWindow::initZjuConnect() return; } - QString username_ = settings->value("Common/Username", "").toString(); - QString password_ = QByteArray::fromBase64(settings->value("Common/Password", "").toString().toUtf8()); + QString username_ = settings->value("Credential/Username", "").toString(); + QString password_ = QByteArray::fromBase64(settings->value("Credential/Password", "").toString().toUtf8()); auto startZjuConnect = [this](const QString &username, const QString &password) { QString program_filename; @@ -125,13 +125,13 @@ void MainWindow::initZjuConnect() program_filename = "zju-connect"; } QString program_path = QCoreApplication::applicationDirPath() + "/" + program_filename; - QString bind_prefix = settings->value("ZJUConnect/OutsideAccess", false).toBool() ? "0.0.0.0:" : "127.0.0.1:"; + QString bind_prefix = settings->value("ZJUConnect/OutsideAccess", false).toBool() ? "[::]:" : "[::1]:"; isZjuConnectLinked = true; ui->pushButton1->setText("断开服务器"); ui->pushButton2->show(); - if (settings->value("ZJUConnect/AutoSetProxy", false).toBool()) + if (settings->value("Common/AutoSetProxy", false).toBool()) { ui->pushButton2->click(); } @@ -140,24 +140,33 @@ void MainWindow::initZjuConnect() program_path, username, password, + settings->value("Credential/TOTPSecret").toString(), settings->value("ZJUConnect/ServerAddress").toString(), settings->value("ZJUConnect/ServerPort").toInt(), settings->value("ZJUConnect/DNS").toString(), settings->value("ZJUConnect/DNSAuto").toBool(), settings->value("ZJUConnect/SecondaryDNS").toString(), - !settings->value("ZJUConnect/MultiLine").toBool(), - !settings->value("ZJUConnect/KeepAlive").toBool(), - settings->value("ZJUConnect/ProxyAll").toBool(), + settings->value("ZJUConnect/DNSTTL").toInt(), bind_prefix + QString::number(settings->value("ZJUConnect/Socks5Port").toInt()), bind_prefix + QString::number(settings->value("ZJUConnect/HttpPort").toInt()), - settings->value("ZJUConnect/ShadowsocksUrl").toString(), - settings->value("ZJUConnect/TunMode").toBool(), - settings->value("ZJUConnect/Route").toBool(), - settings->value("ZJUConnect/DNSHijack").toBool(), - settings->value("ZJUConnect/SkipDomainResource").toBool(), + settings->value("ZJUConnect/ShadowsocksURL").toString(), + settings->value("ZJUConnect/DialDirectProxy").toString(), + !settings->value("ZJUConnect/MultiLine").toBool(), + !settings->value("ZJUConnect/KeepAlive").toBool(), + settings->value("ZJUConnect/SkipDomainResource").toBool(), + settings->value("ZJUConnect/DisableServerConfig").toBool(), + settings->value("ZJUConnect/ProxyAll").toBool(), + settings->value("ZJUConnect/DisableZJUDNS").toBool(), + !settings->value("ZJUConnect/ZJUDefault").toBool(), settings->value("ZJUConnect/Debug").toBool(), + settings->value("ZJUConnect/TunMode").toBool(), + settings->value("ZJUConnect/AddRoute").toBool(), + settings->value("ZJUConnect/DNSHijack").toBool(), settings->value("ZJUConnect/TcpPortForwarding").toString(), - settings->value("ZJUConnect/UdpPortForwarding").toString() + settings->value("ZJUConnect/UdpPortForwarding").toString(), + settings->value("ZJUConnect/CustomDNS", "").toString(), + settings->value("ZJUConnect/CustomProxyDomain", "").toString(), + settings->value("ZJUConnect/ExtraArguments", "").toString() ); }; @@ -171,8 +180,8 @@ void MainWindow::initZjuConnect() { if (saveDetail) { - settings->setValue("Common/Username", username); - settings->setValue("Common/Password", QString(password.toUtf8().toBase64())); + settings->setValue("Credential/Username", username); + settings->setValue("Credential/Password", QString(password.toUtf8().toBase64())); settings->sync(); } startZjuConnect(username, password); @@ -221,7 +230,7 @@ void MainWindow::initZjuConnect() Utils::setSystemProxy(settings->value("ZJUConnect/HttpPort", 11081).toInt(), settings->value("ZJUConnect/Socks5Port", 11080).toInt(), - settings->value("ZJUConnect/SystemProxyBypass", "localhost").toString()); + settings->value("Common/SystemProxyBypass", "localhost").toString()); ui->pushButton2->setText("清除系统代理"); isSystemProxySet = true; }