Skip to content

Commit

Permalink
resolve domains, display error if in use
Browse files Browse the repository at this point in the history
  • Loading branch information
vgmoose committed Jul 20, 2023
1 parent 4a8b297 commit 9ae20f8
Show file tree
Hide file tree
Showing 12 changed files with 101 additions and 112 deletions.
1 change: 1 addition & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ jobs:
- uses: actions/checkout@main
- name: Install Qt
uses: jurplel/install-qt-action@v3
- uses: ilammy/msvc-dev-cmd@v1
- name: Build ${{ matrix.platform }}
shell: bash
run: cd CaptiveDNS && qmake && make
1 change: 1 addition & 0 deletions CaptiveDNS/CaptiveDNS.pro
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ FORMS += \
cacheviewer.ui

CONFIG += mobility

MOBILITY =

DISTFILES += \
Expand Down
104 changes: 39 additions & 65 deletions CaptiveDNS/dnsserverwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,16 @@ You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */

Ui::DNSServerWindow* DNSServerWindow::mainUi = NULL;

DNSServerWindow::DNSServerWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::DNSServerWindow)
{
ui->setupUi(this);
qRegisterMetaType<ListEntry>("ListEntry");
qRegisterMetaType<std::vector<ListEntry>>("std::vector<ListEntry>");
qRegisterMetaType<QHostAddress>("QHostAddress");

DNSServerWindow::mainUi = ui;

settingspath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
QDir d{settingspath};
Expand Down Expand Up @@ -159,6 +163,39 @@ void DNSServerWindow::listeningIPsUpdate()

if(ipslist.size() > 0)
{
// sort the ipslist so that the first one is the one we want to respond with
// (eg. prioritize 192.168.x.x over 10.x.x.x, over 172.16.x.x, etc.)

// sort the list
std::sort(ipslist.begin(), ipslist.end());

// check for 10.x.x.x
for (int i = 0; i < ipslist.size(); i++)
{
if((ipslist[i] & 0xFF000000) == 0x0A000000)
{
// move it to the front
ipslist.prepend(ipslist[i]);
ipslist.remove(i+1);
break;
}
}

// check for 192.168.x.x
for (int i = 0; i < ipslist.size(); i++)
{
if((ipslist[i] & 0xFFFF0000) == 0xC0A80000)
{
// move it to the front
ipslist.prepend(ipslist[i]);
ipslist.remove(i+1);
break;
}
}

// really, which IP to use should be a choice in the UI
// but for now we'll just use the first one and sort the list

server->listeningIPs = ipslist;
}
if(ipv6slist.size() > 0)
Expand Down Expand Up @@ -498,7 +535,6 @@ bool DNSServerWindow::settingsLoad()

// blacklist only (allow all non-captive portal domains)
server->whitelistmode = false;
on_blacklistButton_clicked();

// no settings, so no initial mode
server->initialMode = false;
Expand Down Expand Up @@ -534,35 +570,7 @@ void DNSServerWindow::on_saveButton_clicked()

void DNSServerWindow::on_removeButton_clicked()
{
// auto selected = ui->dnslist->selectedItems();
// for(QTreeWidgetItem *i : selected)
// {
// if(server->whitelistmode)
// {
// for(int x = 0; x < server->whitelist.size(); x++)
// {
// if(i->text(1) == server->whitelist[x].hostname)
// {
// qDebug() << "Removing from whitelist:" << i->text(1);
// server->whitelist.remove(x);
// break;
// }
// }
// }
// else
// {
// for(int x = 0; x < server->blacklist.size(); x++)
// {
// if(i->text(1) == server->blacklist[x].hostname)
// {
// qDebug() << "Removing from blacklist:" << i->text(1);
// server->blacklist.remove(x);
// break;
// }
// }
// }
// }
// qDeleteAll(selected);
// blanked out
}

void DNSServerWindow::on_hostnameEdit_returnPressed()
Expand All @@ -578,41 +586,7 @@ void DNSServerWindow::on_ipEdit_returnPressed()
void DNSServerWindow::on_secondAddButton_clicked()
{
bool alreadyAdded = false;
// auto selected = ui->dnsqueries->selectedItems();
// if(server->whitelistmode)
// {
// for(QTreeWidgetItem *i : selected)
// {
// for(ListEntry &e : server->whitelist)
// {
// if(e.hostname == i->text(1))
// {
// alreadyAdded = true;
// break;
// }
// }

// if(!alreadyAdded)
// server->whitelist.append(ListEntry(i->text(1)));
// }
// }
// else
// {
// for(QTreeWidgetItem *i : selected)
// {
// for(ListEntry &e : server->blacklist)
// {
// if(e.hostname == i->text(1))
// {
// alreadyAdded = true;
// break;
// }
// }

// if(!alreadyAdded)
// server->blacklist.append(ListEntry(i->text(1)));
// }
// }
// blanked out
refreshList();
}
void DNSServerWindow::on_settingsButton_clicked()
Expand Down
3 changes: 3 additions & 0 deletions CaptiveDNS/dnsserverwindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ class DNSServerWindow : public QMainWindow
explicit DNSServerWindow(QWidget *parent = 0);
~DNSServerWindow();

static Ui::DNSServerWindow* mainUi;

signals:
void displayCache(const std::vector<DNSInfo> &cache);
void clearSources();
Expand Down Expand Up @@ -85,6 +87,7 @@ private slots:
void on_secondAddButton_clicked();
void on_settingsButton_clicked();
void on_cacheViewButton_clicked();


private:
Ui::DNSServerWindow *ui;
Expand Down
2 changes: 1 addition & 1 deletion CaptiveDNS/dnsserverwindow.ui
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<widget class="QLabel" name="dnsStatus">
<property name="text">
<string>CaptiveDNS is running!</string>
</property>
Expand Down
1 change: 1 addition & 0 deletions CaptiveDNS/messagesthread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ void MessagesThread::run()

if(data->dnsServer->startServer(QHostAddress::Any, data->dnsServerPort))
qDebug() << "DNS server started on address:" << data->dnsServer->serversock.localAddress() << "and port:" << data->dnsServer->serversock.localPort();

if(data->httpServer->startServer(QHostAddress::Any, data->httpServerPort))
qDebug() << "HTTP server started on address:" << data->httpServer->serverAddress() << "and port:" << data->httpServer->serverPort();

Expand Down
1 change: 1 addition & 0 deletions CaptiveDNS/messagesthread.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class MessagesThread : public QThread
signals:
void serversInitialized();
void androidInit();
void displayErrorPopup(QString error);
};

