added domain name resolving before connection for wg/awg and xray protocols (#814)

added domain name resolving before connection
This commit is contained in:
Nethius 2024-09-17 01:14:13 +04:00 committed by GitHub
parent 76e5039578
commit 46cd740a84
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 61 additions and 46 deletions

View file

@ -35,7 +35,7 @@ fun getLocalNetworks(context: Context, ipv6: Boolean): List<InetNetwork> {
return emptyList() return emptyList()
} }
fun parseInetAddress(address: String): InetAddress = parseNumericAddressCompat(address) fun parseInetAddress(address: String): InetAddress = InetAddress.getByName(address)
private val parseNumericAddressCompat: (String) -> InetAddress = private val parseNumericAddressCompat: (String) -> InetAddress =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {

View file

@ -104,7 +104,8 @@ ErrorCode ServerController::runContainerScript(const ServerCredentials &credenti
if (e) if (e)
return e; return e;
QString runner = QString("sudo docker exec -i $CONTAINER_NAME %2 %1 ").arg(fileName, (container == DockerContainer::Socks5Proxy ? "sh" : "bash")); QString runner =
QString("sudo docker exec -i $CONTAINER_NAME %2 %1 ").arg(fileName, (container == DockerContainer::Socks5Proxy ? "sh" : "bash"));
e = runScript(credentials, replaceVars(runner, genVarsForScript(credentials, container)), cbReadStdOut, cbReadStdErr); e = runScript(credentials, replaceVars(runner, genVarsForScript(credentials, container)), cbReadStdOut, cbReadStdErr);
QString remover = QString("sudo docker exec -i $CONTAINER_NAME rm %1 ").arg(fileName); QString remover = QString("sudo docker exec -i $CONTAINER_NAME rm %1 ").arg(fileName);
@ -424,7 +425,7 @@ ErrorCode ServerController::buildContainerWorker(const ServerCredentials &creden
if (errorCode) if (errorCode)
return errorCode; return errorCode;
errorCode = uploadFileToHost(credentials, amnezia::scriptData(ProtocolScriptType::dockerfile, container).toUtf8(),dockerFilePath); errorCode = uploadFileToHost(credentials, amnezia::scriptData(ProtocolScriptType::dockerfile, container).toUtf8(), dockerFilePath);
if (errorCode) if (errorCode)
return errorCode; return errorCode;
@ -435,7 +436,8 @@ ErrorCode ServerController::buildContainerWorker(const ServerCredentials &creden
return ErrorCode::NoError; return ErrorCode::NoError;
}; };
errorCode = runScript(credentials, errorCode =
runScript(credentials,
replaceVars(amnezia::scriptData(SharedScriptType::build_container), genVarsForScript(credentials, container, config)), replaceVars(amnezia::scriptData(SharedScriptType::build_container), genVarsForScript(credentials, container, config)),
cbReadStdOut); cbReadStdOut);
if (errorCode) if (errorCode)
@ -619,13 +621,15 @@ ServerController::Vars ServerController::genVarsForScript(const ServerCredential
// Socks5 proxy vars // Socks5 proxy vars
vars.append({ { "$SOCKS5_PROXY_PORT", socks5ProxyConfig.value(config_key::port).toString(protocols::socks5Proxy::defaultPort) } }); vars.append({ { "$SOCKS5_PROXY_PORT", socks5ProxyConfig.value(config_key::port).toString(protocols::socks5Proxy::defaultPort) } });
auto username = socks5ProxyConfig.value(config_key:: userName).toString(); auto username = socks5ProxyConfig.value(config_key::userName).toString();
auto password = socks5ProxyConfig.value(config_key::password).toString(); auto password = socks5ProxyConfig.value(config_key::password).toString();
QString socks5user = (!username.isEmpty() && !password.isEmpty()) ? QString("users %1:CL:%2").arg(username, password) : ""; QString socks5user = (!username.isEmpty() && !password.isEmpty()) ? QString("users %1:CL:%2").arg(username, password) : "";
vars.append({ { "$SOCKS5_USER", socks5user } }); vars.append({ { "$SOCKS5_USER", socks5user } });
vars.append({ { "$SOCKS5_AUTH_TYPE", socks5user.isEmpty() ? "none" : "strong" } }); vars.append({ { "$SOCKS5_AUTH_TYPE", socks5user.isEmpty() ? "none" : "strong" } });
QString serverIp = NetworkUtilities::getIPAddress(credentials.hostName); QString serverIp = (container != DockerContainer::Awg && container != DockerContainer::WireGuard && container != DockerContainer::Xray)
? NetworkUtilities::getIPAddress(credentials.hostName)
: credentials.hostName;
if (!serverIp.isEmpty()) { if (!serverIp.isEmpty()) {
vars.append({ { "$SERVER_IP_ADDRESS", serverIp } }); vars.append({ { "$SERVER_IP_ADDRESS", serverIp } });
} else { } else {
@ -711,7 +715,8 @@ ErrorCode ServerController::isServerPortBusy(const ServerCredentials &credential
udpProtoScript.append("' | grep -i udp"); udpProtoScript.append("' | grep -i udp");
tcpProtoScript.append(" | grep LISTEN"); tcpProtoScript.append(" | grep LISTEN");
ErrorCode errorCode = runScript(credentials, replaceVars(tcpProtoScript, genVarsForScript(credentials, container)), cbReadStdOut, cbReadStdErr); ErrorCode errorCode =
runScript(credentials, replaceVars(tcpProtoScript, genVarsForScript(credentials, container)), cbReadStdOut, cbReadStdErr);
if (errorCode != ErrorCode::NoError) { if (errorCode != ErrorCode::NoError) {
return errorCode; return errorCode;
} }

View file

@ -100,10 +100,8 @@ QJsonObject VpnConfigurationsController::createVpnConfiguration(const QPair<QStr
protocolConfigString = configurator->processConfigWithLocalSettings(dns, isApiConfig, protocolConfigString); protocolConfigString = configurator->processConfigWithLocalSettings(dns, isApiConfig, protocolConfigString);
QJsonObject vpnConfigData = QJsonDocument::fromJson(protocolConfigString.toUtf8()).object(); QJsonObject vpnConfigData = QJsonDocument::fromJson(protocolConfigString.toUtf8()).object();
vpnConfigData = QJsonDocument::fromJson(protocolConfigString.toUtf8()).object();
// add mtu for old configs
if (container == DockerContainer::Awg || container == DockerContainer::WireGuard) { if (container == DockerContainer::Awg || container == DockerContainer::WireGuard) {
// add mtu for old configs
if (vpnConfigData[config_key::mtu].toString().isEmpty()) { if (vpnConfigData[config_key::mtu].toString().isEmpty()) {
vpnConfigData[config_key::mtu] = container == DockerContainer::Awg ? protocols::awg::defaultMtu : protocols::wireguard::defaultMtu; vpnConfigData[config_key::mtu] = container == DockerContainer::Awg ? protocols::awg::defaultMtu : protocols::wireguard::defaultMtu;
} }

View file

@ -109,7 +109,10 @@ QStringList NetworkUtilities::summarizeRoutes(const QStringList &ips, const QStr
QString NetworkUtilities::getIPAddress(const QString &host) QString NetworkUtilities::getIPAddress(const QString &host)
{ {
if (ipAddressRegExp().match(host).hasMatch()) { QHostAddress address(host);
if (QAbstractSocket::IPv4Protocol == address.protocol()) {
return host;
} else if (QAbstractSocket::IPv6Protocol == address.protocol()) {
return host; return host;
} }

View file

@ -4,9 +4,8 @@
#include <QTcpSocket> #include <QTcpSocket>
#include <QThread> #include <QThread>
#include "logger.h"
#include "utilities.h"
#include "wireguardprotocol.h" #include "wireguardprotocol.h"
#include "core/networkUtilities.h"
#include "mozilla/localsocketcontroller.h" #include "mozilla/localsocketcontroller.h"
@ -37,6 +36,12 @@ void WireguardProtocol::stop()
ErrorCode WireguardProtocol::startMzImpl() ErrorCode WireguardProtocol::startMzImpl()
{ {
QString protocolName = m_rawConfig.value("protocol").toString();
QJsonObject vpnConfigData = m_rawConfig.value(protocolName + "_config_data").toObject();
vpnConfigData[config_key::hostName] = NetworkUtilities::getIPAddress(vpnConfigData.value(config_key::hostName).toString());
m_rawConfig.insert(protocolName + "_config_data", vpnConfigData);
m_rawConfig[config_key::hostName] = NetworkUtilities::getIPAddress(m_rawConfig[config_key::hostName].toString());
m_impl->activate(m_rawConfig); m_impl->activate(m_rawConfig);
return ErrorCode::NoError; return ErrorCode::NoError;
} }

View file

@ -43,7 +43,9 @@ ErrorCode XrayProtocol::start()
m_xrayCfgFile.setAutoRemove(false); m_xrayCfgFile.setAutoRemove(false);
#endif #endif
m_xrayCfgFile.open(); m_xrayCfgFile.open();
m_xrayCfgFile.write(QJsonDocument(m_xrayConfig).toJson()); QString config = QJsonDocument(m_xrayConfig).toJson();
config.replace(m_remoteHost, m_remoteAddress);
m_xrayCfgFile.write(config.toUtf8());
m_xrayCfgFile.close(); m_xrayCfgFile.close();
QStringList args = QStringList() << "-c" << m_xrayCfgFile.fileName() << "-format=json"; QStringList args = QStringList() << "-c" << m_xrayCfgFile.fileName() << "-format=json";
@ -238,7 +240,8 @@ void XrayProtocol::readXrayConfiguration(const QJsonObject &configuration)
} }
m_xrayConfig = xrayConfiguration; m_xrayConfig = xrayConfiguration;
m_localPort = QString(amnezia::protocols::xray::defaultLocalProxyPort).toInt(); m_localPort = QString(amnezia::protocols::xray::defaultLocalProxyPort).toInt();
m_remoteAddress = configuration.value(amnezia::config_key::hostName).toString(); m_remoteHost = configuration.value(amnezia::config_key::hostName).toString();
m_remoteAddress = NetworkUtilities::getIPAddress(m_remoteHost);
m_routeMode = configuration.value(amnezia::config_key::splitTunnelType).toInt(); m_routeMode = configuration.value(amnezia::config_key::splitTunnelType).toInt();
m_primaryDNS = configuration.value(amnezia::config_key::dns1).toString(); m_primaryDNS = configuration.value(amnezia::config_key::dns1).toString();
m_secondaryDNS = configuration.value(amnezia::config_key::dns2).toString(); m_secondaryDNS = configuration.value(amnezia::config_key::dns2).toString();

View file

@ -26,6 +26,7 @@ private:
static QString tun2SocksExecPath(); static QString tun2SocksExecPath();
private: private:
int m_localPort; int m_localPort;
QString m_remoteHost;
QString m_remoteAddress; QString m_remoteAddress;
int m_routeMode; int m_routeMode;
QJsonObject m_configData; QJsonObject m_configData;

View file

@ -13,5 +13,5 @@ sudo docker network connect amnezia-dns-net $CONTAINER_NAME
sudo docker exec -i $CONTAINER_NAME bash -c 'mkdir -p /dev/net; if [ ! -c /dev/net/tun ]; then mknod /dev/net/tun c 10 200; fi' sudo docker exec -i $CONTAINER_NAME bash -c 'mkdir -p /dev/net; if [ ! -c /dev/net/tun ]; then mknod /dev/net/tun c 10 200; fi'
# Prevent to route packets outside of the container in case if server behind of the NAT # Prevent to route packets outside of the container in case if server behind of the NAT
sudo docker exec -i $CONTAINER_NAME sh -c "ifconfig eth0:0 $SERVER_IP_ADDRESS netmask 255.255.255.255 up" #sudo docker exec -i $CONTAINER_NAME sh -c "ifconfig eth0:0 $SERVER_IP_ADDRESS netmask 255.255.255.255 up"

View file

@ -3,7 +3,7 @@
# This scripts copied from Amnezia client to Docker container to /opt/amnezia and launched every time container starts # This scripts copied from Amnezia client to Docker container to /opt/amnezia and launched every time container starts
echo "Container startup" echo "Container startup"
ifconfig eth0:0 $SERVER_IP_ADDRESS netmask 255.255.255.255 up #ifconfig eth0:0 $SERVER_IP_ADDRESS netmask 255.255.255.255 up
iptables -A INPUT -i lo -j ACCEPT iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

View file

@ -4,12 +4,12 @@
#include <QFileInfo> #include <QFileInfo>
#include <QQuickItem> #include <QQuickItem>
#include <QRandomGenerator> #include <QRandomGenerator>
#include <QUrlQuery>
#include <QStandardPaths> #include <QStandardPaths>
#include <QUrlQuery>
#include "utilities.h"
#include "core/serialization/serialization.h"
#include "core/errorstrings.h" #include "core/errorstrings.h"
#include "core/serialization/serialization.h"
#include "utilities.h"
#ifdef Q_OS_ANDROID #ifdef Q_OS_ANDROID
#include "platforms/android/android_controller.h" #include "platforms/android/android_controller.h"
@ -96,36 +96,40 @@ bool ImportController::extractConfigFromData(QString data)
if (config.startsWith("vless://")) { if (config.startsWith("vless://")) {
m_configType = ConfigTypes::Xray; m_configType = ConfigTypes::Xray;
m_config = extractXrayConfig(Utils::JsonToString(serialization::vless::Deserialize(config, &prefix, &errormsg), m_config = extractXrayConfig(
QJsonDocument::JsonFormat::Compact), prefix); Utils::JsonToString(serialization::vless::Deserialize(config, &prefix, &errormsg), QJsonDocument::JsonFormat::Compact),
prefix);
return m_config.empty() ? false : true; return m_config.empty() ? false : true;
} }
if (config.startsWith("vmess://") && config.contains("@")) { if (config.startsWith("vmess://") && config.contains("@")) {
m_configType = ConfigTypes::Xray; m_configType = ConfigTypes::Xray;
m_config = extractXrayConfig(Utils::JsonToString(serialization::vmess_new::Deserialize(config, &prefix, &errormsg), m_config = extractXrayConfig(
QJsonDocument::JsonFormat::Compact), prefix); Utils::JsonToString(serialization::vmess_new::Deserialize(config, &prefix, &errormsg), QJsonDocument::JsonFormat::Compact),
prefix);
return m_config.empty() ? false : true; return m_config.empty() ? false : true;
} }
if (config.startsWith("vmess://")) { if (config.startsWith("vmess://")) {
m_configType = ConfigTypes::Xray; m_configType = ConfigTypes::Xray;
m_config = extractXrayConfig(Utils::JsonToString(serialization::vmess::Deserialize(config, &prefix, &errormsg), m_config = extractXrayConfig(
QJsonDocument::JsonFormat::Compact), prefix); Utils::JsonToString(serialization::vmess::Deserialize(config, &prefix, &errormsg), QJsonDocument::JsonFormat::Compact),
prefix);
return m_config.empty() ? false : true; return m_config.empty() ? false : true;
} }
if (config.startsWith("trojan://")) { if (config.startsWith("trojan://")) {
m_configType = ConfigTypes::Xray; m_configType = ConfigTypes::Xray;
m_config = extractXrayConfig(Utils::JsonToString(serialization::trojan::Deserialize(config, &prefix, &errormsg), m_config = extractXrayConfig(
QJsonDocument::JsonFormat::Compact), prefix); Utils::JsonToString(serialization::trojan::Deserialize(config, &prefix, &errormsg), QJsonDocument::JsonFormat::Compact),
prefix);
return m_config.empty() ? false : true; return m_config.empty() ? false : true;
} }
if (config.startsWith("ss://") && !config.contains("plugin=")) { if (config.startsWith("ss://") && !config.contains("plugin=")) {
m_configType = ConfigTypes::ShadowSocks; m_configType = ConfigTypes::ShadowSocks;
m_config = extractXrayConfig(Utils::JsonToString(serialization::ss::Deserialize(config, &prefix, &errormsg), m_config = extractXrayConfig(
QJsonDocument::JsonFormat::Compact), prefix); Utils::JsonToString(serialization::ss::Deserialize(config, &prefix, &errormsg), QJsonDocument::JsonFormat::Compact), prefix);
return m_config.empty() ? false : true; return m_config.empty() ? false : true;
} }
@ -354,20 +358,19 @@ QJsonObject ImportController::extractWireGuardConfig(const QString &data)
QJsonObject lastConfig; QJsonObject lastConfig;
lastConfig[config_key::config] = data; lastConfig[config_key::config] = data;
const static QRegularExpression hostNameAndPortRegExp("Endpoint = (.*):([0-9]*)"); auto url { QUrl::fromUserInput(configMap.value("Endpoint")) };
QRegularExpressionMatch hostNameAndPortMatch = hostNameAndPortRegExp.match(data);
QString hostName; QString hostName;
QString port; QString port;
if (hostNameAndPortMatch.hasCaptured(1)) { if (!url.host().isEmpty()) {
hostName = hostNameAndPortMatch.captured(1); hostName = url.host();
} else { } else {
qDebug() << "Key parameter 'Endpoint' is missing"; qDebug() << "Key parameter 'Endpoint' is missing or has an invalid format";
emit importErrorOccurred(ErrorCode::ImportInvalidConfigError, false); emit importErrorOccurred(ErrorCode::ImportInvalidConfigError, false);
return QJsonObject(); return QJsonObject();
} }
if (hostNameAndPortMatch.hasCaptured(2)) { if (url.port() != -1) {
port = hostNameAndPortMatch.captured(2); port = QString::number(url.port());
} else { } else {
port = protocols::wireguard::defaultPort; port = protocols::wireguard::defaultPort;
} }

View file

@ -60,9 +60,6 @@ PageType {
Layout.fillWidth: true Layout.fillWidth: true
headerText: qsTr("Server IP address [:port]") headerText: qsTr("Server IP address [:port]")
textFieldPlaceholderText: qsTr("255.255.255.255:22") textFieldPlaceholderText: qsTr("255.255.255.255:22")
textField.validator: RegularExpressionValidator {
regularExpression: InstallController.ipAddressPortRegExp()
}
textField.onFocusChanged: { textField.onFocusChanged: {
textField.text = textField.text.replace(/^\s+|\s+$/g, '') textField.text = textField.text.replace(/^\s+|\s+$/g, '')

View file

@ -233,7 +233,7 @@ void VpnConnection::connectToVpn(int serverIndex, const ServerCredentials &crede
} }
#endif #endif
m_remoteAddress = credentials.hostName; m_remoteAddress = NetworkUtilities::getIPAddress(credentials.hostName);
emit connectionStateChanged(Vpn::ConnectionState::Connecting); emit connectionStateChanged(Vpn::ConnectionState::Connecting);
m_vpnConfiguration = vpnConfiguration; m_vpnConfiguration = vpnConfiguration;