feat: Add customized geo asset download &&

Add font size customization &&
Fix an issue with underlying dns detection &&
Improve Tray Icon &&
Fix a crash when Core crashed while running a profile
This commit is contained in:
Nova 2024-10-17 18:01:02 +03:30
parent 144d4321a4
commit e6149a8d28
14 changed files with 112 additions and 128 deletions

View File

@ -8,16 +8,16 @@ require (
github.com/matsuridayo/libneko v0.0.0-20230913024055-5277a5bfc889
github.com/oschwald/maxminddb-golang v1.13.1
github.com/sagernet/sing v0.5.0-rc.2
github.com/sagernet/sing-box v1.10.0-beta.12
github.com/sagernet/sing-box v1.10.0
github.com/sagernet/sing-dns v0.3.0-rc.2
github.com/sagernet/sing-tun v0.4.0-rc.3.0.20241014141023-07278fb4705b
github.com/sagernet/sing-tun v0.4.0-rc.4
github.com/spf13/cobra v1.8.1
golang.org/x/sys v0.25.0
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6
grpc_server v1.0.0
)
replace github.com/sagernet/sing-box => github.com/Mahdi-zarei/sing-box v1.3.5-0.20241016190733-d626a7470382
replace github.com/sagernet/sing-box => github.com/Mahdi-zarei/sing-box v1.3.5-0.20241017140058-b3e4d700db51
replace github.com/sagernet/sing-dns => github.com/Mahdi-zarei/sing-dns v0.3.0-beta.14.0.20241016191038-09d232d0a8a9

View File

@ -4,8 +4,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY=
cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Mahdi-zarei/sing-box v1.3.5-0.20241016190733-d626a7470382 h1:BTUBM6MU5MFRwKj8gSsP2aPL1/jzUV53MneULed32k0=
github.com/Mahdi-zarei/sing-box v1.3.5-0.20241016190733-d626a7470382/go.mod h1:BAEiGv87fBO6hsop/I6KAW97IBlyy3MIjrw1gwuc+WE=
github.com/Mahdi-zarei/sing-box v1.3.5-0.20241017140058-b3e4d700db51 h1:DBU7LsrTT6k6Wuou0m+PwKZ+HeCRRLhIow6hQbz6XWs=
github.com/Mahdi-zarei/sing-box v1.3.5-0.20241017140058-b3e4d700db51/go.mod h1:vVb92PP7RjZxZwSCFpEQG16GokQFP7XbEpC+AUZgSqs=
github.com/Mahdi-zarei/sing-dns v0.3.0-beta.14.0.20241016191038-09d232d0a8a9 h1:1agKy0IGG6OX6IyFzDhgbplL/1FQQ4LfJLmRA+ufqt8=
github.com/Mahdi-zarei/sing-dns v0.3.0-beta.14.0.20241016191038-09d232d0a8a9/go.mod h1:TqLIelI+FAbVEdiTRolhGLOwvhVjY7oT+wezlOJUQ7M=
github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
@ -163,8 +163,8 @@ github.com/sagernet/sing-shadowsocks2 v0.2.0 h1:wpZNs6wKnR7mh1wV9OHwOyUr21VkS3wK
github.com/sagernet/sing-shadowsocks2 v0.2.0/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ=
github.com/sagernet/sing-shadowtls v0.1.4 h1:aTgBSJEgnumzFenPvc+kbD9/W0PywzWevnVpEx6Tw3k=
github.com/sagernet/sing-shadowtls v0.1.4/go.mod h1:F8NBgsY5YN2beQavdgdm1DPlhaKQlaL6lpDdcBglGK4=
github.com/sagernet/sing-tun v0.4.0-rc.3.0.20241014141023-07278fb4705b h1:a2VWOxv7uvIThhJyW6bB+D+bciLSkkqzq4bC4yg3U0g=
github.com/sagernet/sing-tun v0.4.0-rc.3.0.20241014141023-07278fb4705b/go.mod h1:+lQdWhqD4atzrCgRhoyrxBCg1OBru/hAv2BT3kdgmGM=
github.com/sagernet/sing-tun v0.4.0-rc.4 h1:EFz+UjLZTm+YS3ob1vpqjOga67wyvnxWcbQKfe5wE3Y=
github.com/sagernet/sing-tun v0.4.0-rc.4/go.mod h1:+lQdWhqD4atzrCgRhoyrxBCg1OBru/hAv2BT3kdgmGM=
github.com/sagernet/sing-vmess v0.1.12 h1:2gFD8JJb+eTFMoa8FIVMnknEi+vCSfaiTXTfEYAYAPg=
github.com/sagernet/sing-vmess v0.1.12/go.mod h1:luTSsfyBGAc9VhtCqwjR+dt1QgqBhuYBCONB/POhF8I=
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ=