#endif // MESSAGESTHREAD_H
89 changes: 45 additions & 44 deletions CaptiveDNS/smalldnsserver.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
#include "smalldnsserver.h"

#include <QMessageBox>
#include <iostream>
#include "dnsserverwindow.h"
#include "ui_dnsserverwindow.h"


/* YourFriendlyDNS - A really awesome multi-platform (lin,win,mac,android) local caching and proxying dns server!
Copyright (C) 2018 softwareengineer1 @ github.com/softwareengineer1
Support my work by sending me some Bitcoin or Bitcoin Cash in the value of what you valued one or more of my software projects,
Expand Down Expand Up @@ -73,9 +79,33 @@ SmallDNSServer::SmallDNSServer(QObject *parent)
// connect(dnscrypt, &DNSCrypt::decryptedLookupDoneSendResponseNow, this, &SmallDNSServer::decryptedLookupDoneSendResponseNow);
}

void SmallDNSServer::displayErrorPopup(QString error)
{
// run code on the main thread
// TODO: not working for some reason, crashes with an error about main threads still
// QMetaObject::invokeMethod(this, [error]() {
// QMessageBox::critical(0, "Error", error);
// });

QString msg = "Error: " + error + "\n(Is another DNS server already running?)";
DNSServerWindow::mainUi->dnsStatus->setText(msg);
DNSServerWindow::mainUi->dnsStatus->setStyleSheet("color: red");

}

bool SmallDNSServer::startServer(QHostAddress address, quint16 port, bool reuse)
{
return serversock.bind(address, port, reuse ? QUdpSocket::ReuseAddressHint : QUdpSocket::DefaultForPlatform);
bool res = serversock.bind(address, port, reuse ? QUdpSocket::ReuseAddressHint : QUdpSocket::DefaultForPlatform);

printf("SmallDNSServer::startServer() %s:%d\n", address.toString().toUtf8().data(), port);
printf("SmallDNSServer::startServer() %s\n", res ? "success" : "failed");
if (!res) {
printf("SmallDNSServer::startServer() %s\n", serversock.errorString().toUtf8().data());
// display qt error popup
emit displayErrorPopup(serversock.errorString());
}

return res;
}

void SmallDNSServer::clearDNSCache()
Expand Down Expand Up @@ -240,30 +270,16 @@ void SmallDNSServer::processDNSRequests()
bool shouldCacheDomain, useDedicatedDNSCryptProviderToResolveV2And3Hosts = false;
quint32 customIP = ipToRespondWith;
std::string domain = (char*)dns.domainString.toUtf8().data();
if(whitelistmode)
{
ListEntry *whiteListed = getListEntry(domain, TYPE_WHITELIST);
if(whiteListed)
{
qDebug() << "Matched WhiteList!" << whiteListed->hostname << "to:" << dns.domainString;
//It's whitelist mode and in the whitelist, so it should return a real IP! Unless you've manually specified an IP
if(whiteListed->ip != 0)
customIP = whiteListed->ip;
}
shouldCacheDomain = (whiteListed != nullptr);
}
else
ListEntry *blackListed = getListEntry(domain, TYPE_BLACKLIST);
if(blackListed)
{
ListEntry *blackListed = getListEntry(domain, TYPE_BLACKLIST);
if(blackListed)
{
qDebug() << "Matched BlackList!" << blackListed->hostname << "to:" << dns.domainString;
//It's blacklist mode and in the blacklist, so it should return your custom IP! And your manually specified one if you did specify a particular one
if(blackListed->ip != 0)
customIP = blackListed->ip;
}
shouldCacheDomain = (blackListed == nullptr);
qDebug() << "Matched BlackList!" << blackListed->hostname << "to:" << dns.domainString;
//It's blacklist mode and in the blacklist, so it should return your custom IP! And your manually specified one if you did specify a particular one
if(blackListed->ip != 0)
customIP = blackListed->ip;
}
shouldCacheDomain = (blackListed == nullptr);

if(shouldCacheDomain)
{
//Trying to exclude local hostnames from leaking
Expand Down Expand Up @@ -313,27 +329,12 @@ void SmallDNSServer::processDNSRequests()
dns.senderPort = senderPort;
dns.ttl = dnsTTL;

if(dnscryptEnabled)
{
qDebug() << "Making encrypted DNS request type:" << dns.question.qtype << "for domain:" << dns.domainString << "request id:" << dns.header.id << "datagram:" << datagram;
if(useDedicatedDNSCryptProviderToResolveV2And3Hosts)
{
// dnscrypt->setProvider(dedicatedDNSCrypter);
qDebug() << "Using dedicated DNSCrypt provider to resolve DoH/DoTLS provider's host:" << dns.domainString;
}
// else
// dnscrypt->setProvider(selectRandomDNSCryptServer());

// dnscrypt->makeEncryptedRequest(dns);
}
else
{
qDebug() << "Making DNS request type:" << dns.question.qtype << "for domain:" << dns.domainString << "request id:" << dns.header.id << "datagram:" << datagram;
QString server = selectRandomDNSServer();
quint16 serverPort = DNSInfo::extractPort(server);
if(serverPort == 0 || serverPort == 443) serverPort = 53;
clientsock.writeDatagram(datagram, QHostAddress(server), serverPort);
}

qDebug() << "Making DNS request type:" << dns.question.qtype << "for domain:" << dns.domainString << "request id:" << dns.header.id << "datagram:" << datagram;
QString server = selectRandomDNSServer();
quint16 serverPort = DNSInfo::extractPort(server);
if(serverPort == 0 || serverPort == 443) serverPort = 53;
clientsock.writeDatagram(datagram, QHostAddress(server), serverPort);

InitialResponse *ir = new InitialResponse(dns);
if(ir)
Expand Down
6 changes: 6 additions & 0 deletions CaptiveDNS/smalldnsserver.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ bool GeneralTextCompare(
char cAltTerminator = '\0' // For function names, for example, you can stop at the first '('
);

namespace Ui {
class DNSServerWindow;
}

class SmallDNSServer : public QObject
{
Q_OBJECT
Expand All @@ -98,6 +102,7 @@ class SmallDNSServer : public QObject
// DNSCrypt *dnscrypt;

private:
Ui::DNSServerWindow *ui;
ListEntry* getListEntry(const std::string &tame, int listType);
DNSInfo* getCachedEntry(const QString &byDomain, quint16 andType);
void parseAndRespond(QByteArray &datagram, DNSInfo &dns);
Expand All @@ -119,6 +124,7 @@ public slots:
void clearDNSCache();
void deleteEntriesFromCache(std::vector<ListEntry> entries);
void decryptedLookupDoneSendResponseNow(QByteArray decryptedResponse, DNSInfo &dns);
void displayErrorPopup(QString error);

private slots:
void processDNSRequests();
Expand Down
2 changes: 1 addition & 1 deletion CaptiveDNS/smallhttpserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ void SmallHTTPServer::createLanding()
<li><a href=\"https://duckduckgo.com\">DuckDuckGo</a></li>\n\
<li><a href=\"https://startpage.com\">StartPage</a></li>\n\
</ul>\n\
<p>To customize this page, press \"Edit Landing Page\" in the CaptiveDNS app, and then open `landing.html` in a text editor.</p>\n\
<p>To customize this page, press \"Edit Landing Page\" in the CaptiveDNS app, and then open <code>landing.html</code> in a text editor.</p>\n\
<p>For source code and license information, see <a href=\"https://github.com/browsedns/captivedns\">here</a>.</p>\n\
<p><a href=\"javascript:window.location.reload();\">Reload Page</a></p>\n\
</body></html>";
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ An app to help display a [captive portal](https://en.wikipedia.org/wiki/Captive_
Based on [YourFriendlyDNS](https://github.com/softwareengineer1/YourFriendlyDNS/), which contains many more advanced options for other self-hosted DNS use cases.

## Screenshots
<img src="preview.png" width="317" alt="CaptiveDNS Screenshot" />
<img src="preview.png" width="317" alt="CaptiveDNS Window Screenshot" /> <img src="preview2.png" width="220" alt="CaptiveDNS Landing page" />


## Captured Domains

Expand Down
Binary file added preview2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 9ae20f8

Please sign in to comment.