View File

@ -2,6 +2,7 @@ package boxdns
import (
"context"
"github.com/sagernet/sing/common/control"
"log"
"net/netip"
"strings"
@ -32,12 +33,16 @@ func init() {
})
logger := logFactory.NewLogger("windows-dns")
ifcFinder := control.NewDefaultInterfaceFinder()
monitorNU, _ = tun.NewNetworkUpdateMonitor(logger)
monitorDI, _ = tun.NewDefaultInterfaceMonitor(monitorNU, logger, tun.DefaultInterfaceMonitorOptions{})
monitorDI, _ = tun.NewDefaultInterfaceMonitor(monitorNU, logger, tun.DefaultInterfaceMonitorOptions{
InterfaceFinder: ifcFinder,
})
monitorDI.RegisterCallback(monitorForUnderlyingDNS)
monitorDI.RegisterCallback(handleInterfaceChange)
monitorDI.Start()
monitorNU.Start()
ifcFinder.Update()
go func() {
for {
@ -61,8 +66,10 @@ func monitorForUnderlyingDNS(event int) {
guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7],
})
guidStr := "{" + u.String() + "}"
underlyingDNS = getFirstDNS(guidStr)
log.Println("underlyingDNS:", guidStr, underlyingDNS)
if getFirstDNS(guidStr) != underlyingDNS {
underlyingDNS = getFirstDNS(guidStr)
log.Println("underlyingDNS:", guidStr, underlyingDNS)
}
}
func getFirstDNS(guid string) string {

View File

@ -1,5 +1,6 @@
#pragma once
#include <QString>
#include <QStringList>
namespace NekoGui {
namespace DomainMatcher {
@ -26,4 +27,9 @@ namespace NekoGui {
namespace Information {
inline QString HijackInfo = "Listens on the given addr:port (on Windows, port is always 53) and redirects the requests to the DNS module. Domains that match the rules will have their requests hijacked and the A and AAAA queries will be responded with the Inet4 response and Inet6 response respectively.\nThe Redirect settings sets up an inbound that listens on the given addr:port, sniffs the destination if possible and redirects the requests to their true destination.\nThe use case of these settings is apps that do not respect the system proxy for resolving their DNS requests (one such example is discord), You can hijack their DNS requests to 127.0.0.1 and then route them through the Nekoray tunnel. The same effect could be achieved using Tun mode, but one may not want to tunnel the whole device (For example when Gaming), this is where DNS hijack can transparently handle things.\n\nCurrently you can Automatically set the System DNS in windows.";
}
namespace GeoAssets {
inline QStringList GeoIPURLs = {"https://github.com/SagerNet/sing-geoip/releases/latest/download/geoip.db", "https://raw.githubusercontent.com/Chocolate4U/Iran-sing-box-rules/release/geoip.db"};
inline QStringList GeoSiteURLs = {"https://github.com/SagerNet/sing-geosite/releases/latest/download/geosite.db", "https://raw.githubusercontent.com/Chocolate4U/Iran-sing-box-rules/release/geosite.db"};
}
} // namespace NekoGui

View File

@ -47,33 +47,6 @@ namespace NekoGui_network {
return "";
}
QString NetworkRequestHelper::GetLatestDownloadURL(const QString &url, const QString &assetName, bool* success) {
cpr::Session session;
session.SetUrl(cpr::Url{url.toStdString()});
session.SetTimeout(3000);
if (NekoGui::dataStore->spmode_system_proxy) {
session.SetProxies({{"http", "127.0.0.1:" + QString(Int2String(NekoGui::dataStore->inbound_socks_port)).toStdString()},
{"https", "127.0.0.1:" + QString(Int2String(NekoGui::dataStore->inbound_socks_port)).toStdString()}});
}
cpr::Response r = session.Get();
if (r.status_code != 200) {
*success = false;
return {r.status_line.c_str()};
}
auto respObj = QString2QJsonObject(QString(r.text.c_str()));
auto assets = respObj["assets"].toArray();
for (const auto &asset: assets) {
auto assetObj = asset.toObject();
if (assetObj["name"] == assetName) {
*success = true;
return assetObj["browser_download_url"].toString();
}
}
*success = false;
return "not found";
}
QString NetworkRequestHelper::DownloadGeoAsset(const QString &url, const QString &fileName) {
cpr::Session session;
session.SetUrl(cpr::Url{url.toStdString()});
@ -83,6 +56,7 @@ namespace NekoGui_network {
}
auto filePath = qApp->applicationDirPath()+ "/" + fileName;
std::ofstream fout;
QFile::remove(QString(filePath + ".1"));
fout.open(QString(filePath + ".1").toStdString(), std::ios::trunc | std::ios::out | std::ios::binary);
auto r = session.Download(fout);
fout.close();

View File

@ -26,8 +26,6 @@ namespace NekoGui_network {
static QString GetHeader(const QList<QPair<QByteArray, QByteArray>> &header, const QString &name);
static QString GetLatestDownloadURL(const QString &url, const QString &assetName, bool* success);
static QString DownloadGeoAsset(const QString &url, const QString &fileName);
};
} // namespace NekoGui_network

View File

@ -259,6 +259,7 @@ namespace NekoGui {
_add(new configItem("remember_enable", &remember_enable, itemType::boolean));
_add(new configItem("language", &language, itemType::integer));
_add(new configItem("font", &font, itemType::string));
_add(new configItem("font_size", &font_size, itemType::integer));
_add(new configItem("spmode2", &remember_spmode, itemType::stringList));
_add(new configItem("skip_cert", &skip_cert, itemType::boolean));
_add(new configItem("hk_mw", &hotkey_mainwindow, itemType::string));

View File

@ -85,7 +85,8 @@ namespace NekoGui {
bool mux_default_on = false;
QString theme = "0";
int language = 0;
QString font;
QString font = "";
int font_size = 0;
QString mw_size = "";
QStringList log_ignore = {};
bool start_minimal = false;

View File

@ -232,6 +232,11 @@ int main(int argc, char* argv[]) {
if (!NekoGui::dataStore->font.isEmpty()) {
qApp->setFont(NekoGui::dataStore->font);
}
if (NekoGui::dataStore->font_size != 0) {
auto font = qApp->font();
font.setPointSize(NekoGui::dataStore->font_size);
qApp->setFont(font);
}
// Signals
signal(SIGTERM, signal_handler);

View File

@ -25,8 +25,8 @@ QPixmap Icon::GetTrayIcon(Icon::TrayIconStatus status) {
auto side = pixmap.width();
auto radius = side * 0.4;
auto d = side * 0.3;
auto margin = side * 0.05;
auto d = side * 0.4;
auto margin = side * 0.04;
if (status == TrayIconStatus::RUNNING) {
p.setBrush(QBrush(Qt::darkGreen));
@ -35,7 +35,7 @@ QPixmap Icon::GetTrayIcon(Icon::TrayIconStatus status) {
} else if (status == TrayIconStatus::VPN) {
p.setBrush(QBrush(Qt::red));
} else if (status == TrayIconStatus::DNS) {
p.setBrush(QBrush(Qt::yellow));
p.setBrush(QBrush(Qt::darkMagenta));
}
p.drawRoundedRect(
QRect(side - d - margin,

View File

@ -100,10 +100,23 @@ DialogBasicSettings::DialogBasicSettings(QWidget *parent)
connect(ui->language, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, [=](int index) {
CACHE.needRestart = true;
});
ui->font->addItems(QFontDatabase::families());
ui->font->setCurrentText(qApp->font().family());
connect(ui->font, &QComboBox::currentTextChanged, this, [=](const QString &font) {
CACHE.needRestart = true;
qApp->setFont(font);
NekoGui::dataStore->font = font;
NekoGui::dataStore->Save();
adjustSize();
});
for (int i=7;i<=26;i++) {
ui->font_size->addItem(Int2String(i));
}
ui->font_size->setCurrentText(Int2String(qApp->font().pointSize()));
connect(ui->font_size, &QComboBox::currentTextChanged, this, [=](const QString &sizeStr) {
auto font = qApp->font();
font.setPointSize(sizeStr.toInt());
qApp->setFont(font);
NekoGui::dataStore->font_size = sizeStr.toInt();
NekoGui::dataStore->Save();
adjustSize();
});
//
ui->theme->addItems(QStyleFactory::keys());
@ -136,32 +149,15 @@ DialogBasicSettings::DialogBasicSettings(QWidget *parent)
ui->groupBox_core->setTitle(software_core_name);
// Assets
ui->geoip_url->setText(NekoGui::dataStore->geoip_download_url);
ui->geosite_url->setText(NekoGui::dataStore->geosite_download_url);
connect(ui->geoip_auto_btn, &QPushButton::clicked, this, [=](){
bool success;
auto resp = NetworkRequestHelper::GetLatestDownloadURL("https://api.github.com/repos/SagerNet/sing-geoip/releases/latest", "geoip.db", &success);
if (!success) {
runOnUiThread([=](){
MessageBoxWarning("Error", resp);
});
return;
}
ui->geoip_url->setText(resp);
});
connect(ui->geosite_auto_btn, &QPushButton::clicked, this, [=](){
bool success;
auto resp = NetworkRequestHelper::GetLatestDownloadURL("https://api.github.com/repos/SagerNet/sing-geosite/releases/latest", "geosite.db", &success);
if (!success) {
runOnUiThread([=](){
MessageBoxWarning("Error", resp);
});
return;
}
ui->geosite_url->setText(resp);
});
ui->geoip_url->setEditable(true);
ui->geosite_url->setEditable(true);
ui->geoip_url->addItems(NekoGui::GeoAssets::GeoIPURLs);
ui->geosite_url->addItems(NekoGui::GeoAssets::GeoSiteURLs);
ui->geoip_url->setCurrentText(NekoGui::dataStore->geoip_download_url);
ui->geosite_url->setCurrentText(NekoGui::dataStore->geosite_download_url);
connect(ui->download_geo_btn, &QPushButton::clicked, this, [=]() {
MW_dialog_message(Dialog_DialogBasicSettings, "DownloadAssets;"+ui->geoip_url->text()+";"+ui->geosite_url->text());
MW_dialog_message(Dialog_DialogBasicSettings, "DownloadAssets;"+ui->geoip_url->currentText()+";"+ui->geosite_url->currentText());
});
connect(ui->remove_srs_btn, &QPushButton::clicked, this, [=](){
auto rsDir = QDir(RULE_SETS_DIR);
@ -259,7 +255,6 @@ void DialogBasicSettings::accept() {
// Style
NekoGui::dataStore->language = ui->language->currentIndex();
NekoGui::dataStore->font = ui->font->currentText();
D_SAVE_BOOL(start_minimal)
D_SAVE_INT(max_log_line)
@ -300,8 +295,8 @@ void DialogBasicSettings::accept() {
NekoGui::dataStore->disable_traffic_stats = ui->disable_stats->isChecked();
// Assets
NekoGui::dataStore->geoip_download_url = ui->geoip_url->text();
NekoGui::dataStore->geosite_download_url = ui->geosite_url->text();
NekoGui::dataStore->geoip_download_url = ui->geoip_url->currentText();
NekoGui::dataStore->geosite_download_url = ui->geosite_url->currentText();
// Mux
D_SAVE_INT(mux_concurrency)

View File

@ -70,7 +70,9 @@
<item>
<widget class="QLabel" name="inbound_socks_port_l">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Socks + HTTP Proxy&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Socks
+ HTTP Proxy&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;
</string>
</property>
<property name="text">
<string>Listen Port</string>
@ -336,27 +338,7 @@
<item>
<widget class="QGroupBox" name="groupBox2">
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0">
<widget class="QLabel" name="label_15">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string notr="true">Language</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Font</string>
</property>
</widget>
</item>
<item row="0" column="1">
<item row="0" column="2">
<widget class="QComboBox" name="language">
<item>
<property name="text">
@ -385,8 +367,38 @@
</item>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="font"/>
<item row="2" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Font Size</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Font</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_15">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string notr="true">Language</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QFontComboBox" name="font"/>
</item>
<item row="2" column="2">
<widget class="QComboBox" name="font_size"/>
</item>
</layout>
</widget>
@ -521,7 +533,9 @@
</size>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Might Improve Ping and Performance&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Might
Improve Ping and Performance&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;
</string>
</property>
<property name="text">
<string>Disable Traffic Stats</string>
@ -591,7 +605,9 @@
<item>
<widget class="QGroupBox" name="ntp_box">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Settings for the sing-box's built-in NTP client&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Settings for the
sing-box's built-in NTP client&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;
</string>
</property>
<property name="title">
<string>NTP Settings</string>
@ -643,7 +659,9 @@
<item>
<widget class="QComboBox" name="ntp_interval">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;In minutes&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;In
minutes&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;
</string>
</property>
<item>
<property name="text">
@ -683,7 +701,9 @@
<item>
<widget class="QPushButton" name="remove_srs_btn">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Remove the currently generated rule-sets so that they can be regenerated&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Remove the
currently generated rule-sets so that they can be regenerated&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;
</string>
</property>
<property name="text">
<string>Remove Generated Rule-sets</string>
@ -703,17 +723,7 @@
</widget>
</item>
<item>
<widget class="QLineEdit" name="geoip_url"/>
</item>
<item>
<widget class="QPushButton" name="geoip_auto_btn">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Sets the URL to the latest sing-geoip release URL&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Use Sing-Geoip</string>
</property>
</widget>
<widget class="QComboBox" name="geoip_url"/>
</item>
</layout>
</item>
@ -727,17 +737,7 @@
</widget>
</item>
<item>
<widget class="QLineEdit" name="geosite_url"/>
</item>
<item>
<widget class="QPushButton" name="geosite_auto_btn">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Sets the URL to the latest sing-geosite release URL&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Use Sing-Geosite</string>
</property>
</widget>
<widget class="QComboBox" name="geosite_url"/>
</item>
</layout>
</item>

View File

@ -100,9 +100,6 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
// software_name
software_name = "NekoBox";
software_core_name = "sing-box";
// replace default values
if (NekoGui::dataStore->log_level == "warning") NekoGui::dataStore->log_level = "info";
if (NekoGui::dataStore->mux_protocol.isEmpty()) NekoGui::dataStore->mux_protocol = "h2mux";
//
if (QDir("dashboard").count() == 0) {
QDir().mkdir("dashboard");

View File

@ -364,7 +364,7 @@ void MainWindow::neko_start(int _id) {
runOnNewThread([=] {
// stop current running
if (NekoGui::dataStore->started_id >= 0) {
if (running != nullptr) {
runOnUiThread([=] { neko_stop(false, true, true); });
sem_stopped.acquire();
}