├── preview.png ├── preview2.png ├── CaptiveDNS ├── gear.gif ├── minus.png ├── plus.png ├── newBCHaddr_small.png ├── newBTCaddr_small.png ├── images.qrc ├── index.html ├── main.cpp ├── cacheviewer.ui ├── indexhtml.h ├── indexhtml.cpp ├── cacheviewer.h ├── smallhttpserver.h ├── messagesthread.h ├── indexhtml.ui ├── CaptiveDNS.pro ├── initialresponse.h ├── dnsserverwindow.ui ├── messagesthread.cpp ├── dnsserverwindow.h ├── cacheviewer.cpp ├── androidsuop.h ├── smalldnsserver.h ├── settingswindow.h ├── dnsinfo.h ├── smallhttpserver.cpp ├── initialresponse.cpp ├── settingswindow.cpp ├── settingswindow.ui ├── buffer.h ├── GPLv2.txt ├── dnsserverwindow.cpp └── smalldnsserver.cpp ├── .gitignore ├── .github └── workflows │ └── main.yml ├── README.md └── LICENSE /preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/browseDNS/CaptiveDNS/HEAD/preview.png -------------------------------------------------------------------------------- /preview2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/browseDNS/CaptiveDNS/HEAD/preview2.png -------------------------------------------------------------------------------- /CaptiveDNS/gear.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/browseDNS/CaptiveDNS/HEAD/CaptiveDNS/gear.gif -------------------------------------------------------------------------------- /CaptiveDNS/minus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/browseDNS/CaptiveDNS/HEAD/CaptiveDNS/minus.png -------------------------------------------------------------------------------- /CaptiveDNS/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/browseDNS/CaptiveDNS/HEAD/CaptiveDNS/plus.png -------------------------------------------------------------------------------- /CaptiveDNS/newBCHaddr_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/browseDNS/CaptiveDNS/HEAD/CaptiveDNS/newBCHaddr_small.png -------------------------------------------------------------------------------- /CaptiveDNS/newBTCaddr_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/browseDNS/CaptiveDNS/HEAD/CaptiveDNS/newBTCaddr_small.png -------------------------------------------------------------------------------- /CaptiveDNS/images.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | newBCHaddr_small.png 4 | newBTCaddr_small.png 5 | minus.png 6 | plus.png 7 | gear.gif 8 | 9 | 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | 3 | *.app 4 | *.DS_Store 5 | *.qmake* 6 | 7 | *.slo 8 | *.lo 9 | *.o 10 | *.a 11 | *.la 12 | *.lai 13 | *.so 14 | *.so.* 15 | *.dll 16 | *.dylib 17 | 18 | # Qt-es 19 | object_script.*.Release 20 | object_script.*.Debug 21 | *_plugin_import.cpp 22 | /.qmake.cache 23 | /.qmake.stash 24 | *.pro.user 25 | *.pro.user.* 26 | *.qbs.user 27 | *.qbs.user.* 28 | *.moc 29 | moc_*.cpp 30 | moc_*.h 31 | qrc_*.cpp 32 | ui_*.h 33 | *.qmlc 34 | *.jsc 35 | Makefile* 36 | *build-* 37 | *.qm 38 | *.prl 39 | 40 | # Qt unit tests 41 | target_wrapper.* 42 | 43 | # QtCreator 44 | *.autosave 45 | 46 | # QtCreator Qml 47 | *.qmlproject.user 48 | *.qmlproject.user.* 49 | 50 | # QtCreator CMake 51 | CMakeLists.txt.user* 52 | 53 | # QtCreator 4.8< compilation database 54 | compile_commands.json 55 | 56 | # QtCreator local machine specific files for imported projects 57 | *creator.user* 58 | 59 | *_qmlcache.qrc 60 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Build CaptiveDNS 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - ci-release 8 | pull_request: 9 | branches: 10 | - main 11 | 12 | jobs: 13 | all: 14 | strategy: 15 | matrix: 16 | os: [ubuntu, windows, macos] 17 | runs-on: ${{ matrix.os }}-latest 18 | steps: 19 | - uses: actions/checkout@main 20 | - name: Install Qt 21 | uses: jurplel/install-qt-action@v3 22 | - uses: ilammy/msvc-dev-cmd@v1 23 | - name: Build for ${{ matrix.os }} 24 | shell: bash 25 | run: cd CaptiveDNS && qmake && (make || nmake || (rm /usr/bin/link && nmake)) 26 | - name: Bundle for ${{ matrix.os }} 27 | shell: bash 28 | run: | 29 | if [[ "${{ matrix.os }}" == "macos" ]]; then 30 | macdeployqt ./CaptiveDNS/CaptiveDNS.app 31 | zip -r ./CaptiveDNS-${{ matrix.os }}.zip ./CaptiveDNS/CaptiveDNS.app 32 | elif [[ "${{ matrix.os }}" == "windows" ]]; then 33 | mkdir -p ./CaptiveDNS/CaptiveDNS 34 | cp ./CaptiveDNS/release/CaptiveDNS.exe ./CaptiveDNS/CaptiveDNS 35 | windeployqt ./CaptiveDNS/CaptiveDNS/CaptiveDNS.exe 36 | choco install -y zip 37 | cd ./CaptiveDNS/CaptiveDNS/ 38 | zip -r ../../CaptiveDNS-${{ matrix.os }}.zip . 39 | else 40 | zip -r ./CaptiveDNS-${{ matrix.os }}.zip ./CaptiveDNS/CaptiveDNS 41 | fi 42 | - uses: actions/upload-artifact@v4 43 | with: 44 | name: CaptiveDNS-${{ matrix.os }} 45 | path: ./CaptiveDNS-${{ matrix.os }}.zip -------------------------------------------------------------------------------- /CaptiveDNS/index.html: -------------------------------------------------------------------------------- 1 | 2 | CaptiveDNS 3 | 20 | 21 |

CaptiveDNS

22 |

Welcome to the CaptiveDNS landing page!

23 |

Quick Links:

24 | 31 |

To customize this page, edit index.html in the same directory as the CaptiveDNS app.

32 |

For source code and license information, see here.

33 |

Reload Page

34 | 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CaptiveDNS 2 | An app to help display a [captive portal](https://en.wikipedia.org/wiki/Captive_portal) browser to other devices on the network via DNS. Run this app on your computer, enter the DNS in the target device settings, and the captive portal should be displayed. 3 | 4 | This program is based on a stripped down verison of [YourFriendlyDNS](https://github.com/softwareengineer1/YourFriendlyDNS/). YourFriendlyDNS contains many more advanced options for self-hosted DNS and HTTP servers, and should be used instead of CaptiveDNS in those use cases. 5 | 6 | Download CaptiveDNS from on the [Releases](https://github.com/browseDNS/CaptiveDNS/releases) page. Nightly builds from the latest commits can be found [here](https://nightly.link/browsedns/captivedns/workflows/main/main). 7 | 8 | ## Screenshots 9 | CaptiveDNS Window Screenshot CaptiveDNS Landing page 10 | 11 | 12 | ## Captured Domains 13 | 14 | If a captive portal test domain is missing here, please file an issue and it will be added to the redirection list. 15 | 16 | ``` 17 | ctest.cdn.nintendo.net 18 | conntest.nintendowifi.net 19 | detectportal.firefox.com 20 | connectivitycheck.gstatic.com 21 | connectivitycheck.android.com 22 | clients1.google.com 23 | clients3.google.com 24 | captive.apple.com 25 | ctest.p01.ctest.srv.nintendo.net 26 | www.msftconnecttest.com 27 | ``` 28 | 29 | This list of domains cannot be configured within CaptiveDNS. To customize it further, check out [YourFriendlyDNS](https://github.com/softwareengineer1/YourFriendlyDNS/). 30 | 31 | ## Compiling 32 | 33 | ``` 34 | git clone git@github.com:BrowseDNS/CaptiveDNS.git 35 | cd CaptiveDNS/CaptiveDNS 36 | qmake 37 | make 38 | ``` 39 | 40 | ## License 41 | This software is licensed under the GPLv2. 42 | 43 | If you like this software, please support the YourFriendlyDNS author, [softwareengineer1](https://github.com/softwareengineer1), through one of the below methods! 44 | 45 | ``` 46 | BCH: bitcoincash:qzh3knl0xeyrzrxm5paenewsmkm8r4t76glzxmzpqs 47 | BTC: 1279WngWQUTV56UcTvzVAnNdR3Z7qb6R8j 48 | ``` 49 | -------------------------------------------------------------------------------- /CaptiveDNS/main.cpp: -------------------------------------------------------------------------------- 1 | #include "dnsserverwindow.h" 2 | #include 3 | 4 | /* YourFriendlyDNS - A really awesome multi-platform (lin,win,mac,android) local caching and proxying dns server! 5 | Copyright (C) 2018 softwareengineer1 @ github.com/softwareengineer1 6 | 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, 7 | so I can keep bringing you great free and open software and continue to do so for a long time! 8 | I'm going entirely 100% free software this year in 2018 (and onwards I want to) :) 9 | Everything I make will be released under a free software license! That's my promise! 10 | If you want to contact me another way besides through github, insert your message into the blockchain with a BCH/BTC UTXO! ^_^ 11 | Thank you for your support! 12 | BCH: bitcoincash:qzh3knl0xeyrzrxm5paenewsmkm8r4t76glzxmzpqs 13 | BTC: 1279WngWQUTV56UcTvzVAnNdR3Z7qb6R8j 14 | (These are the payment methods I currently accept, 15 | if you want to support me via another cryptocurrency let me know and I'll probably start accepting that one too) 16 | 17 | This program is free software; you can redistribute it and/or modify 18 | it under the terms of the GNU General Public License as published by 19 | the Free Software Foundation; either version 2 of the License, or 20 | (at your option) any later version. 21 | 22 | This program is distributed in the hope that it will be useful, 23 | but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | GNU General Public License for more details. 26 | 27 | You should have received a copy of the GNU General Public License along 28 | with this program; if not, write to the Free Software Foundation, Inc., 29 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ 30 | 31 | int main(int argc, char *argv[]) 32 | { 33 | QApplication a(argc, argv); 34 | 35 | a.setOrganizationDomain("CaptiveDNS.domain"); 36 | a.setApplicationName("CaptiveDNS"); 37 | 38 | DNSServerWindow *w = new DNSServerWindow(); 39 | w->show(); 40 | 41 | 42 | int r = a.exec(); 43 | 44 | delete w; 45 | return r; 46 | } 47 | -------------------------------------------------------------------------------- /CaptiveDNS/cacheviewer.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | CacheViewer 4 | 5 | 6 | 7 | 0 8 | 0 9 | 803 10 | 588 11 | 12 | 13 | 14 | Cache Viewer 15 | 16 | 17 | 18 | 19 | 20 | 21 | true 22 | 23 | 24 | QAbstractItemView::MultiSelection 25 | 26 | 27 | 0 28 | 29 | 30 | true 31 | 32 | 33 | true 34 | 35 | 36 | 160 37 | 38 | 39 | 40 | Hostname 41 | 42 | 43 | 44 | 45 | Type 46 | 47 | 48 | 49 | 50 | Expiry 51 | 52 | 53 | 54 | 55 | Data 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | Remove Selected 64 | 65 | 66 | 67 | 68 | 69 | 70 | OK 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /CaptiveDNS/indexhtml.h: -------------------------------------------------------------------------------- 1 | #ifndef INDEXHTML_H 2 | #define INDEXHTML_H 3 | 4 | #include 5 | 6 | /* YourFriendlyDNS - A really awesome multi-platform (lin,win,mac,android) local caching and proxying dns server! 7 | Copyright (C) 2018 softwareengineer1 @ github.com/softwareengineer1 8 | 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, 9 | so I can keep bringing you great free and open software and continue to do so for a long time! 10 | I'm going entirely 100% free software this year in 2018 (and onwards I want to) :) 11 | Everything I make will be released under a free software license! That's my promise! 12 | If you want to contact me another way besides through github, insert your message into the blockchain with a BCH/BTC UTXO! ^_^ 13 | Thank you for your support! 14 | BCH: bitcoincash:qzh3knl0xeyrzrxm5paenewsmkm8r4t76glzxmzpqs 15 | BTC: 1279WngWQUTV56UcTvzVAnNdR3Z7qb6R8j 16 | (These are the payment methods I currently accept, 17 | if you want to support me via another cryptocurrency let me know and I'll probably start accepting that one too) 18 | 19 | This program is free software; you can redistribute it and/or modify 20 | it under the terms of the GNU General Public License as published by 21 | the Free Software Foundation; either version 2 of the License, or 22 | (at your option) any later version. 23 | 24 | This program is distributed in the hope that it will be useful, 25 | but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 | GNU General Public License for more details. 28 | 29 | You should have received a copy of the GNU General Public License along 30 | with this program; if not, write to the Free Software Foundation, Inc., 31 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ 32 | 33 | namespace Ui { 34 | class IndexHTML; 35 | } 36 | 37 | class IndexHTML : public QMainWindow 38 | { 39 | Q_OBJECT 40 | 41 | public: 42 | explicit IndexHTML(QWidget *parent = 0); 43 | ~IndexHTML(); 44 | void setHTML(QString &html); 45 | QString getHTML(); 46 | 47 | signals: 48 | void htmlChanged(QString &html); 49 | 50 | private slots: 51 | void on_okButton_clicked(); 52 | 53 | private: 54 | Ui::IndexHTML *ui; 55 | }; 56 | 57 | #endif // INDEXHTML_H 58 | -------------------------------------------------------------------------------- /CaptiveDNS/indexhtml.cpp: -------------------------------------------------------------------------------- 1 | #include "indexhtml.h" 2 | #include "ui_indexhtml.h" 3 | 4 | /* YourFriendlyDNS - A really awesome multi-platform (lin,win,mac,android) local caching and proxying dns server! 5 | Copyright (C) 2018 softwareengineer1 @ github.com/softwareengineer1 6 | 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, 7 | so I can keep bringing you great free and open software and continue to do so for a long time! 8 | I'm going entirely 100% free software this year in 2018 (and onwards I want to) :) 9 | Everything I make will be released under a free software license! That's my promise! 10 | If you want to contact me another way besides through github, insert your message into the blockchain with a BCH/BTC UTXO! ^_^ 11 | Thank you for your support! 12 | BCH: bitcoincash:qzh3knl0xeyrzrxm5paenewsmkm8r4t76glzxmzpqs 13 | BTC: 1279WngWQUTV56UcTvzVAnNdR3Z7qb6R8j 14 | (These are the payment methods I currently accept, 15 | if you want to support me via another cryptocurrency let me know and I'll probably start accepting that one too) 16 | 17 | This program is free software; you can redistribute it and/or modify 18 | it under the terms of the GNU General Public License as published by 19 | the Free Software Foundation; either version 2 of the License, or 20 | (at your option) any later version. 21 | 22 | This program is distributed in the hope that it will be useful, 23 | but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | GNU General Public License for more details. 26 | 27 | You should have received a copy of the GNU General Public License along 28 | with this program; if not, write to the Free Software Foundation, Inc., 29 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ 30 | 31 | IndexHTML::IndexHTML(QWidget *parent) : QMainWindow(parent),ui(new Ui::IndexHTML) 32 | { 33 | ui->setupUi(this); 34 | } 35 | 36 | IndexHTML::~IndexHTML() 37 | { 38 | delete ui; 39 | } 40 | 41 | void IndexHTML::setHTML(QString &html) 42 | { 43 | ui->html->clear(); 44 | ui->html->appendPlainText(html); 45 | } 46 | 47 | QString IndexHTML::getHTML() 48 | { 49 | return ui->html->toPlainText(); 50 | } 51 | void IndexHTML::on_okButton_clicked() 52 | { 53 | QString html = ui->html->toPlainText(); 54 | emit htmlChanged(html); 55 | hide(); 56 | } 57 | -------------------------------------------------------------------------------- /CaptiveDNS/cacheviewer.h: -------------------------------------------------------------------------------- 1 | #ifndef CACHEVIEWER_H 2 | #define CACHEVIEWER_H 3 | 4 | #include 5 | #include "dnsinfo.h" 6 | 7 | /* YourFriendlyDNS - A really awesome multi-platform (lin,win,mac,android) local caching and proxying dns server! 8 | Copyright (C) 2018 softwareengineer1 @ github.com/softwareengineer1 9 | 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, 10 | so I can keep bringing you great free and open software and continue to do so for a long time! 11 | I'm going entirely 100% free software this year in 2018 (and onwards I want to) :) 12 | Everything I make will be released under a free software license! That's my promise! 13 | If you want to contact me another way besides through github, insert your message into the blockchain with a BCH/BTC UTXO! ^_^ 14 | Thank you for your support! 15 | BCH: bitcoincash:qzh3knl0xeyrzrxm5paenewsmkm8r4t76glzxmzpqs 16 | BTC: 1279WngWQUTV56UcTvzVAnNdR3Z7qb6R8j 17 | (These are the payment methods I currently accept, 18 | if you want to support me via another cryptocurrency let me know and I'll probably start accepting that one too) 19 | 20 | This program is free software; you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation; either version 2 of the License, or 23 | (at your option) any later version. 24 | 25 | This program is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License along 31 | with this program; if not, write to the Free Software Foundation, Inc., 32 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ 33 | 34 | namespace Ui { 35 | class CacheViewer; 36 | } 37 | 38 | class CacheViewer : public QMainWindow 39 | { 40 | Q_OBJECT 41 | 42 | public: 43 | explicit CacheViewer(QWidget *parent = 0); 44 | ~CacheViewer(); 45 | 46 | signals: 47 | void deleteEntriesFromCache(std::vector entries); 48 | 49 | public slots: 50 | void displayCache(const std::vector &cache); 51 | 52 | private slots: 53 | void on_okButton_clicked(); 54 | void on_removeButton_clicked(); 55 | 56 | private: 57 | Ui::CacheViewer *ui; 58 | }; 59 | 60 | #endif // CACHEVIEWER_H 61 | -------------------------------------------------------------------------------- /CaptiveDNS/smallhttpserver.h: -------------------------------------------------------------------------------- 1 | #ifndef SMALLHTTPSERVER_H 2 | #define SMALLHTTPSERVER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | /* YourFriendlyDNS - A really awesome multi-platform (lin,win,mac,android) local caching and proxying dns server! 10 | Copyright (C) 2018 softwareengineer1 @ github.com/softwareengineer1 11 | 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, 12 | so I can keep bringing you great free and open software and continue to do so for a long time! 13 | I'm going entirely 100% free software this year in 2018 (and onwards I want to) :) 14 | Everything I make will be released under a free software license! That's my promise! 15 | If you want to contact me another way besides through github, insert your message into the blockchain with a BCH/BTC UTXO! ^_^ 16 | Thank you for your support! 17 | BCH: bitcoincash:qzh3knl0xeyrzrxm5paenewsmkm8r4t76glzxmzpqs 18 | BTC: 1279WngWQUTV56UcTvzVAnNdR3Z7qb6R8j 19 | (These are the payment methods I currently accept, 20 | if you want to support me via another cryptocurrency let me know and I'll probably start accepting that one too) 21 | 22 | This program is free software; you can redistribute it and/or modify 23 | it under the terms of the GNU General Public License as published by 24 | the Free Software Foundation; either version 2 of the License, or 25 | (at your option) any later version. 26 | 27 | This program is distributed in the hope that it will be useful, 28 | but WITHOUT ANY WARRANTY; without even the implied warranty of 29 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 30 | GNU General Public License for more details. 31 | 32 | You should have received a copy of the GNU General Public License along 33 | with this program; if not, write to the Free Software Foundation, Inc., 34 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ 35 | 36 | class SmallHTTPServer : public QTcpServer 37 | { 38 | Q_OBJECT 39 | public: 40 | explicit SmallHTTPServer(QObject *parent = nullptr); 41 | bool startServer(QHostAddress address = QHostAddress::AnyIPv4, quint16 port = 80); 42 | void setHTML(QString html); 43 | 44 | QString getIndexHTMLPath(); 45 | QString getHTMLContent(); 46 | void createLanding(); 47 | 48 | private: 49 | QString html, response_header, contentType, encodingType, acceptRanges, connection; 50 | 51 | private slots: 52 | void returnIndexPage(); 53 | }; 54 | 55 | #endif // SMALLHTTPSERVER_H 56 | -------------------------------------------------------------------------------- /CaptiveDNS/messagesthread.h: -------------------------------------------------------------------------------- 1 | #ifndef MESSAGESTHREAD_H 2 | #define MESSAGESTHREAD_H 3 | 4 | #include 5 | #include 6 | #include "smalldnsserver.h" 7 | #include "smallhttpserver.h" 8 | 9 | /* YourFriendlyDNS - A really awesome multi-platform (lin,win,mac,android) local caching and proxying dns server! 10 | Copyright (C) 2018 softwareengineer1 @ github.com/softwareengineer1 11 | 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, 12 | so I can keep bringing you great free and open software and continue to do so for a long time! 13 | I'm going entirely 100% free software this year in 2018 (and onwards I want to) :) 14 | Everything I make will be released under a free software license! That's my promise! 15 | If you want to contact me another way besides through github, insert your message into the blockchain with a BCH/BTC UTXO! ^_^ 16 | Thank you for your support! 17 | BCH: bitcoincash:qzh3knl0xeyrzrxm5paenewsmkm8r4t76glzxmzpqs 18 | BTC: 1279WngWQUTV56UcTvzVAnNdR3Z7qb6R8j 19 | (These are the payment methods I currently accept, 20 | if you want to support me via another cryptocurrency let me know and I'll probably start accepting that one too) 21 | 22 | This program is free software; you can redistribute it and/or modify 23 | it under the terms of the GNU General Public License as published by 24 | the Free Software Foundation; either version 2 of the License, or 25 | (at your option) any later version. 26 | 27 | This program is distributed in the hope that it will be useful, 28 | but WITHOUT ANY WARRANTY; without even the implied warranty of 29 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 30 | GNU General Public License for more details. 31 | 32 | You should have received a copy of the GNU General Public License along 33 | with this program; if not, write to the Free Software Foundation, Inc., 34 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ 35 | 36 | class AppData 37 | { 38 | public: 39 | static AppData* instance; 40 | SmallDNSServer *dnsServer; 41 | SmallHTTPServer *httpServer; 42 | quint16 dnsServerPort, httpServerPort; 43 | 44 | AppData(); 45 | static AppData* get(); 46 | }; 47 | 48 | class MessagesThread : public QThread 49 | { 50 | Q_OBJECT 51 | public: 52 | ~MessagesThread(); 53 | AppData *data; 54 | void run(); 55 | 56 | signals: 57 | void serversInitialized(); 58 | void androidInit(); 59 | void displayErrorPopup(QString error); 60 | }; 61 | 62 | #endif // MESSAGESTHREAD_H 63 | -------------------------------------------------------------------------------- /CaptiveDNS/indexhtml.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | IndexHTML 4 | 5 | 6 | 7 | 0 8 | 0 9 | 800 10 | 600 11 | 12 | 13 | 14 | Edit Landing Page 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | Reload from Disk 26 | 27 | 28 | 29 | 30 | 31 | 32 | Show in File Browser 33 | 34 | 35 | 36 | 37 | 38 | 39 | Reset to Default 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | Courier New 50 | 51 | 52 | 53 | <html> 54 | HTML content goes here 55 | </html> 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | Cancel 65 | 66 | 67 | 68 | 69 | 70 | 71 | Save and Apply 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /CaptiveDNS/CaptiveDNS.pro: -------------------------------------------------------------------------------- 1 | #------------------------------------------------- 2 | # 3 | # Project created by QtCreator 2018-04-06T03:09:54 4 | # 5 | #------------------------------------------------- 6 | 7 | QT += core gui network 8 | 9 | CONFIG += c++14 openssl 10 | 11 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 12 | 13 | TARGET = CaptiveDNS 14 | TEMPLATE = app 15 | 16 | VERSION = 2.1.3 17 | QMAKE_TARGET_COMPANY = BrowseDNS 18 | QMAKE_TARGET_PRODUCT = CaptiveDNS 19 | QMAKE_TARGET_DESCRIPTION = captive portal redirector 20 | QMAKE_TARGET_COPYRIGHT = 2023 21 | DEFINES += APP_VERSION=\\\"$$VERSION\\\" 22 | 23 | # The following define makes your compiler emit warnings if you use 24 | # any feature of Qt which has been marked as deprecated (the exact warnings 25 | # depend on your compiler). Please consult the documentation of the 26 | # deprecated API in order to know how to port your code away from it. 27 | DEFINES += QT_DEPRECATED_WARNINGS 28 | #comment this next line out if you need to debug it if somethings not quite right (you'll get the qDebug() output then [and on macOS it has to be a debug build too for some reason]) 29 | DEFINES += QT_NO_DEBUG_OUTPUT 30 | 31 | # You can also make your code fail to compile if you use deprecated APIs. 32 | # In order to do so, uncomment the following line. 33 | # You can also select to disable deprecated APIs only up to a certain version of Qt. 34 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 35 | 36 | SOURCES += \ 37 | main.cpp \ 38 | dnsserverwindow.cpp \ 39 | smalldnsserver.cpp \ 40 | settingswindow.cpp \ 41 | initialresponse.cpp \ 42 | indexhtml.cpp \ 43 | smallhttpserver.cpp \ 44 | messagesthread.cpp \ 45 | cacheviewer.cpp 46 | 47 | HEADERS += \ 48 | dnsserverwindow.h \ 49 | smalldnsserver.h \ 50 | settingswindow.h \ 51 | initialresponse.h \ 52 | indexhtml.h \ 53 | smallhttpserver.h \ 54 | androidsuop.h \ 55 | messagesthread.h \ 56 | cacheviewer.h \ 57 | dnsinfo.h \ 58 | buffer.h 59 | 60 | FORMS += \ 61 | dnsserverwindow.ui \ 62 | settingswindow.ui \ 63 | indexhtml.ui \ 64 | cacheviewer.ui 65 | 66 | CONFIG += mobility 67 | 68 | MOBILITY = 69 | 70 | DISTFILES += \ 71 | GPLv2.txt \ 72 | android/AndroidManifest.xml \ 73 | android/gradle/wrapper/gradle-wrapper.jar \ 74 | android/gradlew \ 75 | android/res/values/libs.xml \ 76 | android/build.gradle \ 77 | android/gradle/wrapper/gradle-wrapper.properties \ 78 | android/gradlew.bat 79 | 80 | RESOURCES += \ 81 | images.qrc 82 | 83 | ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android 84 | 85 | -------------------------------------------------------------------------------- /CaptiveDNS/initialresponse.h: -------------------------------------------------------------------------------- 1 | #ifndef INITIALRESPONSE_H 2 | #define INITIALRESPONSE_H 3 | 4 | #include 5 | #include 6 | #include "dnsinfo.h" 7 | 8 | /* YourFriendlyDNS - A really awesome multi-platform (lin,win,mac,android) local caching and proxying dns server! 9 | Copyright (C) 2018 softwareengineer1 @ github.com/softwareengineer1 10 | 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, 11 | so I can keep bringing you great free and open software and continue to do so for a long time! 12 | I'm going entirely 100% free software this year in 2018 (and onwards I want to) :) 13 | Everything I make will be released under a free software license! That's my promise! 14 | If you want to contact me another way besides through github, insert your message into the blockchain with a BCH/BTC UTXO! ^_^ 15 | Thank you for your support! 16 | BCH: bitcoincash:qzh3knl0xeyrzrxm5paenewsmkm8r4t76glzxmzpqs 17 | BTC: 1279WngWQUTV56UcTvzVAnNdR3Z7qb6R8j 18 | (These are the payment methods I currently accept, 19 | if you want to support me via another cryptocurrency let me know and I'll probably start accepting that one too) 20 | 21 | This program is free software; you can redistribute it and/or modify 22 | it under the terms of the GNU General Public License as published by 23 | the Free Software Foundation; either version 2 of the License, or 24 | (at your option) any later version. 25 | 26 | This program is distributed in the hope that it will be useful, 27 | but WITHOUT ANY WARRANTY; without even the implied warranty of 28 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 29 | GNU General Public License for more details. 30 | 31 | You should have received a copy of the GNU General Public License along 32 | with this program; if not, write to the Free Software Foundation, Inc., 33 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ 34 | 35 | 36 | 37 | void morphRequestIntoARecordResponse(QByteArray &dnsrequest, quint32 responseIP, quint32 spliceOffset, quint32 ttl = 13337); 38 | void morphRequestIntoARecordResponse(QByteArray &dnsrequest, std::vector &responseIPs, quint32 spliceOffset, quint32 ttl = 13337); 39 | 40 | class InitialResponse : public QObject 41 | { 42 | public: 43 | Q_OBJECT 44 | public: 45 | explicit InitialResponse(DNSInfo &dns, QObject *parent=0); 46 | 47 | private: 48 | //QUdpSocket sock; 49 | QDateTime timeWithoutAResponse; 50 | DNSInfo respondTo; 51 | bool responseHandled; 52 | 53 | signals: 54 | void finished(); 55 | 56 | public slots: 57 | void lookupDoneSendResponseNow(DNSInfo &dns, QUdpSocket *serversocket); 58 | void deleteObjectsTheresNoResponseFor(); 59 | }; 60 | 61 | #endif // INITIALRESPONSE_H 62 | -------------------------------------------------------------------------------- /CaptiveDNS/dnsserverwindow.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | DNSServerWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 205 10 | 192 11 | 12 | 13 | 14 | CaptiveDNS 15 | 16 | 17 | 18 | 19 | 20 | 21 | Qt::Vertical 22 | 23 | 24 | 25 | 20 26 | 40 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | Enter the above address into your device's DNS settings. 35 | 36 | 37 | true 38 | 39 | 40 | 41 | 42 | 43 | 44 | CaptiveDNS is running! 45 | 46 | 47 | 48 | 49 | 50 | 51 | About CaptiveDNS 52 | 53 | 54 | 55 | 56 | 57 | 58 | Qt::Vertical 59 | 60 | 61 | 62 | 20 63 | 40 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 20 73 | true 74 | 75 | 76 | 77 | 0.0.0.0 78 | 79 | 80 | Qt::AlignCenter 81 | 82 | 83 | Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse 84 | 85 | 86 | 87 | 88 | 89 | 90 | Edit Landing Page 91 | 92 | 93 | 94 | 95 | 96 | 97 | Qt::Vertical 98 | 99 | 100 | 101 | 20 102 | 40 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /CaptiveDNS/messagesthread.cpp: -------------------------------------------------------------------------------- 1 | #include "messagesthread.h" 2 | 3 | /* YourFriendlyDNS - A really awesome multi-platform (lin,win,mac,android) local caching and proxying dns server! 4 | Copyright (C) 2018 softwareengineer1 @ github.com/softwareengineer1 5 | 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, 6 | so I can keep bringing you great free and open software and continue to do so for a long time! 7 | I'm going entirely 100% free software this year in 2018 (and onwards I want to) :) 8 | Everything I make will be released under a free software license! That's my promise! 9 | If you want to contact me another way besides through github, insert your message into the blockchain with a BCH/BTC UTXO! ^_^ 10 | Thank you for your support! 11 | BCH: bitcoincash:qzh3knl0xeyrzrxm5paenewsmkm8r4t76glzxmzpqs 12 | BTC: 1279WngWQUTV56UcTvzVAnNdR3Z7qb6R8j 13 | (These are the payment methods I currently accept, 14 | if you want to support me via another cryptocurrency let me know and I'll probably start accepting that one too) 15 | 16 | This program is free software; you can redistribute it and/or modify 17 | it under the terms of the GNU General Public License as published by 18 | the Free Software Foundation; either version 2 of the License, or 19 | (at your option) any later version. 20 | 21 | This program is distributed in the hope that it will be useful, 22 | but WITHOUT ANY WARRANTY; without even the implied warranty of 23 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24 | GNU General Public License for more details. 25 | 26 | You should have received a copy of the GNU General Public License along 27 | with this program; if not, write to the Free Software Foundation, Inc., 28 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ 29 | 30 | AppData* AppData::instance = nullptr; 31 | 32 | AppData::AppData() 33 | { 34 | dnsServer = nullptr; 35 | httpServer = nullptr; 36 | dnsServerPort = 53; 37 | httpServerPort = 80; 38 | } 39 | 40 | AppData* AppData::get() 41 | { 42 | if(instance == nullptr) 43 | instance = new AppData(); 44 | return instance; 45 | } 46 | 47 | void MessagesThread::run() 48 | { 49 | data = AppData::get(); 50 | data->dnsServer = new SmallDNSServer(); 51 | data->httpServer = new SmallHTTPServer(); 52 | 53 | emit serversInitialized(); 54 | 55 | #ifdef Q_OS_ANDROID 56 | if(data->dnsServerPort == 53) 57 | data->dnsServerPort = 5333; 58 | if(data->httpServerPort == 80) 59 | data->httpServerPort = 8080; 60 | 61 | AndroidSU_ServerOP *suOP = new AndroidSU_ServerOP(AndroidSU_ServerOP::opcode::iptablesSet, data->dnsServerPort, data->httpServerPort); 62 | connect(suOP, SIGNAL(finished()), suOP, SLOT(deleteLater())); 63 | suOP->start(); 64 | emit androidInit(); 65 | #endif 66 | 67 | if(data->dnsServer->startServer(QHostAddress::Any, data->dnsServerPort)) 68 | qDebug() << "DNS server started on address:" << data->dnsServer->serversock.localAddress() << "and port:" << data->dnsServer->serversock.localPort(); 69 | 70 | if(data->httpServer->startServer(QHostAddress::Any, data->httpServerPort)) 71 | qDebug() << "HTTP server started on address:" << data->httpServer->serverAddress() << "and port:" << data->httpServer->serverPort(); 72 | 73 | qDebug() << "MessagesThread started, for handling server duties!"; 74 | exec(); //handles the signals and slots for objects owned by this thread 75 | } 76 | 77 | MessagesThread::~MessagesThread() 78 | { 79 | data = AppData::get(); 80 | if(data->httpServer) 81 | delete data->httpServer; 82 | if(data->dnsServer) 83 | delete data->dnsServer; 84 | } 85 | -------------------------------------------------------------------------------- /CaptiveDNS/dnsserverwindow.h: -------------------------------------------------------------------------------- 1 | #ifndef DNSSERVERWINDOW_H 2 | #define DNSSERVERWINDOW_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "settingswindow.h" 12 | #include "cacheviewer.h" 13 | #include "messagesthread.h" 14 | 15 | /* YourFriendlyDNS - A really awesome multi-platform (lin,win,mac,android) local caching and proxying dns server! 16 | Copyright (C) 2018 softwareengineer1 @ github.com/softwareengineer1 17 | 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, 18 | so I can keep bringing you great free and open software and continue to do so for a long time! 19 | I'm going entirely 100% free software this year in 2018 (and onwards I want to) :) 20 | Everything I make will be released under a free software license! That's my promise! 21 | If you want to contact me another way besides through github, insert your message into the blockchain with a BCH/BTC UTXO! ^_^ 22 | Thank you for your support! 23 | BCH: bitcoincash:qzh3knl0xeyrzrxm5paenewsmkm8r4t76glzxmzpqs 24 | BTC: 1279WngWQUTV56UcTvzVAnNdR3Z7qb6R8j 25 | (These are the payment methods I currently accept, 26 | if you want to support me via another cryptocurrency let me know and I'll probably start accepting that one too) 27 | 28 | This program is free software; you can redistribute it and/or modify 29 | it under the terms of the GNU General Public License as published by 30 | the Free Software Foundation; either version 2 of the License, or 31 | (at your option) any later version. 32 | 33 | This program is distributed in the hope that it will be useful, 34 | but WITHOUT ANY WARRANTY; without even the implied warranty of 35 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 36 | GNU General Public License for more details. 37 | 38 | You should have received a copy of the GNU General Public License along 39 | with this program; if not, write to the Free Software Foundation, Inc., 40 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ 41 | 42 | namespace Ui { 43 | class DNSServerWindow; 44 | } 45 | 46 | class DNSServerWindow : public QMainWindow 47 | { 48 | Q_OBJECT 49 | 50 | public: 51 | explicit DNSServerWindow(QWidget *parent = 0); 52 | ~DNSServerWindow(); 53 | 54 | static Ui::DNSServerWindow* mainUi; 55 | 56 | signals: 57 | void displayCache(const std::vector &cache); 58 | void clearSources(); 59 | void loadSource(QString url, bool forceUpdate = false, QByteArray hash = "", QDateTime lastUpdated = QDateTime()); 60 | 61 | public slots: 62 | void serversInitialized(); 63 | void displayLastUsedProvider(quint64 props, QString providerName, QHostAddress server, quint16 port); 64 | void androidInit(); 65 | void htmlChanged(QString &html); 66 | void setIPToFirstListening(); 67 | 68 | void showInFolder(const QString& path); 69 | 70 | private slots: 71 | void settingsUpdated(); 72 | void queryRespondedTo(ListEntry e); 73 | void autoCaptureCaptivePortals(); 74 | void iptablesUndoAndroid(); 75 | void on_firstAddButton_clicked(); 76 | void on_whitelistButton_clicked(); 77 | void on_blacklistButton_clicked(); 78 | void on_initialMode_stateChanged(int arg1); 79 | 80 | void on_editHTMLButton_clicked(); 81 | void on_aboutApp_clicked(); 82 | 83 | void on_saveButton_clicked(); 84 | void on_removeButton_clicked(); 85 | void on_hostnameEdit_returnPressed(); 86 | void on_ipEdit_returnPressed(); 87 | void on_secondAddButton_clicked(); 88 | void on_settingsButton_clicked(); 89 | void on_cacheViewButton_clicked(); 90 | 91 | 92 | private: 93 | Ui::DNSServerWindow *ui; 94 | MessagesThread *messagesThread; 95 | SettingsWindow *settings; 96 | CacheViewer *cacheviewer; 97 | SmallDNSServer *server; 98 | SmallHTTPServer *httpServer; 99 | QString settingspath, html, version; 100 | 101 | void listeningIPsUpdate(); 102 | void appendToBlacklist(ListEntry e); 103 | void refreshList(); 104 | void preloadServerPorts(); 105 | bool settingsSave(); 106 | bool settingsLoad(); 107 | }; 108 | 109 | #endif // DNSSERVERWINDOW_H 110 | -------------------------------------------------------------------------------- /CaptiveDNS/cacheviewer.cpp: -------------------------------------------------------------------------------- 1 | #include "cacheviewer.h" 2 | #include "ui_cacheviewer.h" 3 | 4 | /* YourFriendlyDNS - A really awesome multi-platform (lin,win,mac,android) local caching and proxying dns server! 5 | Copyright (C) 2018 softwareengineer1 @ github.com/softwareengineer1 6 | 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, 7 | so I can keep bringing you great free and open software and continue to do so for a long time! 8 | I'm going entirely 100% free software this year in 2018 (and onwards I want to) :) 9 | Everything I make will be released under a free software license! That's my promise! 10 | If you want to contact me another way besides through github, insert your message into the blockchain with a BCH/BTC UTXO! ^_^ 11 | Thank you for your support! 12 | BCH: bitcoincash:qzh3knl0xeyrzrxm5paenewsmkm8r4t76glzxmzpqs 13 | BTC: 1279WngWQUTV56UcTvzVAnNdR3Z7qb6R8j 14 | (These are the payment methods I currently accept, 15 | if you want to support me via another cryptocurrency let me know and I'll probably start accepting that one too) 16 | 17 | This program is free software; you can redistribute it and/or modify 18 | it under the terms of the GNU General Public License as published by 19 | the Free Software Foundation; either version 2 of the License, or 20 | (at your option) any later version. 21 | 22 | This program is distributed in the hope that it will be useful, 23 | but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | GNU General Public License for more details. 26 | 27 | You should have received a copy of the GNU General Public License along 28 | with this program; if not, write to the Free Software Foundation, Inc., 29 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ 30 | 31 | CacheViewer::CacheViewer(QWidget *parent) : QMainWindow(parent), ui(new Ui::CacheViewer) 32 | { 33 | ui->setupUi(this); 34 | } 35 | 36 | CacheViewer::~CacheViewer() 37 | { 38 | delete ui; 39 | } 40 | 41 | void CacheViewer::displayCache(const std::vector &cache) 42 | { 43 | QString type, data; 44 | ui->cacheView->clear(); 45 | for(const DNSInfo &dns : cache) 46 | { 47 | if(dns.question.qtype == DNS_TYPE_A) //IPv4 addresses 48 | { 49 | type = "A"; 50 | data = ""; 51 | if(dns.hasIPs && dns.ipaddresses.size() > 0) 52 | { 53 | for(const quint32 &i : dns.ipaddresses) 54 | { 55 | data += QString("%1, ").arg(QHostAddress(i).toString()); 56 | } 57 | data.truncate(data.size()-2); 58 | } 59 | } 60 | else if(dns.question.qtype == DNS_TYPE_AAAA) //IPv6 addresses 61 | { 62 | type = "AAAA"; 63 | data = dns.res.toHex().toStdString().c_str(); 64 | } 65 | else if(dns.question.qtype == DNS_TYPE_TXT) //TXT record 66 | { 67 | type = "TXT"; 68 | QByteArray data2 = dns.res; 69 | if(data2.size() > DNS_HEADER_SIZE) 70 | data2.remove(0, DNS_HEADER_SIZE); 71 | data = data2.toStdString().c_str(); 72 | } 73 | else 74 | { 75 | type = QString("%1").arg(dns.question.qtype); 76 | data = dns.res.toHex().toStdString().c_str(); 77 | } 78 | 79 | ui->cacheView->addTopLevelItem(new QTreeWidgetItem(QStringList() << dns.domainString << type << dns.expiry.toString() << data)); 80 | } 81 | } 82 | 83 | void CacheViewer::on_okButton_clicked() 84 | { 85 | this->hide(); 86 | } 87 | 88 | void CacheViewer::on_removeButton_clicked() 89 | { 90 | std::vector entries; 91 | auto selected = ui->cacheView->selectedItems(); 92 | for(QTreeWidgetItem *i : selected) 93 | { 94 | if(i->text(1) == "A") 95 | entries.push_back(ListEntry(i->text(0), DNS_TYPE_A)); //Reusing the ip field as a record type field just for this 96 | else if(i->text(1) == "AAAA") 97 | entries.push_back(ListEntry(i->text(0), DNS_TYPE_AAAA)); 98 | else if(i->text(1) == "TXT") 99 | entries.push_back(ListEntry(i->text(0), DNS_TYPE_TXT)); 100 | else 101 | entries.push_back(ListEntry(i->text(0), i->text(1).toInt())); 102 | } 103 | qDeleteAll(selected); 104 | emit deleteEntriesFromCache(entries); 105 | } 106 | -------------------------------------------------------------------------------- /CaptiveDNS/androidsuop.h: -------------------------------------------------------------------------------- 1 | #ifndef ANDROIDSUOP_H 2 | #define ANDROIDSUOP_H 3 | 4 | #ifdef Q_OS_ANDROID 5 | 6 | #include 7 | #include 8 | 9 | /* YourFriendlyDNS - A really awesome multi-platform (lin,win,mac,android) local caching and proxying dns server! 10 | Copyright (C) 2018 softwareengineer1 @ github.com/softwareengineer1 11 | 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, 12 | so I can keep bringing you great free and open software and continue to do so for a long time! 13 | I'm going entirely 100% free software this year in 2018 (and onwards I want to) :) 14 | Everything I make will be released under a free software license! That's my promise! 15 | If you want to contact me another way besides through github, insert your message into the blockchain with a BCH/BTC UTXO! ^_^ 16 | Thank you for your support! 17 | BCH: bitcoincash:qzh3knl0xeyrzrxm5paenewsmkm8r4t76glzxmzpqs 18 | BTC: 1279WngWQUTV56UcTvzVAnNdR3Z7qb6R8j 19 | (These are the payment methods I currently accept, 20 | if you want to support me via another cryptocurrency let me know and I'll probably start accepting that one too) 21 | 22 | This program is free software; you can redistribute it and/or modify 23 | it under the terms of the GNU General Public License as published by 24 | the Free Software Foundation; either version 2 of the License, or 25 | (at your option) any later version. 26 | 27 | This program is distributed in the hope that it will be useful, 28 | but WITHOUT ANY WARRANTY; without even the implied warranty of 29 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 30 | GNU General Public License for more details. 31 | 32 | You should have received a copy of the GNU General Public License along 33 | with this program; if not, write to the Free Software Foundation, Inc., 34 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ 35 | 36 | class AndroidSU_ServerOP : public QThread 37 | { 38 | public: 39 | enum class opcode 40 | { 41 | iptablesSet, iptablesRemove 42 | }; 43 | 44 | opcode op; 45 | quint16 dnsServerPort,httpServerPort; 46 | AndroidSU_ServerOP(opcode op, quint16 dnsServerPort, quint16 httpServerPort = 0) 47 | { 48 | this->op = op; 49 | this->dnsServerPort = dnsServerPort; 50 | this->httpServerPort = httpServerPort; 51 | } 52 | void run() 53 | { 54 | QProcess su; 55 | QProcess du; 56 | if(op == opcode::iptablesSet) 57 | { 58 | //Run su, enable ipv4 forwarding, and do iptables redirect from port 53(dns) to 5333 (where this server is binded on android by default), also 80 to 8080 now 59 | du.start("su"); //First time running it, accept the root prompt 60 | if(!du.waitForStarted()) 61 | return; 62 | du.write(QString("iptables -t nat --list | grep \"ports %1\"\n").arg(dnsServerPort).toUtf8()); 63 | du.waitForFinished(); 64 | QByteArray listresult = du.read(4096); 65 | qDebug() << "iptables dns port list result:" << listresult << "list size:" << listresult.size(); 66 | 67 | su.start("su"); 68 | if(!su.waitForStarted()) 69 | return; 70 | 71 | if(listresult.size() == 0) 72 | { 73 | qDebug() << "iptables dns not set yet, setting dns iptables now..."; 74 | su.write("sysctl -w net.ipv4.ip_forward=1\n"); 75 | su.write(QString("iptables -A INPUT -p udp --dport %1 -j ACCEPT\n").arg(dnsServerPort).toUtf8()); 76 | su.write(QString("iptables -t nat -A PREROUTING -p udp --dport 53 -j REDIRECT --to-ports %1\n").arg(dnsServerPort).toUtf8()); 77 | } 78 | 79 | if(httpServerPort != 0) 80 | { 81 | du.write(QString("iptables -t nat --list | grep \"ports %1\"\n").arg(httpServerPort).toUtf8()); 82 | du.closeWriteChannel(); 83 | du.waitForFinished(); 84 | QByteArray listresult = du.read(4096); 85 | 86 | qDebug() << "iptables http port list result:" << listresult << "list size:" << listresult.size(); 87 | if(listresult.size() == 0) 88 | { 89 | qDebug() << "iptables http not set yet, setting http iptables now..."; 90 | su.write(QString("iptables -A INPUT -p tcp --dport %1 -j ACCEPT\n").arg(httpServerPort).toUtf8()); 91 | su.write(QString("iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports %1\n").arg(httpServerPort).toUtf8()); 92 | } 93 | } 94 | 95 | su.closeWriteChannel(); 96 | if(!su.waitForFinished()) 97 | return; 98 | } 99 | else if(op == opcode::iptablesRemove) 100 | { 101 | su.start("su"); 102 | if(!su.waitForStarted()) 103 | return; 104 | 105 | su.write(QString("iptables -D INPUT -p udp --dport %1 -j ACCEPT\n").arg(dnsServerPort).toUtf8()); 106 | su.write(QString("iptables -t nat -D PREROUTING -p udp --dport 53 -j REDIRECT --to-ports %1\n").arg(dnsServerPort).toUtf8()); 107 | if(httpServerPort != 0) 108 | { 109 | su.write(QString("iptables -D INPUT -p tcp --dport %1 -j ACCEPT\n").arg(httpServerPort).toUtf8()); 110 | su.write(QString("iptables -t nat -D PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports %1\n").arg(httpServerPort).toUtf8()); 111 | } 112 | su.closeWriteChannel(); 113 | 114 | if(!su.waitForFinished()) 115 | return; 116 | } 117 | } 118 | }; 119 | 120 | #endif 121 | 122 | #endif // ANDROIDSUOP_H 123 | -------------------------------------------------------------------------------- /CaptiveDNS/smalldnsserver.h: -------------------------------------------------------------------------------- 1 | #ifndef SMALLDNSSERVER_H 2 | #define SMALLDNSSERVER_H 3 | 4 | /* YourFriendlyDNS - A really awesome multi-platform (lin,win,mac,android) local caching and proxying dns server! 5 | Copyright (C) 2018 softwareengineer1 @ github.com/softwareengineer1 6 | Support my work so I can keep bringing you great free and open software! 7 | I'm going entirely 100% free software this year in 2018 (and onwards I want to) :) 8 | Everything I make will be released under a free software license! That's my promise! 9 | If you want to contact me another way besides through github, insert your message into the blockchain with a BCH/BTC UTXO! ^_^ 10 | Thank you for your support! 11 | BCH: bitcoincash:qzh3knl0xeyrzrxm5paenewsmkm8r4t76glzxmzpqs 12 | BTC: 1279WngWQUTV56UcTvzVAnNdR3Z7qb6R8j 13 | 14 | This program is free software; you can redistribute it and/or modify 15 | it under the terms of the GNU General Public License as published by 16 | the Free Software Foundation; either version 2 of the License, or 17 | (at your option) any later version. 18 | 19 | This program is distributed in the hope that it will be useful, 20 | but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | GNU General Public License for more details. 23 | 24 | You should have received a copy of the GNU General Public License along 25 | with this program; if not, write to the Free Software Foundation, Inc., 26 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include "androidsuop.h" 37 | #include "initialresponse.h" 38 | // #include "dnscrypt.h" //Including our DNSCrypt class and helpers, giving us DNSCrypt protocol version 1,2,3 support! 39 | 40 | /* YourFriendlyDNS - A really awesome multi-platform (lin,win,mac,android) local caching and proxying dns server! 41 | Copyright (C) 2018 softwareengineer1 @ github.com/softwareengineer1 42 | 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, 43 | so I can keep bringing you great free and open software and continue to do so for a long time! 44 | I'm going entirely 100% free software this year in 2018 (and onwards I want to) :) 45 | Everything I make will be released under a free software license! That's my promise! 46 | If you want to contact me another way besides through github, insert your message into the blockchain with a BCH/BTC UTXO! ^_^ 47 | Thank you for your support! 48 | BCH: bitcoincash:qzh3knl0xeyrzrxm5paenewsmkm8r4t76glzxmzpqs 49 | BTC: 1279WngWQUTV56UcTvzVAnNdR3Z7qb6R8j 50 | (These are the payment methods I currently accept, 51 | if you want to support me via another cryptocurrency let me know and I'll probably start accepting that one too) 52 | 53 | This program is free software; you can redistribute it and/or modify 54 | it under the terms of the GNU General Public License as published by 55 | the Free Software Foundation; either version 2 of the License, or 56 | (at your option) any later version. 57 | 58 | This program is distributed in the hope that it will be useful, 59 | but WITHOUT ANY WARRANTY; without even the implied warranty of 60 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 61 | GNU General Public License for more details. 62 | 63 | You should have received a copy of the GNU General Public License along 64 | with this program; if not, write to the Free Software Foundation, Inc., 65 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ 66 | 67 | /* GeneralTextCompare By Kirk J. Krauss, August 26, 2008 68 | 69 | A simple wildcard text-matching algorithm in a single while loop */ 70 | bool GeneralTextCompare( 71 | char * pTameText, // A string without wildcards 72 | char * pWildText, // A (potentially) corresponding string with wildcards 73 | bool bCaseSensitive = false, // By default, match on 'X' vs 'x' 74 | char cAltTerminator = '\0' // For function names, for example, you can stop at the first '(' 75 | ); 76 | 77 | namespace Ui { 78 | class DNSServerWindow; 79 | } 80 | 81 | class SmallDNSServer : public QObject 82 | { 83 | Q_OBJECT 84 | public: 85 | explicit SmallDNSServer(QObject *parent = nullptr); 86 | bool startServer(QHostAddress address = QHostAddress::AnyIPv4, quint16 port = 53, bool reuse = false); 87 | QString getDomainString(const QByteArray &dnsmessage, DNSInfo &dns); 88 | void determineDoHDoTLSProviders(); 89 | 90 | bool whitelistmode, blockmode_returnlocalhost, initialMode, autoTTL, dnscryptEnabled, sendrecvFlag; 91 | QDateTime requestLastSentTime, responseLastReceivedTime, timeoutInferencePeriod, timeoutEnd; 92 | Q_IPV6ADDR ipv6ToRespondWith; 93 | quint32 ipToRespondWith, cachedMinutesValid, dnsTTL, inTimeout; 94 | quint64 numSentRequests, numReceivedResponses; 95 | QString dedicatedDNSCrypter; 96 | QVector whitelist,blacklist; 97 | QVector realdns, v2and3Providers; 98 | QVector listeningIPs; 99 | QVector listeningIPv6s; 100 | std::vector cachedDNSResponses; 101 | QUdpSocket serversock; 102 | // DNSCrypt *dnscrypt; 103 | 104 | private: 105 | Ui::DNSServerWindow *ui; 106 | ListEntry* getListEntry(const std::string &tame, int listType); 107 | DNSInfo* getCachedEntry(const QString &byDomain, quint16 andType); 108 | void parseAndRespond(QByteArray &datagram, DNSInfo &dns); 109 | bool interpretHeader(const QByteArray &dnsmessage, DNSInfo &dns); 110 | void parseRequest(const QByteArray &dnsrequest, DNSInfo &dns); 111 | void parseResponse(const QByteArray &dnsresponse, DNSInfo &dns); 112 | void getHostAddresses(const QByteArray &dnsresponse, DNSInfo &dns); 113 | QString selectRandomDNSServer(); 114 | QString selectRandomDNSCryptServer(); 115 | bool weDoStillHaveAConnection(); 116 | QUdpSocket clientsock; 117 | 118 | signals: 119 | void queryRespondedTo(ListEntry responded); 120 | void lookupDoneSendResponseNow(DNSInfo &dns, QUdpSocket *serversocket); 121 | void deleteObjectsTheresNoResponseFor(); 122 | 123 | public slots: 124 | void clearDNSCache(); 125 | void deleteEntriesFromCache(std::vector entries); 126 | void decryptedLookupDoneSendResponseNow(QByteArray decryptedResponse, DNSInfo &dns); 127 | void displayErrorPopup(QString error); 128 | 129 | private slots: 130 | void processDNSRequests(); 131 | void processLookups(); 132 | }; 133 | 134 | #endif // SMALLDNSSERVER_H 135 | -------------------------------------------------------------------------------- /CaptiveDNS/settingswindow.h: -------------------------------------------------------------------------------- 1 | #ifndef SETTINGSWINDOW_H 2 | #define SETTINGSWINDOW_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "indexhtml.h" 8 | // #include "providersourcerstampconverter.h" 9 | 10 | /* YourFriendlyDNS - A really awesome multi-platform (lin,win,mac,android) local caching and proxying dns server! 11 | Copyright (C) 2018 softwareengineer1 @ github.com/softwareengineer1 12 | 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, 13 | so I can keep bringing you great free and open software and continue to do so for a long time! 14 | I'm going entirely 100% free software this year in 2018 (and onwards I want to) :) 15 | Everything I make will be released under a free software license! That's my promise! 16 | If you want to contact me another way besides through github, insert your message into the blockchain with a BCH/BTC UTXO! ^_^ 17 | Thank you for your support! 18 | BCH: bitcoincash:qzh3knl0xeyrzrxm5paenewsmkm8r4t76glzxmzpqs 19 | BTC: 1279WngWQUTV56UcTvzVAnNdR3Z7qb6R8j 20 | (These are the payment methods I currently accept, 21 | if you want to support me via another cryptocurrency let me know and I'll probably start accepting that one too) 22 | 23 | This program is free software; you can redistribute it and/or modify 24 | it under the terms of the GNU General Public License as published by 25 | the Free Software Foundation; either version 2 of the License, or 26 | (at your option) any later version. 27 | 28 | This program is distributed in the hope that it will be useful, 29 | but WITHOUT ANY WARRANTY; without even the implied warranty of 30 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 31 | GNU General Public License for more details. 32 | 33 | You should have received a copy of the GNU General Public License along 34 | with this program; if not, write to the Free Software Foundation, Inc., 35 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ 36 | 37 | /*MUST BLOCK: 38 | http://sun.hac.lp1.d4c.nintendo.net:443 - System Update Server/Nag 39 | http://beach.hac.lp1.eshop.nintendo.net:443 - System Update Nag/Eshop lockout 40 | 41 | http://receive-lp1.dg.srv.nintendo.net 42 | http://sun.hac.lp1.d4c.nintendo.net 43 | 44 | hmmm... maybe we better implement some wildcards for extra safety... Done! :D 45 | 46 | *.srv.nintendo.net 47 | *.d4c.nintendo.net 48 | * eshop.nintendo.net 49 | 50 | OPTIONAL (May cause system instability): 51 | http://aauth-lp1.ndas.srv.nintendo.net:443 52 | http://accounts.nintendo.com:443 - Nintendo Account 53 | http://api.accounts.nintendo.com:443 - Add Friends API 54 | http://app-a04.lp1.npns.srv.nintendo.net:443 55 | http://aqua.hac.lp1.d4c.nintendo.net:443 56 | http://atum.hac.lp1.d4c.nintendo.net:443 - Game download server 57 | http://bcat-data-lp1.cdn.nintendo.net:443 58 | http://bcat-list-lp1.cdn.nintendo.net:443 59 | http://broker.lp1.npns.srv.nintendo.net:443 60 | http://bugyo.hac.lp1.eshop.nintendo.net:443 - eshop 61 | http://consumer.lp1.npns.srv.nintendo.net:443 - eshop 62 | http://dauth-lp1.ndas.srv.nintendo.net:443 63 | http://e0d67c509fb203858ebcb2fe3f88c2aa.baas.nintendo.com:443 - Friends list 64 | http://ecs-lp1.hac.shop.nintendo.net:443 65 | http://pushmo.hac.lp1.eshop.nintendo.net:443 - eshop 66 | http://receive-lp1.dg.srv.nintendo.net:443 67 | http://receive-lp1.er.srv.nintendo.net:443 - error reporting 68 | http://scontent.xx.fbcdn.net:443 - Facebook 69 | http://superfly.hac.lp1.d4c.nintendo.net:443 - Game updates server 70 | http://tagaya.hac.lp1.eshop.nintendo.net:443 71 | http://web-lp1.share.srv.nintendo.net:443 - Facebook Image Posting 72 | http://www.google-analytics.com:443 - Fsck you google! Stay out of my shit! 73 | http://www.googletagmanager.com:443 - Google again? Really? 74 | */ 75 | 76 | namespace Ui { 77 | class SettingsWindow; 78 | } 79 | 80 | class SettingsWindow : public QMainWindow 81 | { 82 | Q_OBJECT 83 | 84 | public: 85 | explicit SettingsWindow(QWidget *parent = 0); 86 | ~SettingsWindow(); 87 | IndexHTML *indexhtml; 88 | // providerSourcerStampConverter *sourcerAndStampConverter; 89 | QString returnDedicatedDNSCrypter(); 90 | QVector returnRealDNSServers(); 91 | void clearDNSServers(); 92 | bool isExisting(const QString &dns); 93 | void appendDNSServer(const QString &dns); 94 | void setRespondingIP(const QString &ip); 95 | void setRespondingIPv6(const QString &ipv6); 96 | bool getDNSCryptEnabled(); 97 | bool getNewKeyPerRequestEnabled(); 98 | QString getRespondingIP(); 99 | QString getDNSServerPort(); 100 | QString getHTTPServerPort(); 101 | void setDNSCryptEnabled(bool yes = true); 102 | void setNewKeyPerRequest(bool yes = true); 103 | void setCachedMinutesValid(quint32 minutesValid); 104 | void setAutoTTL(bool autottl); 105 | void setdnsTTL(quint32 dnsttl); 106 | void setDNSServerPort(quint16 dnsServerPort); 107 | void setHTTPServerPort(quint16 httpServerPort); 108 | void setiptablesButtonEnabled(bool enabled = true); 109 | quint32 getCachedMinutesValid(); 110 | void setBlockOptionNoResponse(); 111 | void setAutoInject(bool checked); 112 | bool blockmode_localhost, autoinject, autoTTL; 113 | quint32 dnsTTL; 114 | 115 | signals: 116 | void settingsUpdated(); 117 | void clearDNSCache(); 118 | void setIPToFirstListening(); 119 | void autoCaptureCaptivePortals(); 120 | void iptablesUndoAndroid(); 121 | void autoInjectIfEnabled(); 122 | void decodeStamp(QString sdns); 123 | 124 | public slots: 125 | void addToServerList(QString stamp); 126 | 127 | private slots: 128 | void on_addButton_clicked(); 129 | void on_removeButton_clicked(); 130 | void on_option_localhost_clicked(); 131 | void on_option_noresponse_clicked(); 132 | void on_cacheValidMinutes_editingFinished(); 133 | void on_respondingIP_editingFinished(); 134 | void on_edit_dnsserver_returnPressed(); 135 | void on_clearCacheButton_clicked(); 136 | void on_editindexButton_clicked(); 137 | void on_ipinjectButton_clicked(); 138 | void on_autoinjectBox_stateChanged(int arg1); 139 | void on_captureCaptive_clicked(); 140 | void on_iptablesUndo_clicked(); 141 | void on_dnsTTL_textChanged(const QString &arg1); 142 | void on_sameAsCachedBox_stateChanged(int arg1); 143 | void on_cacheValidMinutes_textChanged(const QString &arg1); 144 | void on_dnscryptEnabled_stateChanged(int arg1); 145 | void on_newKeyPerRequest_stateChanged(int arg1); 146 | void on_backButton_clicked(); 147 | void on_getProvidersButton_clicked(); 148 | void on_realdnsservers_itemClicked(QListWidgetItem *item); 149 | 150 | private: 151 | Ui::SettingsWindow *ui; 152 | }; 153 | 154 | #endif // SETTINGSWINDOW_H 155 | -------------------------------------------------------------------------------- /CaptiveDNS/dnsinfo.h: -------------------------------------------------------------------------------- 1 | #ifndef DNSINFO_H 2 | #define DNSINFO_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | /* YourFriendlyDNS - A really awesome multi-platform (lin,win,mac,android) local caching and proxying dns server! 9 | Copyright (C) 2018 softwareengineer1 @ github.com/softwareengineer1 10 | 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, 11 | so I can keep bringing you great free and open software and continue to do so for a long time! 12 | I'm going entirely 100% free software this year in 2018 (and onwards I want to) :) 13 | Everything I make will be released under a free software license! That's my promise! 14 | If you want to contact me another way besides through github, insert your message into the blockchain with a BCH/BTC UTXO! ^_^ 15 | Thank you for your support! 16 | BCH: bitcoincash:qzh3knl0xeyrzrxm5paenewsmkm8r4t76glzxmzpqs 17 | BTC: 1279WngWQUTV56UcTvzVAnNdR3Z7qb6R8j 18 | (These are the payment methods I currently accept, 19 | if you want to support me via another cryptocurrency let me know and I'll probably start accepting that one too) 20 | 21 | This program is free software; you can redistribute it and/or modify 22 | it under the terms of the GNU General Public License as published by 23 | the Free Software Foundation; either version 2 of the License, or 24 | (at your option) any later version. 25 | 26 | This program is distributed in the hope that it will be useful, 27 | but WITHOUT ANY WARRANTY; without even the implied warranty of 28 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 29 | GNU General Public License for more details. 30 | 31 | You should have received a copy of the GNU General Public License along 32 | with this program; if not, write to the Free Software Foundation, Inc., 33 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ 34 | 35 | #define DNS_HEADER_SIZE 12 36 | #define DNS_TYPE_A 1 37 | #define DNS_TYPE_AAAA 28 38 | #define DNS_TYPE_TXT 16 39 | 40 | #define RCODE_NOERROR 0 41 | #define RCODE_FMTERROR 1 42 | #define RCODE_SERVFAIL 2 43 | #define RCODE_NXDOMAIN 3 44 | #define RCODE_NOTIMPL 4 45 | #define RCODE_REFUSED 5 46 | #define RCODE_YXDOMAIN 6 47 | #define RCODE_XRRSET 7 48 | #define RCODE_NOTAUTH 8 49 | #define RCODE_NOTZONE 9 50 | 51 | // DNS header structure : 12 bytes 52 | struct DNS_HEADER 53 | { 54 | unsigned short id; // identification number 55 | 56 | unsigned char rd :1; // recursion desired 57 | unsigned char tc :1; // truncated message 58 | unsigned char AUTHORITATIVE_ANSWER_FLAG :1; // authoritive answer 59 | unsigned char opcode :4; // purpose of message 60 | unsigned char QUERY_RESPONSE_FLAG :1; // query/response flag 61 | 62 | unsigned char rcode :4; // response code 63 | unsigned char cd :1; // checking disabled 64 | unsigned char ad :1; // authenticated data 65 | unsigned char z :1; // its z! reserved 66 | unsigned char RECURSION_AVAILABLE_FLAG :1; // recursion available 67 | 68 | unsigned short q_count; // number of question entries 69 | unsigned short ans_count; // number of answer entries 70 | unsigned short auth_count; // number of authority entries 71 | unsigned short add_count; // number of resource entries 72 | }; 73 | 74 | struct QUESTION 75 | { 76 | unsigned short qtype; 77 | unsigned short qclass; 78 | }; 79 | 80 | struct ANSWER 81 | { 82 | quint16 name; 83 | quint16 type; 84 | quint16 rclass; 85 | quint32 ttl; 86 | quint16 rdlength; 87 | //rdata 88 | }; 89 | 90 | class DNSInfo 91 | { 92 | public: 93 | DNSInfo() 94 | { 95 | memset(&header, 0, sizeof(header)); 96 | memset(&question, 0, sizeof(question)); 97 | answeroffset = 0; 98 | senderPort = 0; 99 | ttl = 0; 100 | isValid = isResponse = hasIPs = false; 101 | expiry = QDateTime::currentDateTime(); 102 | } 103 | DNSInfo(const DNSInfo &info) 104 | { 105 | copyDNSInfoFrom(info); 106 | } 107 | DNSInfo operator=(const DNSInfo &info) 108 | { 109 | copyDNSInfoFrom(info); 110 | return *this; 111 | } 112 | bool operator==(const DNSInfo &info) 113 | { 114 | return (this->domainString == info.domainString && this->question.qtype == info.question.qtype); 115 | } 116 | void copyDNSInfoFrom(const DNSInfo &info) 117 | { 118 | memcpy(&this->header, &info.header, sizeof(header)); 119 | memcpy(&this->question, &info.question, sizeof(question)); 120 | this->domainString = info.domainString; 121 | this->answeroffset = info.answeroffset; 122 | this->ttl = info.ttl; 123 | this->isValid = info.isValid; 124 | this->isResponse = info.isResponse; 125 | this->hasIPs = info.hasIPs; 126 | this->ipaddresses = info.ipaddresses; 127 | this->expiry = info.expiry; 128 | this->req = info.req; 129 | this->res = info.res; 130 | this->sender = info.sender; 131 | this->senderPort = info.senderPort; 132 | } 133 | static quint16 extractPort(QString &addr) 134 | { 135 | if(addr.size() == 0) return 443; 136 | if(!addr.contains(".") && !addr.contains("[")) { quint16 port = addr.toInt(); addr.clear(); return port; } 137 | if(addr.data()[0] == '[') 138 | { 139 | addr.remove(0, 1); 140 | int portOffset = addr.lastIndexOf("]:"); 141 | if(portOffset != -1) 142 | { 143 | QString ipv6Port = addr.right(addr.size() - (portOffset + 2)); 144 | addr.truncate(portOffset); 145 | return ipv6Port.toInt(); 146 | } 147 | else 148 | { 149 | addr.truncate(addr.size() - 1); 150 | return 443; 151 | } 152 | } 153 | else 154 | { 155 | int portOffset = addr.lastIndexOf(":"); 156 | if(portOffset != -1) 157 | { 158 | QString ipv4Port = addr.right(addr.size() - (portOffset + 1)); 159 | addr.truncate(portOffset); 160 | return ipv4Port.toInt(); 161 | } 162 | else 163 | return 443; 164 | } 165 | } 166 | DNS_HEADER header; 167 | QUESTION question; 168 | QString domainString; 169 | quint16 senderPort; 170 | quint32 answeroffset, ttl; 171 | bool isValid, isResponse, hasIPs; 172 | std::vector ipaddresses; 173 | QDateTime expiry; 174 | QByteArray req, res; 175 | QHostAddress sender; 176 | }; 177 | 178 | class ListEntry 179 | { 180 | public: 181 | QString hostname; 182 | quint32 ip; 183 | ListEntry() { ip = 0; } 184 | ListEntry(const QString &host, quint32 address = 0) 185 | { 186 | hostname = host; 187 | ip = address; 188 | } 189 | }; 190 | 191 | #define TYPE_WHITELIST 1 192 | #define TYPE_BLACKLIST 2 193 | 194 | #endif // DNSINFO_H 195 | -------------------------------------------------------------------------------- /CaptiveDNS/smallhttpserver.cpp: -------------------------------------------------------------------------------- 1 | #include "smallhttpserver.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | /* YourFriendlyDNS - A really awesome multi-platform (lin,win,mac,android) local caching and proxying dns server! 14 | Copyright (C) 2018 softwareengineer1 @ github.com/softwareengineer1 15 | 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, 16 | so I can keep bringing you great free and open software and continue to do so for a long time! 17 | I'm going entirely 100% free software this year in 2018 (and onwards I want to) :) 18 | Everything I make will be released under a free software license! That's my promise! 19 | If you want to contact me another way besides through github, insert your message into the blockchain with a BCH/BTC UTXO! ^_^ 20 | Thank you for your support! 21 | BCH: bitcoincash:qzh3knl0xeyrzrxm5paenewsmkm8r4t76glzxmzpqs 22 | BTC: 1279WngWQUTV56UcTvzVAnNdR3Z7qb6R8j 23 | (These are the payment methods I currently accept, 24 | if you want to support me via another cryptocurrency let me know and I'll probably start accepting that one too) 25 | 26 | This program is free software; you can redistribute it and/or modify 27 | it under the terms of the GNU General Public License as published by 28 | the Free Software Foundation; either version 2 of the License, or 29 | (at your option) any later version. 30 | 31 | This program is distributed in the hope that it will be useful, 32 | but WITHOUT ANY WARRANTY; without even the implied warranty of 33 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 34 | GNU General Public License for more details. 35 | 36 | You should have received a copy of the GNU General Public License along 37 | with this program; if not, write to the Free Software Foundation, Inc., 38 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ 39 | 40 | SmallHTTPServer::SmallHTTPServer(QObject *parent) 41 | { 42 | Q_UNUSED(parent); 43 | html = "CaptiveDNS is working, but you shouldn't be seeing this message!"; 44 | response_header=R"(HTTP/1.1 200 OK 45 | Content-Type: %1 46 | Content-Encoding: %2 47 | Content-Length: %3 48 | Accept-Ranges: %4 49 | Date: %5 50 | Connection: %6)"; 51 | response_header += "\r\n\r\n"; 52 | contentType = "text/html", encodingType = "identity", acceptRanges = "bytes", connection = "close"; 53 | 54 | connect(this, &QTcpServer::newConnection, this, &SmallHTTPServer::returnIndexPage); 55 | } 56 | 57 | bool SmallHTTPServer::startServer(QHostAddress address, quint16 port) 58 | { 59 | if(port == 0) 60 | { 61 | qDebug() << "HTTP server disabled in settings (set to port 0)"; 62 | return false; 63 | } 64 | return listen(address, port); 65 | } 66 | 67 | void SmallHTTPServer::setHTML(QString html) 68 | { 69 | this->html = html; 70 | } 71 | 72 | QString SmallHTTPServer::getIndexHTMLPath() { 73 | // TODO: copied from dnsserverwindow.cpp, refactor this 74 | auto settingspath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); 75 | settingspath += QDir::separator(); 76 | return settingspath + "landing.html"; 77 | } 78 | 79 | // we never cache the index page, and just always read it from disk 80 | // this has worse performance, but it's easier to edit and reload 81 | QString SmallHTTPServer::getHTMLContent() 82 | { 83 | // html = settings->indexhtml->getHTML(); 84 | 85 | // read the html from the landing page 86 | auto landingPath = getIndexHTMLPath(); 87 | 88 | // create it, if it doesn't exist 89 | createLanding(); 90 | 91 | if (QFile::exists(landingPath)) { 92 | QFile file(landingPath); 93 | if (file.open(QIODevice::ReadOnly)) { 94 | html = file.readAll(); 95 | file.close(); 96 | } 97 | } 98 | 99 | return html; 100 | } 101 | 102 | // creates the landing page, if it doesn't already exist 103 | void SmallHTTPServer::createLanding() 104 | { 105 | auto landingPath = getIndexHTMLPath(); 106 | if (!QFile::exists(landingPath)) { 107 | auto defaultHtml = "\ 108 | \n\ 109 | CaptiveDNS\n\ 110 | \n\ 127 | \n\ 128 |

CaptiveDNS

\n\ 129 |

Welcome to the CaptiveDNS landing page!

\n\ 130 |

Quick Links:

\n\ 131 | \n\ 138 |

To customize this page, press \"Edit Landing Page\" in the CaptiveDNS app, and then open landing.html in a text editor.

\n\ 139 |

For source code and license information, see here.

\n\ 140 |

Reload Page

\n\ 141 | "; 142 | 143 | QFile indexhtml(landingPath); 144 | if(indexhtml.open(QFile::WriteOnly | QIODevice::Text)) 145 | { 146 | QTextStream out(&indexhtml); 147 | out << defaultHtml << Qt::endl; 148 | } 149 | 150 | // if the readme doesn't exist, create it 151 | // auto readmePath = settingspath + "README.txt"; 152 | // if (!QFile::exists(readmePath)) { 153 | // QFile readme(readmePath); 154 | // if(readme.open(QFile::WriteOnly | QIODevice::Text)) 155 | // { 156 | // QTextStream out(&readme); 157 | // out << "This is the CaptiveDNS internal folder. You can customize the captive portal start page by editing the landing.html file in a text editor." << Qt::endl; 158 | // } 159 | // } 160 | } 161 | } 162 | 163 | void SmallHTTPServer::returnIndexPage() 164 | { 165 | // always reload the html content in case it changed 166 | getHTMLContent(); 167 | 168 | QTcpSocket *socket = nextPendingConnection(); 169 | connect(socket, &QTcpSocket::disconnected, socket, &QObject::deleteLater); 170 | 171 | QString contentLength = QString("%1").arg(html.size()); 172 | QString currentDateTime = QDateTime::currentDateTime().toString(); 173 | QString response = response_header.arg(contentType).arg(encodingType).arg(contentLength).arg(acceptRanges).arg(currentDateTime).arg(connection); 174 | response += html; 175 | 176 | socket->write(response.toUtf8()); 177 | socket->disconnectFromHost(); 178 | //qDebug() << "[" << socket->socketDescriptor() << "] Wrote index page:" << response; 179 | } 180 | -------------------------------------------------------------------------------- /CaptiveDNS/initialresponse.cpp: -------------------------------------------------------------------------------- 1 | #include "initialresponse.h" 2 | 3 | /* YourFriendlyDNS - A really awesome multi-platform (lin,win,mac,android) local caching and proxying dns server! 4 | Copyright (C) 2018 softwareengineer1 @ github.com/softwareengineer1 5 | 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, 6 | so I can keep bringing you great free and open software and continue to do so for a long time! 7 | I'm going entirely 100% free software this year in 2018 (and onwards I want to) :) 8 | Everything I make will be released under a free software license! That's my promise! 9 | If you want to contact me another way besides through github, insert your message into the blockchain with a BCH/BTC UTXO! ^_^ 10 | Thank you for your support! 11 | BCH: bitcoincash:qzh3knl0xeyrzrxm5paenewsmkm8r4t76glzxmzpqs 12 | BTC: 1279WngWQUTV56UcTvzVAnNdR3Z7qb6R8j 13 | (These are the payment methods I currently accept, 14 | if you want to support me via another cryptocurrency let me know and I'll probably start accepting that one too) 15 | 16 | This program is free software; you can redistribute it and/or modify 17 | it under the terms of the GNU General Public License as published by 18 | the Free Software Foundation; either version 2 of the License, or 19 | (at your option) any later version. 20 | 21 | This program is distributed in the hope that it will be useful, 22 | but WITHOUT ANY WARRANTY; without even the implied warranty of 23 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24 | GNU General Public License for more details. 25 | 26 | You should have received a copy of the GNU General Public License along 27 | with this program; if not, write to the Free Software Foundation, Inc., 28 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ 29 | 30 | void morphRequestIntoARecordResponse(QByteArray &dnsrequest, quint32 responseIP, quint32 spliceOffset, quint32 ttl) 31 | { 32 | if(dnsrequest.size() >= DNS_HEADER_SIZE) //Make sure there's at least a dns header here to write to 33 | { 34 | DNS_HEADER *header = (DNS_HEADER*)dnsrequest.data(); 35 | 36 | header->QUERY_RESPONSE_FLAG = 1; //Change from query to response 37 | if(header->rd == 1) //Do this so there's not even a warning about about recursion requested but not available, let's say yes if it's requested. 38 | header->RECURSION_AVAILABLE_FLAG = 1; 39 | header->ans_count = qToBigEndian((quint16)1); 40 | header->rcode = RCODE_NOERROR; 41 | // DNS Answer 42 | unsigned char QAnswer[] = { 43 | 0xc0,0x0c, // 1100 0000 0000 1100 -> offset = 12 44 | 0x00,0x01, // Type : A 45 | 0x00,0x01, // Class : IN 46 | 0x00,0x01,0x51,0x80, // TTL = 86400 -> 24h 47 | 0x00,0x04, // RD Length 48 | 0x00,0x00,0x00,0x00 // RDATA 49 | }; 50 | QAnswer[12] = (responseIP & 0xff000000) >> 24; 51 | QAnswer[13] = (responseIP & 0x00ff0000) >> 16; 52 | QAnswer[14] = (responseIP & 0x0000ff00) >> 8; 53 | QAnswer[15] = (responseIP & 0x000000ff); 54 | 55 | QAnswer[6] = (ttl & 0xff000000) >> 24; 56 | QAnswer[7] = (ttl & 0x00ff0000) >> 16; 57 | QAnswer[8] = (ttl & 0x0000ff00) >> 8; 58 | QAnswer[9] = (ttl & 0x000000ff); 59 | 60 | // We add our answer containing our ip of choice! (localhost/127.0.0.1/injected server ip by default, change it in setings or adding a host with a custom ip to either list) 61 | if(spliceOffset < (quint32)dnsrequest.size()) //Make sure the splice offset / where the answer(s) should go is in bounds or don't use it 62 | dnsrequest.insert(spliceOffset, (char*)QAnswer, 16); 63 | else 64 | dnsrequest.append((char*)QAnswer, 16); 65 | } 66 | } 67 | 68 | void morphRequestIntoARecordResponse(QByteArray &dnsrequest, std::vector &responseIPs, quint32 spliceOffset, quint32 ttl) 69 | { 70 | if(dnsrequest.size() >= DNS_HEADER_SIZE) //Make sure there's at least a dns header here to write to 71 | { 72 | DNS_HEADER *header = (DNS_HEADER*)dnsrequest.data(); 73 | 74 | header->QUERY_RESPONSE_FLAG = 1; //Change from query to response 75 | if(header->rd == 1) //Do this so there's not even a warning about about recursion requested but not available, let's say yes if it's requested. 76 | header->RECURSION_AVAILABLE_FLAG = 1; 77 | header->rcode = RCODE_NOERROR; 78 | // DNS Answer 79 | unsigned char QAnswer[] = { 80 | 0xc0,0x0c, // 1100 0000 0000 1100 -> offset = 12 81 | 0x00,0x01, // Type : A 82 | 0x00,0x01, // Class : IN 83 | 0x00,0x01,0x51,0x80, // TTL = 86400 -> 24h 84 | 0x00,0x04, // RD Length 85 | 0x00,0x00,0x00,0x00 // RDATA 86 | }; 87 | 88 | QAnswer[6] = (ttl & 0xff000000) >> 24; 89 | QAnswer[7] = (ttl & 0x00ff0000) >> 16; 90 | QAnswer[8] = (ttl & 0x0000ff00) >> 8; 91 | QAnswer[9] = (ttl & 0x000000ff); 92 | 93 | if(responseIPs.size() > 0) 94 | { 95 | quint16 count = 0; 96 | QByteArray answers; 97 | for(quint32 ip : responseIPs) 98 | { 99 | QAnswer[12] = (ip & 0xff000000) >> 24; 100 | QAnswer[13] = (ip & 0x00ff0000) >> 16; 101 | QAnswer[14] = (ip & 0x0000ff00) >> 8; 102 | QAnswer[15] = (ip & 0x000000ff); 103 | 104 | // We add as many answers as ips we have to return to the requester 105 | answers.append((char*)QAnswer, 16); 106 | count++; 107 | } 108 | header->ans_count = qToBigEndian(count); 109 | 110 | if(spliceOffset < (quint32)dnsrequest.size()) //Make sure the splice offset / where the answer(s) should go is in bounds or don't use it 111 | dnsrequest.insert(spliceOffset, answers); 112 | else 113 | dnsrequest.append(answers); 114 | } 115 | else 116 | { 117 | // NXDOMAIN -> Non eXistent domain 118 | header->ans_count = 0; 119 | header->rcode = RCODE_NXDOMAIN; 120 | } 121 | } 122 | } 123 | 124 | InitialResponse::InitialResponse(DNSInfo &dns, QObject *parent) 125 | { 126 | Q_UNUSED(parent); 127 | respondTo.question.qtype = dns.question.qtype; 128 | respondTo.domainString = dns.domainString; 129 | respondTo.sender = dns.sender; 130 | respondTo.senderPort = dns.senderPort; 131 | respondTo.req = dns.req; 132 | respondTo.ttl = dns.ttl; 133 | timeWithoutAResponse = QDateTime::currentDateTime(); 134 | responseHandled = false; 135 | } 136 | 137 | void InitialResponse::lookupDoneSendResponseNow(DNSInfo &dns, QUdpSocket *serversocket) 138 | { 139 | if(respondTo == dns && !responseHandled) 140 | { 141 | if(respondTo.req.size() > DNS_HEADER_SIZE) 142 | { 143 | if(dns.question.qtype == DNS_TYPE_A) 144 | { 145 | if(dns.hasIPs) 146 | { 147 | morphRequestIntoARecordResponse(respondTo.req, dns.ipaddresses, dns.answeroffset, respondTo.ttl); 148 | serversocket->writeDatagram(respondTo.req, respondTo.sender, respondTo.senderPort); 149 | qDebug() << "[A RECORD] to:" << respondTo.sender << respondTo.senderPort << "\n" << respondTo.req; 150 | } 151 | } 152 | else 153 | { 154 | if(dns.res.size() > DNS_HEADER_SIZE) 155 | { 156 | *(quint16*)dns.res.data() = *(quint16*)respondTo.req.data(); //match the request/response ids in case they aren't matching 157 | serversocket->writeDatagram(dns.res, respondTo.sender, respondTo.senderPort); 158 | qDebug() << "Responding to a type:" << dns.question.qtype << "\n" << dns.res; 159 | } 160 | } 161 | } 162 | 163 | qDebug() << "Response handled in:" << ((float)timeWithoutAResponse.msecsTo(QDateTime::currentDateTime()) / 1000.0f) << "secs"; 164 | responseHandled = true; 165 | this->deleteLater(); 166 | } 167 | } 168 | 169 | void InitialResponse::deleteObjectsTheresNoResponseFor() 170 | { 171 | if(!responseHandled && timeWithoutAResponse.secsTo(QDateTime::currentDateTime()) > 60) 172 | this->deleteLater(); 173 | } 174 | -------------------------------------------------------------------------------- /CaptiveDNS/settingswindow.cpp: -------------------------------------------------------------------------------- 1 | #include "settingswindow.h" 2 | #include "ui_settingswindow.h" 3 | 4 | /* YourFriendlyDNS - A really awesome multi-platform (lin,win,mac,android) local caching and proxying dns server! 5 | Copyright (C) 2018 softwareengineer1 @ github.com/softwareengineer1 6 | 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, 7 | so I can keep bringing you great free and open software and continue to do so for a long time! 8 | I'm going entirely 100% free software this year in 2018 (and onwards I want to) :) 9 | Everything I make will be released under a free software license! That's my promise! 10 | If you want to contact me another way besides through github, insert your message into the blockchain with a BCH/BTC UTXO! ^_^ 11 | Thank you for your support! 12 | BCH: bitcoincash:qzh3knl0xeyrzrxm5paenewsmkm8r4t76glzxmzpqs 13 | BTC: 1279WngWQUTV56UcTvzVAnNdR3Z7qb6R8j 14 | (These are the payment methods I currently accept, 15 | if you want to support me via another cryptocurrency let me know and I'll probably start accepting that one too) 16 | 17 | This program is free software; you can redistribute it and/or modify 18 | it under the terms of the GNU General Public License as published by 19 | the Free Software Foundation; either version 2 of the License, or 20 | (at your option) any later version. 21 | 22 | This program is distributed in the hope that it will be useful, 23 | but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | GNU General Public License for more details. 26 | 27 | You should have received a copy of the GNU General Public License along 28 | with this program; if not, write to the Free Software Foundation, Inc., 29 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ 30 | 31 | SettingsWindow::SettingsWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::SettingsWindow) 32 | { 33 | ui->setupUi(this); 34 | indexhtml = new IndexHTML(); 35 | // sourcerAndStampConverter = new providerSourcerStampConverter(); 36 | // if(sourcerAndStampConverter) 37 | // { 38 | // connect(this, &SettingsWindow::decodeStamp, sourcerAndStampConverter, &providerSourcerStampConverter::decodeStamp); 39 | // connect(sourcerAndStampConverter, &providerSourcerStampConverter::addToServerList, this, &SettingsWindow::addToServerList); 40 | // } 41 | blockmode_localhost = true; 42 | 43 | #ifdef Q_OS_MACOS 44 | QFont font = ui->label->font(); 45 | font.setPointSize(11); 46 | QList widgets = this->findChildren(); 47 | foreach (QWidget *widget, widgets) 48 | { 49 | widget->setFont(font); 50 | } 51 | #endif 52 | } 53 | 54 | SettingsWindow::~SettingsWindow() 55 | { 56 | // if(sourcerAndStampConverter) 57 | // delete sourcerAndStampConverter; 58 | if(indexhtml) 59 | delete indexhtml; 60 | delete ui; 61 | } 62 | 63 | QString SettingsWindow::returnDedicatedDNSCrypter() 64 | { 65 | return ui->dedicatedDNSCrypt->text(); 66 | } 67 | 68 | QVector SettingsWindow::returnRealDNSServers() 69 | { 70 | QVector dnsservers; 71 | 72 | for(int i = 0; i < ui->realdnsservers->count(); i++) 73 | dnsservers.append(ui->realdnsservers->item(i)->text()); 74 | 75 | return dnsservers; 76 | } 77 | 78 | void SettingsWindow::clearDNSServers() 79 | { 80 | ui->realdnsservers->clear(); 81 | } 82 | 83 | bool SettingsWindow::isExisting(const QString &dns) 84 | { 85 | for(int i = 0; i < ui->realdnsservers->count(); i++) 86 | if(ui->realdnsservers->item(i)->text() == dns) 87 | return true; 88 | 89 | return false; 90 | } 91 | 92 | void SettingsWindow::appendDNSServer(const QString &dns) 93 | { 94 | if(!dns.isEmpty() && !isExisting(dns)) 95 | ui->realdnsservers->addItem(dns); 96 | } 97 | 98 | void SettingsWindow::addToServerList(QString stamp) 99 | { 100 | appendDNSServer(stamp); 101 | } 102 | 103 | void SettingsWindow::setRespondingIP(const QString &ip) 104 | { 105 | ui->respondingIP->setText(ip); 106 | } 107 | 108 | void SettingsWindow::setRespondingIPv6(const QString &ipv6) 109 | { 110 | ui->respondingIPv6->setText(ipv6); 111 | } 112 | 113 | bool SettingsWindow::getDNSCryptEnabled() 114 | { 115 | return ui->dnscryptEnabled->isChecked(); 116 | } 117 | 118 | bool SettingsWindow::getNewKeyPerRequestEnabled() 119 | { 120 | return ui->newKeyPerRequest->isChecked(); 121 | } 122 | 123 | QString SettingsWindow::getRespondingIP() 124 | { 125 | return ui->respondingIP->text(); 126 | } 127 | 128 | QString SettingsWindow::getDNSServerPort() 129 | { 130 | return ui->dnsServerPort->text(); 131 | } 132 | 133 | QString SettingsWindow::getHTTPServerPort() 134 | { 135 | return ui->httpServerPort->text(); 136 | } 137 | 138 | void SettingsWindow::setDNSCryptEnabled(bool yes) 139 | { 140 | ui->dnscryptEnabled->setChecked(yes); 141 | } 142 | 143 | void SettingsWindow::setNewKeyPerRequest(bool yes) 144 | { 145 | ui->newKeyPerRequest->setChecked(yes); 146 | } 147 | 148 | void SettingsWindow::setCachedMinutesValid(quint32 minutesValid) 149 | { 150 | ui->cacheValidMinutes->setText(QString("%1").arg(minutesValid)); 151 | } 152 | 153 | void SettingsWindow::setDNSServerPort(quint16 dnsServerPort) 154 | { 155 | ui->dnsServerPort->setText(QString("%1").arg(dnsServerPort)); 156 | } 157 | 158 | void SettingsWindow::setHTTPServerPort(quint16 httpServerPort) 159 | { 160 | ui->httpServerPort->setText(QString("%1").arg(httpServerPort)); 161 | } 162 | 163 | void SettingsWindow::setiptablesButtonEnabled(bool enabled) 164 | { 165 | ui->iptablesUndo->setVisible(enabled); 166 | ui->iptablesUndo->setEnabled(enabled); 167 | } 168 | 169 | quint32 SettingsWindow::getCachedMinutesValid() 170 | { 171 | return ui->cacheValidMinutes->text().toInt(); 172 | } 173 | 174 | void SettingsWindow::setBlockOptionNoResponse() 175 | { 176 | ui->option_noresponse->setChecked(true); 177 | } 178 | 179 | void SettingsWindow::setAutoInject(bool checked) 180 | { 181 | ui->autoinjectBox->setChecked(checked); 182 | if(checked) 183 | emit setIPToFirstListening(); 184 | } 185 | 186 | void SettingsWindow::setAutoTTL(bool autottl) 187 | { 188 | autoTTL = autottl; 189 | if(autoTTL) 190 | { 191 | quint32 ttl = (ui->cacheValidMinutes->text().toInt() * 60); 192 | ui->dnsTTL->setText(QString("%1").arg(ttl)); 193 | qDebug() << "Auto-setting DNS TTL:" << ttl; 194 | } 195 | } 196 | 197 | void SettingsWindow::setdnsTTL(quint32 dnsttl) 198 | { 199 | dnsTTL = dnsttl; 200 | ui->dnsTTL->setText(QString("%1").arg(dnsttl)); 201 | qDebug() << "Specified DNS TTL:" << dnsttl; 202 | emit settingsUpdated(); 203 | } 204 | 205 | void SettingsWindow::on_addButton_clicked() 206 | { 207 | if(!isExisting(ui->edit_dnsserver->text())) 208 | { 209 | ui->realdnsservers->addItem(ui->edit_dnsserver->text()); 210 | ui->edit_dnsserver->clear(); 211 | emit settingsUpdated(); 212 | } 213 | } 214 | 215 | void SettingsWindow::on_removeButton_clicked() 216 | { 217 | qDeleteAll(ui->realdnsservers->selectedItems()); 218 | emit settingsUpdated(); 219 | } 220 | 221 | void SettingsWindow::on_option_localhost_clicked() 222 | { 223 | blockmode_localhost = true; 224 | emit settingsUpdated(); 225 | } 226 | 227 | void SettingsWindow::on_option_noresponse_clicked() 228 | { 229 | blockmode_localhost = false; 230 | emit settingsUpdated(); 231 | } 232 | 233 | void SettingsWindow::on_cacheValidMinutes_editingFinished() 234 | { 235 | emit settingsUpdated(); 236 | } 237 | 238 | void SettingsWindow::on_respondingIP_editingFinished() 239 | { 240 | emit settingsUpdated(); 241 | } 242 | 243 | void SettingsWindow::on_edit_dnsserver_returnPressed() 244 | { 245 | on_addButton_clicked(); 246 | } 247 | 248 | void SettingsWindow::on_clearCacheButton_clicked() 249 | { 250 | emit clearDNSCache(); 251 | } 252 | 253 | void SettingsWindow::on_editindexButton_clicked() 254 | { 255 | if(indexhtml) 256 | indexhtml->show(); 257 | } 258 | 259 | void SettingsWindow::on_ipinjectButton_clicked() 260 | { 261 | emit setIPToFirstListening(); 262 | } 263 | 264 | void SettingsWindow::on_autoinjectBox_stateChanged(int arg1) 265 | { 266 | if(arg1) 267 | { 268 | emit setIPToFirstListening(); 269 | autoinject = true; 270 | } 271 | else 272 | autoinject = false; 273 | 274 | emit settingsUpdated(); 275 | } 276 | 277 | void SettingsWindow::on_captureCaptive_clicked() 278 | { 279 | emit autoCaptureCaptivePortals(); 280 | } 281 | 282 | void SettingsWindow::on_iptablesUndo_clicked() 283 | { 284 | emit iptablesUndoAndroid(); 285 | } 286 | 287 | void SettingsWindow::on_dnsTTL_textChanged(const QString &arg1) 288 | { 289 | if(arg1.size() > 0) 290 | { 291 | dnsTTL = arg1.toInt(); 292 | emit settingsUpdated(); 293 | } 294 | } 295 | 296 | void SettingsWindow::on_sameAsCachedBox_stateChanged(int arg1) 297 | { 298 | if(arg1) 299 | { 300 | autoTTL = true; 301 | setAutoTTL(autoTTL); 302 | } 303 | else 304 | autoTTL = false; 305 | 306 | emit settingsUpdated(); 307 | } 308 | 309 | void SettingsWindow::on_cacheValidMinutes_textChanged(const QString &arg1) 310 | { 311 | if(arg1.size() > 0) 312 | { 313 | if(autoTTL) 314 | { 315 | setAutoTTL(autoTTL); 316 | } 317 | emit settingsUpdated(); 318 | } 319 | } 320 | 321 | void SettingsWindow::on_dnscryptEnabled_stateChanged(int arg1) 322 | { 323 | if(arg1) 324 | setDNSCryptEnabled(arg1); 325 | emit settingsUpdated(); 326 | } 327 | 328 | void SettingsWindow::on_newKeyPerRequest_stateChanged(int arg1) 329 | { 330 | if(arg1) 331 | setNewKeyPerRequest(arg1); 332 | emit settingsUpdated(); 333 | } 334 | 335 | void SettingsWindow::on_backButton_clicked() 336 | { 337 | this->hide(); 338 | } 339 | 340 | void SettingsWindow::on_getProvidersButton_clicked() 341 | { 342 | // if(sourcerAndStampConverter) 343 | // sourcerAndStampConverter->show(); 344 | } 345 | 346 | void SettingsWindow::on_realdnsservers_itemClicked(QListWidgetItem *item) 347 | { 348 | // if(sourcerAndStampConverter && item->text().startsWith("sdns://")) 349 | // emit decodeStamp(item->text()); 350 | } 351 | -------------------------------------------------------------------------------- /CaptiveDNS/settingswindow.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | SettingsWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 965 10 | 511 11 | 12 | 13 | 14 | Settings 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 8 23 | 24 | 25 | 26 | Auto capture known captive portals! 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 8 35 | 36 | 37 | 38 | ^ Inject IPs ^ 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 8 47 | 48 | 49 | 50 | New Key Every Request 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 8 59 | 60 | 61 | 62 | Add 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 10 71 | 72 | 73 | 74 | Close 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 8 83 | 84 | 85 | 86 | <- Cached DNS responses # of minutes valid (0 == basically no cache) 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 8 95 | 96 | 97 | 98 | DNS Server Port: 99 | 100 | 101 | 102 | 103 | 104 | 105 | false 106 | 107 | 108 | 109 | 8 110 | 111 | 112 | 113 | Delete iptables entries (android) 114 | 115 | 116 | false 117 | 118 | 119 | false 120 | 121 | 122 | false 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 8 131 | 132 | 133 | 134 | Edit "index.html" 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 8 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 8 152 | 153 | 154 | 155 | 53 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 8 164 | 165 | 166 | 167 | 7 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 8 176 | 177 | 178 | 179 | 60 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 8 188 | 189 | 190 | 191 | Dont respond 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 8 200 | 201 | 202 | 203 | 127.0.0.1 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 10 212 | 213 | 214 | 215 | DNSCrypt Enabled! :) 216 | 217 | 218 | true 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 8 227 | 228 | 229 | 230 | 80 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 8 239 | 240 | 241 | 242 | Auto inject it 243 | 244 | 245 | true 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 8 254 | 255 | 256 | 257 | HTTP Server Port: 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 8 266 | 267 | 268 | 269 | Return localhost/127.0.0.1/custom: 270 | 271 | 272 | true 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 8 281 | 282 | 283 | 284 | DNS TTL(secs): 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 8 293 | 294 | 295 | 296 | 297 | sdns://AQAAAAAAAAAADjIwOC42Ny4yMjAuMjIwILc1EUAgbyJdPivYItf9aR6hwzzI1maNDL4Ev6vKQ_t5GzIuZG5zY3J5cHQtY2VydC5vcGVuZG5zLmNvbQ 298 | 299 | 300 | 301 | 302 | 208.67.222.222 303 | 304 | 305 | 306 | 307 | 208.67.220.220 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 8 317 | 318 | 319 | 320 | Lock to same as cached minutes valid 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 8 329 | 330 | 331 | 332 | Real DNS servers: 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 8 341 | 342 | 343 | 344 | Remove 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 8 353 | 354 | 355 | 356 | DNS Block Method: 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 8 365 | 366 | 367 | 368 | Dedicated v1 DNSCrypt for DoH/DoTLS host resolving: 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 8 377 | 378 | 379 | 380 | sdns://AQAAAAAAAAAADjIwOC42Ny4yMjAuMjIwILc1EUAgbyJdPivYItf9aR6hwzzI1maNDL4Ev6vKQ_t5GzIuZG5zY3J5cHQtY2VydC5vcGVuZG5zLmNvbQ 381 | 382 | 383 | 384 | 385 | 386 | 387 | ::1 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 8 396 | 397 | 398 | 399 | Clear cache now 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 8 408 | 409 | 410 | 411 | Get/Convert Providers! 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | -------------------------------------------------------------------------------- /CaptiveDNS/buffer.h: -------------------------------------------------------------------------------- 1 | #ifndef BUFFER_H 2 | #define BUFFER_H 3 | 4 | //Idea from: Nigshoxiz / DemoHn -> github.com/DemoHn 5 | //Found here: https://github.com/DemoHn/asyncDNS-Qt/blob/master/buffer.cpp 6 | //Rewritten to be safer and consistently compiled across platforms to still work properly across platforms 7 | //Thanks for showing me a better way to do what I needed to do Nigshoxiz! :) 8 | //Rewritten by softwareengineer1 @ github.com/softwareengineer1 9 | //Part of YourFriendlyDNS, found at github.com/softwareengineer1/YourFriendlyDNS 10 | 11 | //Note from during rewriting: Scratch that, it's also unsafe, as different compilers compile it differently making it crash on some platforms 12 | //so I'm re-writing it as a c++ templated parameter pack function instead of old c style var_arg (which is causing undefined behavior and incompatibility) 13 | 14 | /* This program is free software; you can redistribute it and/or modify 15 | it under the terms of the GNU General Public License as published by 16 | the Free Software Foundation; either version 2 of the License, or 17 | (at your option) any later version. 18 | 19 | This program is distributed in the hope that it will be useful, 20 | but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | GNU General Public License for more details. 23 | 24 | You should have received a copy of the GNU General Public License along 25 | with this program; if not, write to the Free Software Foundation, Inc., 26 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | template std::string type_name() 36 | { 37 | typedef typename std::remove_reference::type TR; 38 | std::string r = typeid(TR).name(); 39 | if (std::is_const::value) 40 | r += " const"; 41 | if (std::is_volatile::value) 42 | r += " volatile"; 43 | if (std::is_lvalue_reference::value) 44 | r += "&"; 45 | else if (std::is_rvalue_reference::value) 46 | r += "&&"; 47 | return r; 48 | } 49 | 50 | class Var 51 | { 52 | public: 53 | Var(void *pVar, quint64 varSize) 54 | { 55 | var = pVar; 56 | size = varSize; 57 | } 58 | void *var; 59 | quint64 size; 60 | }; 61 | 62 | //When PACKED_BUFFER_IS_BIG_ENDIAN flag is set and when your host byte order is little endian (ex. x86_64), 63 | //it will pack from little endian source variables into a big endian buffer, and unpack from a big endian buffer to little endian destination variables. 64 | //if your host byte order is big endian no change will occur when packing or unpacking as the bytes will already be in the right order. 65 | //When PACKED_BUFFER_IS_BIG_ENDIAN flag is not set and when your host byte order is big endian (ex. PowerPC), 66 | //it will pack from big endian source variables into a little endian buffer, and unpack from a little endian buffer to big endian destination variables 67 | //if your host byte order is little endian then no change will occur when packing or unpacking as the bytes will already be in the right order. 68 | 69 | #define PACKED_BUFFER_IS_BIG_ENDIAN 1 70 | 71 | class ModernBuffer 72 | { 73 | public: 74 | ModernBuffer(const ModernBuffer &buffer) 75 | { 76 | buf = buffer.buf; 77 | init(); 78 | } 79 | ModernBuffer(const QByteArray &buffer) 80 | { 81 | buf = buffer; 82 | init(); 83 | } 84 | ModernBuffer(const char *buffer, quint64 length) 85 | { 86 | buf.append(buffer, length); 87 | init(); 88 | } 89 | ModernBuffer(quint64 startingSize) 90 | { 91 | buf.reserve(startingSize); 92 | init(); 93 | } 94 | ModernBuffer() { init(); } 95 | void init(bool isBigEndian = true) 96 | { 97 | flags = fmtIndex = fmtLen = packedLen = unpackedLen = 0; 98 | if(isBigEndian) 99 | flags |= PACKED_BUFFER_IS_BIG_ENDIAN; 100 | } 101 | 102 | 103 | /* pack: 104 | * B : Byte : 1 byte (unsigned char) 105 | * W : Word : 2 bytes (unsigned short) 106 | * L : Long : 4 bytes (unsigned int) 107 | * I : LongLong : 8 bytes (unsigned long long) 108 | * T : typename T : Experimental any type (this is the only time you pass a full type directly rather than by reference/pointer) 109 | * Z : String : N bytes (char* that ends with '\0') 110 | * z : Prefixed Length String : [N][N Bytes] (char* that's prefixed with it's length using a single byte) from a QString or QByteArray 111 | * x : QByteArray or QString : N bytes (doesn't need to be null terminated and it uses it's size for N bytes) 112 | */ 113 | 114 | template static quint64 pack(QByteArray &buff, const char *fmt, Params... parameters) 115 | { 116 | ModernBuffer buffer; 117 | buffer.pack(fmt, parameters...); 118 | buff = buffer.buf; 119 | return buffer.packedLen; 120 | } 121 | 122 | template quint64 pack(const char *fmt, Params... parameters) 123 | { 124 | this->fmt = fmt; 125 | fmtLen = strlen(fmt); 126 | fmtIndex = 0; 127 | packedLen = 0; 128 | 129 | return pack(parameters...); 130 | } 131 | 132 | template quint64 pack(T source, Params... next) 133 | { 134 | doPackStep(source); 135 | 136 | return pack(next...); 137 | } 138 | 139 | template quint64 pack(T source) 140 | { 141 | doPackStep(source); 142 | 143 | return packedLen; 144 | } 145 | 146 | template void doPackStep(T source) 147 | { 148 | if(fmtIndex == fmtLen || fmt[fmtIndex] == 0) 149 | return; 150 | 151 | if(fmt[fmtIndex] == 'B') 152 | { 153 | quint8 byte = *(quint8*)source; 154 | buf.append(byte, sizeof(byte)); 155 | packedLen++; 156 | } 157 | else if(fmt[fmtIndex] == 'W') 158 | { 159 | quint16 word; 160 | if(flags & PACKED_BUFFER_IS_BIG_ENDIAN) 161 | word = qToBigEndian(*(quint16*)source); 162 | else 163 | word = qToLittleEndian(*(quint16*)source); 164 | buf.append((const char*)&word, 2); 165 | packedLen += 2; 166 | } 167 | else if(fmt[fmtIndex] == 'L') 168 | { 169 | quint32 Long; 170 | if(flags & PACKED_BUFFER_IS_BIG_ENDIAN) 171 | Long = qToBigEndian(*(quint32*)source); 172 | else 173 | Long = qToLittleEndian(*(quint32*)source); 174 | buf.append((const char*)&Long, 4); 175 | packedLen += 4; 176 | } 177 | else if(fmt[fmtIndex] == 'I') 178 | { 179 | quint64 LongLong; 180 | if(flags & PACKED_BUFFER_IS_BIG_ENDIAN) 181 | LongLong = qToBigEndian(*(quint64*)source); 182 | else 183 | LongLong = qToLittleEndian(*(quint64*)source); 184 | buf.append((const char*)&LongLong, 8); 185 | packedLen += 8; 186 | } 187 | /*else if(fmt[fmtIndex] == 'T') //Any type 188 | { 189 | T typeT; 190 | qDebug() << "Packing typeT:" << type_name().c_str() << "size:" << sizeof typeT; 191 | 192 | if(flags & PACKED_BUFFER_IS_BIG_ENDIAN) 193 | typeT = qToBigEndian(*(T*)source); 194 | else 195 | typeT = qToLittleEndian(*(T*)source); 196 | 197 | buf.append((const char*)&typeT, sizeof typeT); 198 | packedLen += sizeof typeT; 199 | }*/ 200 | else if(fmt[fmtIndex] == 'Z') //Null-terminated C String 201 | { 202 | size_t len = strlen((const char*)source); 203 | buf.append((const char*)source, len + 1); 204 | packedLen += len + 1; 205 | } 206 | else if(fmt[fmtIndex] == 'z') //Prefixed Length String 207 | { 208 | // quint8 prefixedLen; 209 | // QString *s; 210 | // if(type_name() == type_name()) 211 | // { 212 | // QByteArray *src = (QByteArray*)source; 213 | // prefixedLen = src->size(); 214 | // buf.append(prefixedLen, sizeof(prefixedLen)); 215 | // buf.append(*src, prefixedLen); 216 | // packedLen += prefixedLen + 1; 217 | // } 218 | // else if(type_name() == type_name()) 219 | // { 220 | // s = (QString*)source; 221 | // prefixedLen = s->size(); 222 | // buf.append(prefixedLen, sizeof(prefixedLen)); 223 | // buf.append(*s, prefixedLen); 224 | // packedLen += prefixedLen + 1; 225 | // } 226 | } 227 | else if(fmt[fmtIndex] == 'x') //QByteArray or QString 228 | { 229 | // QString *s; 230 | // if(type_name() == type_name()) 231 | // { 232 | // QByteArray *src = (QByteArray*)source; 233 | // buf.append(*src); 234 | // packedLen += src->size(); 235 | // } 236 | // else if(type_name() == type_name()) 237 | // { 238 | // s = (QString*)source; 239 | // buf.append(*s); 240 | // packedLen += s->size(); 241 | // } 242 | } 243 | 244 | fmtIndex++; 245 | } 246 | 247 | /* unpack: 248 | B : Byte : 1 byte 249 | W : Word : 2 bytes 250 | L : Long : 4 bytes 251 | I : LongLong : 8 bytes 252 | Z : String : N bytes (char* that ends with '\0') *this and below (can unpack into QString, QByteArray, or raw array) 253 | z : Prefixed Length String : [N][N bytes] (char* that's prefixed with it's length using a single byte) 254 | [] : bytes. e.g. : [5] represents 5 bytes (for an arbitrary known length to copy) 255 | [&] : its length is determined by the value of the th variable. 256 | e.g. : "BBBL[&3]" <--> "BBBL[7]" if the parsing data is (00 01 07 04 03 02 01 [01 02 03 04 05 06 07]) 257 | NOTICE : the referenced data is restricted before it. And QByteArray type is not counted. 258 | e.g. : 259 | "BB[32]L[&3]" --> refers to the value of "L" format data. the "[32]" is not counted when calculating the order. 260 | */ 261 | 262 | template static quint64 unpack(QByteArray &buff, const char *fmt, Params... parameters) 263 | { 264 | ModernBuffer buffer(buff); 265 | return buffer.unpack(fmt, parameters...); 266 | } 267 | 268 | template quint64 unpack(const char *fmt, Params... parameters) 269 | { 270 | this->fmt = fmt; 271 | fmtLen = strlen(fmt); 272 | fmtIndex = 0; 273 | unpackedLen = 0; 274 | vars.clear(); 275 | 276 | return unpack(parameters...); 277 | } 278 | 279 | template quint64 unpack(T destination, Params... next) 280 | { 281 | doUnpackStep(destination); 282 | 283 | return unpack(next...); 284 | } 285 | 286 | template quint64 unpack(T destination) 287 | { 288 | doUnpackStep(destination); 289 | 290 | return unpackedLen; 291 | } 292 | 293 | template void doUnpackStep(T destination) 294 | { 295 | if(fmtIndex == fmtLen || fmt[fmtIndex] == 0) 296 | return; 297 | 298 | if(fmt[fmtIndex] == 'B') 299 | { 300 | if(buf.size() < 1) return; 301 | *(quint8*)destination = buf.at(0); 302 | buf.remove(0, 1); 303 | vars.push_back(Var(destination, 1)); 304 | unpackedLen++; 305 | } 306 | else if(fmt[fmtIndex] == 'W') 307 | { 308 | if(buf.size() < 2) return; 309 | if(flags & PACKED_BUFFER_IS_BIG_ENDIAN) 310 | *(quint16*)destination = qFromBigEndian(*(quint16*)buf.data()); 311 | else 312 | *(quint16*)destination = qFromLittleEndian(*(quint16*)buf.data()); 313 | buf.remove(0, 2); 314 | vars.push_back(Var(destination, 2)); 315 | unpackedLen += 2; 316 | } 317 | else if(fmt[fmtIndex] == 'L') 318 | { 319 | if(buf.size() < 4) return; 320 | if(flags & PACKED_BUFFER_IS_BIG_ENDIAN) 321 | *(quint32*)destination = qFromBigEndian(*(quint32*)buf.data()); 322 | else 323 | *(quint32*)destination = qFromLittleEndian(*(quint32*)buf.data()); 324 | buf.remove(0, 4); 325 | vars.push_back(Var(destination, 4)); 326 | unpackedLen += 4; 327 | } 328 | else if(fmt[fmtIndex] == 'I') 329 | { 330 | if(buf.size() < 8) return; 331 | if(flags & PACKED_BUFFER_IS_BIG_ENDIAN) 332 | *(quint64*)destination = qFromBigEndian(*(quint64*)buf.data()); 333 | else 334 | *(quint64*)destination = qFromLittleEndian(*(quint64*)buf.data()); 335 | buf.remove(0, 8); 336 | vars.push_back(Var(destination, 8)); 337 | unpackedLen += 8; 338 | } 339 | else if(fmt[fmtIndex] == 'Z') //C String 340 | { 341 | int strLen = -1; 342 | for(int i = 0; i < buf.size(); i++) 343 | { 344 | if(buf.at(i) == '\0') 345 | { 346 | strLen = i; 347 | break; 348 | } 349 | } 350 | if(strLen == -1) return; 351 | 352 | copyBytesToDestination(destination, strLen); 353 | 354 | buf.remove(0, strLen + 1); 355 | unpackedLen += strLen + 1; 356 | } 357 | else if(fmt[fmtIndex] == 'z') //Prefixed Length String 358 | { 359 | if(buf.size() < 1) return; 360 | quint8 prefixedLen = buf.at(0); 361 | buf.remove(0, 1); 362 | if(buf.size() < prefixedLen) return; 363 | 364 | copyBytesToDestination(destination, prefixedLen); 365 | 366 | buf.remove(0, prefixedLen); 367 | unpackedLen += prefixedLen; 368 | } 369 | else if(fmt[fmtIndex] == '[') 370 | { 371 | fmtIndex++; 372 | if(fmtIndex == fmtLen || fmt[fmtIndex] == 0) return; 373 | if(fmt[fmtIndex] == '&') //referencing a variable to use as the size of this variable 374 | { 375 | fmtIndex++; 376 | quint64 referencingVarNum = extractUpToNextClosingBracket(); 377 | 378 | if(referencingVarNum == 0 || referencingVarNum > vars.size()) 379 | { 380 | qDebug() << "Check your format string, you're doing it wrong!"; 381 | qDebug() << "Either we reached the end before encountering a closing bracket, or the referencing variable doesn't exist"; 382 | return; 383 | } 384 | 385 | quint64 refVarLen = vars[referencingVarNum - 1].size, varLen = 0; 386 | if(refVarLen <= sizeof varLen) 387 | memcpy(&varLen, vars[referencingVarNum - 1].var, refVarLen); 388 | 389 | if((quint64)buf.size() < varLen) return; 390 | 391 | copyBytesToDestination(destination, varLen); 392 | 393 | buf.remove(0, varLen); 394 | unpackedLen += varLen; 395 | } 396 | else //just using the size provided as the size of this variable 397 | { 398 | quint64 varLen = extractUpToNextClosingBracket(); 399 | 400 | if(varLen == 0 || varLen > (quint64)buf.size()) 401 | { 402 | qDebug() << "Check your format string, you're doing it wrong! ;)"; 403 | qDebug() << "Either we reached the end before encountering a closing bracket, or specified variable length exceeds remaining buffer to extract it from"; 404 | return; 405 | } 406 | 407 | copyBytesToDestination(destination, varLen); 408 | 409 | buf.remove(0, varLen); 410 | unpackedLen += varLen; 411 | } 412 | } 413 | 414 | fmtIndex++; 415 | } 416 | 417 | const char *fmt; 418 | QByteArray buf; 419 | std::vector vars; 420 | quint64 fmtIndex, fmtLen, unpackedLen, packedLen; 421 | quint8 flags; 422 | 423 | private: 424 | template void copyBytesToDestination(T destination, size_t numBytes) 425 | { 426 | QString str; 427 | if(type_name() == type_name()) 428 | { 429 | //Copy to a QByteArray 430 | QByteArray *dest = (QByteArray*)destination; 431 | dest->resize(numBytes); 432 | memcpy(dest->data(), buf.data(), numBytes); 433 | } 434 | else if(type_name() == type_name()) 435 | { 436 | //Or copy to a QString 437 | QString *qstr = (QString*)destination; 438 | QByteArray dest; 439 | dest.resize(numBytes); 440 | memcpy(dest.data(), buf.data(), numBytes); 441 | *qstr = dest; 442 | } 443 | else //Or copy to any allocated memory (there better be enough there if you call it like this) 444 | memcpy((void*)destination, buf.data(), numBytes); 445 | } 446 | quint64 extractUpToNextClosingBracket() 447 | { 448 | QString extractedNum; 449 | while(fmtIndex < fmtLen) 450 | { 451 | extractedNum += fmt[fmtIndex++]; 452 | if(fmt[fmtIndex] == ']') 453 | { 454 | return extractedNum.toLongLong(); 455 | } 456 | } 457 | return 0; 458 | } 459 | }; 460 | 461 | #endif // BUFFER_H 462 | -------------------------------------------------------------------------------- /CaptiveDNS/GPLv2.txt: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /CaptiveDNS/dnsserverwindow.cpp: -------------------------------------------------------------------------------- 1 | #include "dnsserverwindow.h" 2 | #include "ui_dnsserverwindow.h" 3 | 4 | #include 5 | 6 | /* YourFriendlyDNS - A really awesome multi-platform (lin,win,mac,android) local caching and proxying dns server! 7 | Copyright (C) 2018 softwareengineer1 @ github.com/softwareengineer1 8 | 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, 9 | so I can keep bringing you great free and open software and continue to do so for a long time! 10 | I'm going entirely 100% free software this year in 2018 (and onwards I want to) :) 11 | Everything I make will be released under a free software license! That's my promise! 12 | If you want to contact me another way besides through github, insert your message into the blockchain with a BCH/BTC UTXO! ^_^ 13 | Thank you for your support! 14 | BCH: bitcoincash:qzh3knl0xeyrzrxm5paenewsmkm8r4t76glzxmzpqs 15 | BTC: 1279WngWQUTV56UcTvzVAnNdR3Z7qb6R8j 16 | (These are the payment methods I currently accept, 17 | if you want to support me via another cryptocurrency let me know and I'll probably start accepting that one too) 18 | 19 | This program is free software; you can redistribute it and/or modify 20 | it under the terms of the GNU General Public License as published by 21 | the Free Software Foundation; either version 2 of the License, or 22 | (at your option) any later version. 23 | 24 | This program is distributed in the hope that it will be useful, 25 | but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 | GNU General Public License for more details. 28 | 29 | You should have received a copy of the GNU General Public License along 30 | with this program; if not, write to the Free Software Foundation, Inc., 31 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ 32 | 33 | Ui::DNSServerWindow* DNSServerWindow::mainUi = NULL; 34 | 35 | DNSServerWindow::DNSServerWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::DNSServerWindow) 36 | { 37 | ui->setupUi(this); 38 | qRegisterMetaType("ListEntry"); 39 | qRegisterMetaType>("std::vector"); 40 | qRegisterMetaType("QHostAddress"); 41 | 42 | DNSServerWindow::mainUi = ui; 43 | 44 | settingspath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); 45 | QDir d{settingspath}; 46 | if(d.mkpath(d.absolutePath())) 47 | qDebug() << "CaptiveDNS settings storage location:" << settingspath; 48 | 49 | settingspath += QDir::separator(); 50 | qDebug() << "CaptiveDNS settings location:" << settingspath; 51 | 52 | settings = new SettingsWindow(); 53 | connect(settings, SIGNAL(settingsUpdated()), this, SLOT(settingsUpdated())); 54 | connect(settings, SIGNAL(setIPToFirstListening()), this, SLOT(setIPToFirstListening())); 55 | connect(settings, SIGNAL(autoCaptureCaptivePortals()), this, SLOT(autoCaptureCaptivePortals())); 56 | connect(settings, SIGNAL(iptablesUndoAndroid()), this, SLOT(iptablesUndoAndroid())); 57 | connect(settings->indexhtml, SIGNAL(htmlChanged(QString&)), this, SLOT(htmlChanged(QString&))); 58 | 59 | cacheviewer = new CacheViewer(); 60 | connect(this, SIGNAL(displayCache(const std::vector&)), cacheviewer, SLOT(displayCache(const std::vector&))); 61 | 62 | preloadServerPorts(); 63 | 64 | messagesThread = new MessagesThread(); 65 | connect(messagesThread, SIGNAL(finished()), this, SLOT(deleteLater())); 66 | connect(messagesThread, SIGNAL(serversInitialized()), this, SLOT(serversInitialized())); 67 | connect(messagesThread, SIGNAL(androidInit()), this, SLOT(androidInit())); 68 | messagesThread->start(); 69 | 70 | #ifdef Q_OS_ANDROID 71 | // ui->settingsButton->setIconSize(QSize(128,128)); 72 | // ui->firstAddButton->setIconSize(QSize(64,64)); 73 | // ui->secondAddButton->setIconSize(QSize(64,64)); 74 | // ui->removeButton->setIconSize(QSize(64,64)); 75 | #endif 76 | #ifdef Q_OS_MACOS 77 | // QFont font = ui->label->font(); 78 | // font.setPointSize(11); 79 | // QList widgets = this->findChildren(); 80 | // foreach (QWidget *widget, widgets) 81 | // { 82 | // widget->setFont(font); 83 | // } 84 | #endif 85 | } 86 | 87 | DNSServerWindow::~DNSServerWindow() 88 | { 89 | settingsSave(); 90 | if(settings) 91 | delete settings; 92 | 93 | delete ui; 94 | } 95 | 96 | void DNSServerWindow::serversInitialized() 97 | { 98 | server = AppData::get()->dnsServer; 99 | httpServer = AppData::get()->httpServer; 100 | connect(server, SIGNAL(queryRespondedTo(ListEntry)), this, SLOT(queryRespondedTo(ListEntry))); 101 | // connect(server->dnscrypt, &DNSCrypt::displayLastUsedProvider, this, &DNSServerWindow::displayLastUsedProvider); 102 | connect(settings, SIGNAL(clearDNSCache()), server, SLOT(clearDNSCache())); 103 | // connect(this, &DNSServerWindow::clearSources, settings->sourcerAndStampConverter, &providerSourcerStampConverter::clearSources); 104 | // connect(this, &DNSServerWindow::loadSource, settings->sourcerAndStampConverter, &providerSourcerStampConverter::loadSource); 105 | connect(cacheviewer, &CacheViewer::deleteEntriesFromCache, server, &SmallDNSServer::deleteEntriesFromCache); 106 | 107 | listeningIPsUpdate(); 108 | settingsLoad(); 109 | settingsUpdated(); 110 | settings->setiptablesButtonEnabled(false); 111 | } 112 | 113 | void DNSServerWindow::displayLastUsedProvider(quint64 props, QString providerName, QHostAddress server, quint16 port) 114 | { 115 | QString Props; 116 | if(props & 2) Props += "\nDoesn't log"; 117 | if(props & 4) Props += "\nDoesn't filter"; 118 | if(props & 1) Props += "\nSupports DNSSEC"; 119 | // ui->encEnabled->setText(QString("ENCRYPTION ENABLED! :)\nProvider last used:\n%1\n%2:%3%4").arg(providerName).arg(server.toString()).arg(port).arg(Props)); 120 | } 121 | 122 | void DNSServerWindow::androidInit() 123 | { 124 | settings->setiptablesButtonEnabled(); 125 | } 126 | 127 | void DNSServerWindow::htmlChanged(QString &html) 128 | { 129 | if(httpServer) 130 | httpServer->setHTML(html); 131 | } 132 | 133 | void DNSServerWindow::listeningIPsUpdate() 134 | { 135 | QList list = QNetworkInterface::allAddresses(); 136 | QVector ipslist; 137 | QVector ipv6slist; 138 | QString listeningips = ""; 139 | if(list.size() > 0) 140 | { 141 | for(int i = 0; i < list.count(); i++) 142 | { 143 | if(!list[i].isLoopback()) 144 | { 145 | // if(listeningips == "") listeningips = "Local DNS Address:\n"; 146 | if(list[i].protocol() == QAbstractSocket::IPv4Protocol) 147 | { 148 | ipslist.append(QHostAddress(list[i].toString()).toIPv4Address()); 149 | listeningips += list[i].toString() + "\n"; 150 | } 151 | // No ipv6 in captivedns (yet?) 152 | 153 | // else if(list[i].protocol() == QAbstractSocket::IPv6Protocol) 154 | // { 155 | // ipv6slist.append(QHostAddress(list[i].toString()).toIPv6Address()); 156 | // listeningips += "[" + QHostAddress(QHostAddress(list[i].toString()).toIPv6Address()).toString() + "], "; 157 | // } 158 | } 159 | } 160 | listeningips.truncate(listeningips.size()-1); 161 | // listeningips.append("\n\nEnter the above address into your device's DNS settings."); 162 | } 163 | 164 | if(ipslist.size() > 0) 165 | { 166 | // sort the ipslist so that the first one is the one we want to respond with 167 | // (eg. prioritize 192.168.x.x over 10.x.x.x, over 172.16.x.x, etc.) 168 | 169 | // sort the list 170 | std::sort(ipslist.begin(), ipslist.end()); 171 | 172 | // check for 10.x.x.x 173 | for (int i = 0; i < ipslist.size(); i++) 174 | { 175 | if((ipslist[i] & 0xFF000000) == 0x0A000000) 176 | { 177 | // move it to the front 178 | ipslist.prepend(ipslist[i]); 179 | ipslist.remove(i+1); 180 | break; 181 | } 182 | } 183 | 184 | // check for 192.168.x.x 185 | for (int i = 0; i < ipslist.size(); i++) 186 | { 187 | if((ipslist[i] & 0xFFFF0000) == 0xC0A80000) 188 | { 189 | // move it to the front 190 | ipslist.prepend(ipslist[i]); 191 | ipslist.remove(i+1); 192 | break; 193 | } 194 | } 195 | 196 | // really, which IP to use should be a choice in the UI 197 | // but for now we'll just use the first one and sort the list 198 | 199 | server->listeningIPs = ipslist; 200 | } 201 | if(ipv6slist.size() > 0) 202 | { 203 | server->listeningIPv6s = ipv6slist; 204 | } 205 | 206 | if(listeningips == "") 207 | { 208 | listeningips = "No non-loopback listening network addresses detected...\ 209 | Check network connection!"; 210 | } 211 | 212 | ui->listeningIPs->setText(listeningips); 213 | } 214 | 215 | void DNSServerWindow::setIPToFirstListening() 216 | { 217 | if(server && settings) 218 | { 219 | listeningIPsUpdate(); 220 | if(server->listeningIPs.size() > 0) 221 | { 222 | settings->setRespondingIP(QHostAddress(server->listeningIPs[0]).toString()); 223 | server->ipToRespondWith = server->listeningIPs[0]; 224 | } 225 | // if(server->listeningIPv6s.size() > 0) 226 | // { 227 | // settings->setRespondingIPv6(QHostAddress(server->listeningIPv6s[0]).toString()); 228 | // server->ipv6ToRespondWith = server->listeningIPv6s[0]; 229 | // } 230 | } 231 | } 232 | 233 | void DNSServerWindow::settingsUpdated() 234 | { 235 | if(server && settings) 236 | { 237 | server->dnscryptEnabled = settings->getDNSCryptEnabled(); 238 | // ui->encEnabled->setVisible(server->dnscryptEnabled); 239 | // server->dnscrypt->newKeyPerRequest = settings->getNewKeyPerRequestEnabled(); 240 | server->blockmode_returnlocalhost = settings->blockmode_localhost; 241 | server->ipToRespondWith = QHostAddress(settings->getRespondingIP()).toIPv4Address(); 242 | server->cachedMinutesValid = settings->getCachedMinutesValid(); 243 | server->realdns = settings->returnRealDNSServers(); 244 | server->dedicatedDNSCrypter = settings->returnDedicatedDNSCrypter(); 245 | server->determineDoHDoTLSProviders(); 246 | server->dnsTTL = settings->dnsTTL; 247 | server->autoTTL = settings->autoTTL; 248 | } 249 | } 250 | 251 | void DNSServerWindow::queryRespondedTo(ListEntry e) 252 | { 253 | QString ip = e.ip ? QHostAddress(e.ip).toString() : ""; 254 | 255 | // for(int i = 0; i < ui->dnsqueries->topLevelItemCount(); i++) 256 | // { 257 | // if(ui->dnsqueries->topLevelItem(i)->text(1) == e.hostname) 258 | // { 259 | // ui->dnsqueries->topLevelItem(i)->setText(0, ip); 260 | // return; 261 | // } 262 | // } 263 | 264 | // ui->dnsqueries->addTopLevelItem(new QTreeWidgetItem(QStringList() << ip << e.hostname)); 265 | } 266 | 267 | void DNSServerWindow::autoCaptureCaptivePortals() 268 | { 269 | // the list that is used is in smalldnsserver.cpp around line 60 270 | 271 | refreshList(); 272 | } 273 | 274 | void DNSServerWindow::iptablesUndoAndroid() 275 | { 276 | #ifdef Q_OS_ANDROID 277 | AndroidSU_ServerOP *suOP = new AndroidSU_ServerOP(AndroidSU_ServerOP::opcode::iptablesRemove, AppData::get()->dnsServerPort, AppData::get()->httpServerPort); 278 | connect(suOP, SIGNAL(finished()), suOP, SLOT(deleteLater())); 279 | suOP->start(); 280 | #endif 281 | } 282 | 283 | void DNSServerWindow::appendToBlacklist(ListEntry e) 284 | { 285 | for(ListEntry &entry : server->blacklist) 286 | { 287 | if(entry.hostname == e.hostname) 288 | return; 289 | } 290 | server->blacklist.append(e); 291 | } 292 | 293 | void DNSServerWindow::on_firstAddButton_clicked() 294 | { 295 | bool append = true; 296 | // ListEntry e(ui->hostnameEdit->text()); 297 | // if(e.hostname.isEmpty()) return; 298 | // if(!ui->ipEdit->text().isEmpty()) 299 | // e.ip = QHostAddress(ui->ipEdit->text()).toIPv4Address(); 300 | 301 | // ui->hostnameEdit->clear(); 302 | // ui->ipEdit->clear(); 303 | if(server->whitelistmode) 304 | { 305 | for(ListEntry &entry : server->whitelist) 306 | { 307 | // if(entry.hostname == e.hostname) 308 | // { 309 | // // entry.ip = e.ip; 310 | // append = false; 311 | // } 312 | } 313 | // if(append) 314 | // server->whitelist.append(e); 315 | } 316 | else 317 | { 318 | for(ListEntry &entry : server->blacklist) 319 | { 320 | // if(entry.hostname == e.hostname) 321 | // { 322 | // // entry.ip = e.ip; 323 | // append = false; 324 | // } 325 | } 326 | // if(append) 327 | // server->blacklist.append(e); 328 | } 329 | 330 | // if(append) 331 | // ui->dnslist->addTopLevelItem(new QTreeWidgetItem(QStringList() << ui->ipEdit->text() << ui->hostnameEdit->text())); 332 | 333 | refreshList(); 334 | } 335 | 336 | void DNSServerWindow::refreshList() 337 | { 338 | // ui->dnslist->clear(); 339 | // ui->dnslist->clear(); 340 | // if(server->whitelistmode) 341 | // { 342 | // for(ListEntry &e : server->whitelist) 343 | // { 344 | // if(e.ip == 0) 345 | // ui->dnslist->addTopLevelItem(new QTreeWidgetItem(QStringList() << "" << e.hostname)); 346 | // else 347 | // ui->dnslist->addTopLevelItem(new QTreeWidgetItem(QStringList() << QHostAddress(e.ip).toString() << e.hostname)); 348 | // } 349 | // } 350 | // else 351 | // { 352 | // for(ListEntry &e : server->blacklist) 353 | // { 354 | // if(e.ip == 0) 355 | // ui->dnslist->addTopLevelItem(new QTreeWidgetItem(QStringList() << "" << e.hostname)); 356 | // else 357 | // ui->dnslist->addTopLevelItem(new QTreeWidgetItem(QStringList() << QHostAddress(e.ip).toString() << e.hostname)); 358 | // } 359 | // } 360 | } 361 | 362 | void DNSServerWindow::on_whitelistButton_clicked() 363 | { 364 | server->whitelistmode = true; 365 | // ui->whitelistButton->setChecked(true); 366 | refreshList(); 367 | } 368 | 369 | void DNSServerWindow::on_blacklistButton_clicked() 370 | { 371 | server->whitelistmode = false; 372 | // ui->blacklistButton->setChecked(true); 373 | refreshList(); 374 | } 375 | 376 | bool DNSServerWindow::settingsSave() 377 | { 378 | return false; // not used in captivedns 379 | 380 | // QFile file(settingspath); 381 | // if(file.open(QFile::WriteOnly)) 382 | // { 383 | // QJsonObject json; 384 | // json["version"] = "2.1"; 385 | // server->dnscryptEnabled = settings->getDNSCryptEnabled(); 386 | // json["dnscryptEnabled"] = server->dnscryptEnabled; 387 | // // server->dnscrypt->newKeyPerRequest = settings->getNewKeyPerRequestEnabled(); 388 | // json["dedicatedDNSCrypter"] = server->dedicatedDNSCrypter; 389 | // // json["newKeyPerRequest"] = server->dnscrypt->newKeyPerRequest; 390 | // json["initialMode"] = server->initialMode; 391 | // json["whitelistmode"] = server->whitelistmode; 392 | // json["blockmode_returnlocalhost"] = server->blockmode_returnlocalhost; 393 | // json["autoinjectip"] = settings->autoinject; 394 | // server->ipToRespondWith = QHostAddress(settings->getRespondingIP()).toIPv4Address(); 395 | // json["ipToRespondWith"] = (int)server->ipToRespondWith; 396 | // json["cachedMinutesValid"] = (int)server->cachedMinutesValid; 397 | // json["dnsTTL"] = (int)server->dnsTTL; 398 | // json["autoTTL"] = server->autoTTL; 399 | // AppData::get()->dnsServerPort = settings->getDNSServerPort().toInt(); 400 | // json["dnsServerPort"] = AppData::get()->dnsServerPort; 401 | // AppData::get()->httpServerPort = settings->getHTTPServerPort().toInt(); 402 | // json["httpServerPort"] = AppData::get()->httpServerPort; 403 | // html = settings->indexhtml->getHTML(); 404 | // json["html"] = html; 405 | 406 | // QJsonArray dnsarray; 407 | // foreach(const QString dns, server->realdns) 408 | // { 409 | // dnsarray.append(dns); 410 | // } 411 | // json["real_dns_servers"] = dnsarray; 412 | 413 | // QJsonArray sourcesarray; 414 | // // foreach(const ProviderSource &s, settings->sourcerAndStampConverter->providerSources) 415 | // // { 416 | // // QJsonObject subObject; 417 | // // subObject["url"] = s.url; 418 | // // if(s.hash.size() > 0) 419 | // // subObject["hash"] = s.hash.toHex().toStdString().c_str(); 420 | // // subObject["lastUpdatedTime"] = s.lastUpdated.toString(); 421 | // // sourcesarray.append(subObject); 422 | // // } 423 | // json["dnscrypt_provider_sources"] = sourcesarray; 424 | 425 | // QJsonArray whitelistarray; 426 | // foreach(const ListEntry w, server->whitelist) 427 | // { 428 | // QJsonObject subObject; 429 | // subObject["hostname"] = w.hostname; 430 | // if(w.ip != 0) //No sense wasting space in the json file for null values 431 | // subObject["ip"] = (int)w.ip; 432 | // whitelistarray.append(subObject); 433 | // } 434 | // json["whitelist"] = whitelistarray; 435 | 436 | // QJsonArray blacklistarray; 437 | // foreach(const ListEntry b, server->blacklist) 438 | // { 439 | // QJsonObject subObject; 440 | // subObject["hostname"] = b.hostname; 441 | // if(b.ip != 0) 442 | // subObject["ip"] = (int)b.ip; 443 | // blacklistarray.append(subObject); 444 | // } 445 | // json["blacklist"] = blacklistarray; 446 | 447 | // QJsonDocument jsondoc(json); 448 | // file.write(jsondoc.toJson()); 449 | // file.close(); 450 | // return true; 451 | // } 452 | 453 | // return false; 454 | } 455 | 456 | void DNSServerWindow::showInFolder(const QString& path) 457 | { 458 | QFileInfo info(path); 459 | #if defined(Q_OS_WIN) 460 | QStringList args; 461 | if (!info.isDir()) 462 | args << "/select,"; 463 | args << QDir::toNativeSeparators(path); 464 | if (QProcess::startDetached("explorer", args)) 465 | return; 466 | #elif defined(Q_OS_MAC) 467 | QStringList args; 468 | args << "-e"; 469 | args << "tell application \"Finder\""; 470 | args << "-e"; 471 | args << "activate"; 472 | args << "-e"; 473 | args << "select POSIX file \"" + path + "\""; 474 | args << "-e"; 475 | args << "end tell"; 476 | args << "-e"; 477 | args << "return"; 478 | if (!QProcess::execute("/usr/bin/osascript", args)) 479 | return; 480 | #endif 481 | QDesktopServices::openUrl(QUrl::fromLocalFile(info.isDir()? path : info.path())); 482 | } 483 | 484 | void DNSServerWindow::on_editHTMLButton_clicked() { 485 | // this editor window kind-of works, but let's just open the containing folder in the system file browser instead 486 | // TODO: re-enable this later 487 | // settings->indexhtml->show(); 488 | 489 | // open html folder 490 | showInFolder(httpServer->getIndexHTMLPath()); 491 | } 492 | 493 | void DNSServerWindow::on_aboutApp_clicked() { 494 | // open about site 495 | auto url = "https://github.com/browsedns/captivedns"; 496 | QDesktopServices::openUrl(QUrl(url)); 497 | } 498 | 499 | void DNSServerWindow::preloadServerPorts() 500 | { 501 | QFile file(settingspath); 502 | if(!file.open(QFile::ReadOnly)) 503 | return; 504 | 505 | QJsonObject json = QJsonDocument::fromJson(file.readAll()).object(); 506 | 507 | if(json.contains("dnsServerPort") && json["dnsServerPort"].isDouble()) 508 | { 509 | AppData::get()->dnsServerPort = json["dnsServerPort"].toInt(); 510 | settings->setDNSServerPort(AppData::get()->dnsServerPort); 511 | } 512 | qDebug() << "Using dns server port:" << AppData::get()->dnsServerPort; 513 | 514 | if(json.contains("httpServerPort") && json["httpServerPort"].isDouble()) 515 | { 516 | AppData::get()->httpServerPort = json["httpServerPort"].toInt(); 517 | settings->setHTTPServerPort(AppData::get()->httpServerPort); 518 | } 519 | qDebug() << "Using http server port:" << AppData::get()->httpServerPort; 520 | 521 | file.close(); 522 | } 523 | 524 | bool DNSServerWindow::settingsLoad() 525 | { 526 | // manually set YFDNS settings (can't be customized by user) 527 | 528 | // blacklist only (allow all non-captive portal domains) 529 | server->whitelistmode = false; 530 | 531 | // no settings, so no initial mode 532 | server->initialMode = false; 533 | 534 | // always return our own IP 535 | setIPToFirstListening(); 536 | 537 | settings->autoinject = true; 538 | settings->setAutoInject(true); 539 | 540 | refreshList(); 541 | 542 | // create the landing.html file if it doesn't exist 543 | httpServer->createLanding(); 544 | 545 | return true; // no settings 546 | } 547 | 548 | void DNSServerWindow::on_initialMode_stateChanged(int arg1) 549 | { 550 | if(arg1) 551 | server->initialMode = true; 552 | else 553 | server->initialMode = false; 554 | 555 | qDebug() << "initial mode:" << server->initialMode; 556 | } 557 | 558 | void DNSServerWindow::on_saveButton_clicked() 559 | { 560 | // settingsSave(); 561 | } 562 | 563 | void DNSServerWindow::on_removeButton_clicked() 564 | { 565 | // blanked out 566 | } 567 | 568 | void DNSServerWindow::on_hostnameEdit_returnPressed() 569 | { 570 | on_firstAddButton_clicked(); 571 | } 572 | 573 | void DNSServerWindow::on_ipEdit_returnPressed() 574 | { 575 | on_firstAddButton_clicked(); 576 | } 577 | 578 | void DNSServerWindow::on_secondAddButton_clicked() 579 | { 580 | bool alreadyAdded = false; 581 | // blanked out 582 | refreshList(); 583 | } 584 | void DNSServerWindow::on_settingsButton_clicked() 585 | { 586 | settings->show(); 587 | } 588 | 589 | void DNSServerWindow::on_cacheViewButton_clicked() 590 | { 591 | emit displayCache(server->cachedDNSResponses); 592 | cacheviewer->show(); 593 | } 594 | -------------------------------------------------------------------------------- /CaptiveDNS/smalldnsserver.cpp: -------------------------------------------------------------------------------- 1 | #include "smalldnsserver.h" 2 | 3 | #include 4 | #include 5 | #include "dnsserverwindow.h" 6 | #include "ui_dnsserverwindow.h" 7 | 8 | 9 | /* YourFriendlyDNS - A really awesome multi-platform (lin,win,mac,android) local caching and proxying dns server! 10 | Copyright (C) 2018 softwareengineer1 @ github.com/softwareengineer1 11 | 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, 12 | so I can keep bringing you great free and open software and continue to do so for a long time! 13 | I'm going entirely 100% free software this year in 2018 (and onwards I want to) :) 14 | Everything I make will be released under a free software license! That's my promise! 15 | If you want to contact me another way besides through github, insert your message into the blockchain with a BCH/BTC UTXO! ^_^ 16 | Thank you for your support! 17 | BCH: bitcoincash:qzh3knl0xeyrzrxm5paenewsmkm8r4t76glzxmzpqs 18 | BTC: 1279WngWQUTV56UcTvzVAnNdR3Z7qb6R8j 19 | (These are the payment methods I currently accept, 20 | if you want to support me via another cryptocurrency let me know and I'll probably start accepting that one too) 21 | 22 | This program is free software; you can redistribute it and/or modify 23 | it under the terms of the GNU General Public License as published by 24 | the Free Software Foundation; either version 2 of the License, or 25 | (at your option) any later version. 26 | 27 | This program is distributed in the hope that it will be useful, 28 | but WITHOUT ANY WARRANTY; without even the implied warranty of 29 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 30 | GNU General Public License for more details. 31 | 32 | You should have received a copy of the GNU General Public License along 33 | with this program; if not, write to the Free Software Foundation, Inc., 34 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ 35 | 36 | SmallDNSServer::SmallDNSServer(QObject *parent) 37 | { 38 | Q_UNUSED(parent); 39 | ipToRespondWith = QHostAddress("127.0.0.1").toIPv4Address(); 40 | cachedMinutesValid = 7; 41 | dnsTTL = 4200; 42 | inTimeout = 0; 43 | numSentRequests = numReceivedResponses = 0; 44 | dnscryptEnabled = false; 45 | dedicatedDNSCrypter = "sdns://AQAAAAAAAAAADjIwOC42Ny4yMjAuMjIwILc1EUAgbyJdPivYItf9aR6hwzzI1maNDL4Ev6vKQ_t5GzIuZG5zY3J5cHQtY2VydC5vcGVuZG5zLmNvbQ"; 46 | 47 | whitelistmode = initialMode = blockmode_returnlocalhost = true; 48 | sendrecvFlag = false; 49 | //default is whitelist mode, with just these three entries to get you started! 50 | whitelist.push_back(ListEntry("*startpage.com")); 51 | whitelist.push_back(ListEntry("*ixquick-proxy.com")); 52 | whitelist.push_back(ListEntry("*gbatemp.net")); 53 | whitelist.push_back(ListEntry("*github.com")); 54 | 55 | //Just in case someone switches to blacklist right away and disables initial mode without setting it up 56 | //This initial default setup should at least help avert disaster, and this demonstrates that it supports wild cards! 57 | //*.srv.nintendo.net 58 | //*.d4c.nintendo.net 59 | //*.eshop.nintendo.net 60 | //*.cdn.nintendo.net 61 | blacklist.push_back(ListEntry("*srv.nintendo.net")); 62 | blacklist.push_back(ListEntry("*d4c.nintendo.net")); 63 | blacklist.push_back(ListEntry("*eshop.nintendo.net")); 64 | blacklist.push_back(ListEntry("*cdn.nintendo.net")); 65 | blacklist.push_back(ListEntry("*.nintendo.net")); 66 | //Known captive portals (to keep them captive) 67 | blacklist.push_back(ListEntry("ctest.cdn.nintendo.net")); 68 | blacklist.push_back(ListEntry("conntest.nintendowifi.net")); 69 | blacklist.push_back(ListEntry("detectportal.firefox.com")); 70 | blacklist.push_back(ListEntry("connectivitycheck.gstatic.com")); 71 | blacklist.push_back(ListEntry("connectivitycheck.android.com")); 72 | blacklist.push_back(ListEntry("clients1.google.com")); 73 | blacklist.push_back(ListEntry("clients3.google.com")); 74 | blacklist.push_back(ListEntry("captive.apple.com")); 75 | blacklist.push_back(ListEntry("ctest.p01.ctest.srv.nintendo.net")); 76 | blacklist.push_back(ListEntry("www.msftconnecttest.com")); 77 | 78 | connect(&serversock, &QUdpSocket::readyRead, this, &SmallDNSServer::processDNSRequests); 79 | connect(&clientsock, &QUdpSocket::readyRead, this, &SmallDNSServer::processLookups); 80 | // dnscrypt = new DNSCrypt(); 81 | // if(dnscrypt) 82 | // connect(dnscrypt, &DNSCrypt::decryptedLookupDoneSendResponseNow, this, &SmallDNSServer::decryptedLookupDoneSendResponseNow); 83 | } 84 | 85 | void SmallDNSServer::displayErrorPopup(QString error) 86 | { 87 | // run code on the main thread 88 | // TODO: not working for some reason, crashes with an error about main threads still 89 | // QMetaObject::invokeMethod(this, [error]() { 90 | // QMessageBox::critical(0, "Error", error); 91 | // }); 92 | 93 | QString msg = "Error: " + error + "\n(Is another DNS server already running?)"; 94 | DNSServerWindow::mainUi->dnsStatus->setText(msg); 95 | DNSServerWindow::mainUi->dnsStatus->setStyleSheet("color: red"); 96 | 97 | } 98 | 99 | bool SmallDNSServer::startServer(QHostAddress address, quint16 port, bool reuse) 100 | { 101 | bool res = serversock.bind(address, port, reuse ? QUdpSocket::ReuseAddressHint : QUdpSocket::DefaultForPlatform); 102 | 103 | printf("SmallDNSServer::startServer() %s:%d\n", address.toString().toUtf8().data(), port); 104 | printf("SmallDNSServer::startServer() %s\n", res ? "success" : "failed"); 105 | if (!res) { 106 | printf("SmallDNSServer::startServer() %s\n", serversock.errorString().toUtf8().data()); 107 | // display qt error popup 108 | emit displayErrorPopup(serversock.errorString()); 109 | } 110 | 111 | return res; 112 | } 113 | 114 | void SmallDNSServer::clearDNSCache() 115 | { 116 | cachedDNSResponses.clear(); 117 | qDebug() << "Local DNS cache cleared!"; 118 | } 119 | 120 | void SmallDNSServer::deleteEntriesFromCache(std::vector entries) 121 | { 122 | DNSInfo cmp; 123 | size_t deletionSize = entries.size(); 124 | qDebug() << "# cached:" << cachedDNSResponses.size() << "# deleting:" << deletionSize; 125 | for(size_t x = 0; x < deletionSize; x++) 126 | { 127 | cmp.domainString = entries[x].hostname; 128 | cmp.question.qtype = entries[x].ip; 129 | 130 | std::remove(cachedDNSResponses.begin(), cachedDNSResponses.end(), cmp); 131 | } 132 | 133 | qDebug() << "Deleting..."; 134 | cachedDNSResponses.erase(cachedDNSResponses.end() - deletionSize, cachedDNSResponses.end()); 135 | } 136 | 137 | void SmallDNSServer::determineDoHDoTLSProviders() 138 | { 139 | //When using only DoH and DoTLS (v2, v3) providers, a dedicated v1 DNSCrypt provider is used to resolve their hosts, 140 | //then DoH and DoTLS providers can be used without any issue. 141 | //QSslSocket::connectToHostEncrypted only takes a hostname, and when YourFriendlyDNS is set as system dns 142 | //it uses this server to try and resolve it, which I solved by using a dedicated v1 provider when that's happening. 143 | v2and3Providers.clear(); 144 | for(QString &p : realdns) 145 | { 146 | if(p.contains("sdns://")) 147 | { 148 | // DNSCryptProvider provider(p.toUtf8()); 149 | // if(provider.protocolVersion == 2 || provider.protocolVersion == 3) 150 | // v2and3Providers.append(provider.hostname); 151 | } 152 | } 153 | } 154 | 155 | QString SmallDNSServer::selectRandomDNSServer() 156 | { 157 | bool hasDNSProviders = false; 158 | for(QString &i : realdns) 159 | { 160 | if(!i.contains("sdns://")) 161 | { 162 | hasDNSProviders = true; 163 | break; 164 | } 165 | } 166 | 167 | if(!hasDNSProviders) 168 | { 169 | realdns.append("208.67.222.222:53"); 170 | realdns.append("208.67.220.220:53"); 171 | } 172 | 173 | for(int x = 0; ; x++) 174 | { 175 | QString randomServer = realdns[QRandomGenerator::global()->bounded(realdns.size())]; 176 | 177 | if(!randomServer.contains("sdns://")) 178 | return randomServer; 179 | 180 | if(x > 100000) 181 | break; 182 | } 183 | 184 | return "208.67.222.222:53"; 185 | } 186 | 187 | QString SmallDNSServer::selectRandomDNSCryptServer() 188 | { 189 | QString oneProvider; 190 | bool hasDNSCryptProviders = false; 191 | quint32 providerCount = 0; 192 | for(QString &i : realdns) 193 | { 194 | if(i.contains("sdns://")) 195 | { 196 | oneProvider = i; 197 | hasDNSCryptProviders = true; 198 | providerCount++; 199 | } 200 | } 201 | if(!hasDNSCryptProviders) 202 | { 203 | realdns.append("sdns://AQAAAAAAAAAADjIwOC42Ny4yMjAuMjIwILc1EUAgbyJdPivYItf9aR6hwzzI1maNDL4Ev6vKQ_t5GzIuZG5zY3J5cHQtY2VydC5vcGVuZG5zLmNvbQ"); 204 | return realdns.last(); 205 | } 206 | else if(providerCount == 1) 207 | return oneProvider; 208 | 209 | for(size_t x = 0; ; x++) 210 | { 211 | QString randomServer = realdns[QRandomGenerator::global()->bounded(realdns.size())]; 212 | 213 | if(randomServer.contains("sdns://")) 214 | { 215 | qDebug() << "Selected:" << randomServer; 216 | return randomServer; 217 | } 218 | 219 | if(x > 100000) 220 | break; 221 | } 222 | return "sdns://AQAAAAAAAAAADjIwOC42Ny4yMjAuMjIwILc1EUAgbyJdPivYItf9aR6hwzzI1maNDL4Ev6vKQ_t5GzIuZG5zY3J5cHQtY2VydC5vcGVuZG5zLmNvbQ"; 223 | } 224 | 225 | bool SmallDNSServer::weDoStillHaveAConnection() 226 | { 227 | if(inTimeout == 0) 228 | { 229 | if(!sendrecvFlag && responseLastReceivedTime.secsTo(requestLastSentTime) > 30) 230 | { 231 | timeoutInferencePeriod = QDateTime::currentDateTime().addSecs(30); 232 | inTimeout = 1; 233 | } 234 | } 235 | else if(inTimeout > 0) 236 | { 237 | if(inTimeout == 1) 238 | { 239 | if(QDateTime::currentDateTime() > timeoutInferencePeriod && !sendrecvFlag && responseLastReceivedTime.secsTo(requestLastSentTime) > 60) 240 | { 241 | timeoutEnd = QDateTime::currentDateTime().addSecs(120); 242 | qDebug() << "Haven't received responses for the last 60 seconds... Let's slow down... Taking a two minute timeout."; 243 | inTimeout = 2; 244 | //Now firmly in a timeout 245 | } 246 | } 247 | if(QDateTime::currentDateTime() > timeoutEnd || sendrecvFlag) //Only unless a response comes in of one already sent while waiting it out 248 | { 249 | responseLastReceivedTime = requestLastSentTime = QDateTime::currentDateTime(); 250 | inTimeout = 0; 251 | emit deleteObjectsTheresNoResponseFor(); 252 | return true; 253 | } 254 | return false; 255 | } 256 | return true; 257 | } 258 | 259 | void SmallDNSServer::processDNSRequests() 260 | { 261 | QByteArray datagram; 262 | QHostAddress sender; 263 | quint16 senderPort; 264 | DNSInfo dns; 265 | 266 | while(serversock.hasPendingDatagrams()) 267 | { 268 | datagram.resize(serversock.pendingDatagramSize()); 269 | serversock.readDatagram(datagram.data(), datagram.size(), &sender, &senderPort); 270 | parseRequest(datagram, dns); 271 | if(!dns.isValid) continue; 272 | 273 | bool shouldCacheDomain, useDedicatedDNSCryptProviderToResolveV2And3Hosts = false; 274 | quint32 customIP = ipToRespondWith; 275 | std::string domain = (char*)dns.domainString.toUtf8().data(); 276 | ListEntry *blackListed = getListEntry(domain, TYPE_BLACKLIST); 277 | if(blackListed) 278 | { 279 | qDebug() << "Matched BlackList!" << blackListed->hostname << "to:" << dns.domainString; 280 | //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 281 | if(blackListed->ip != 0) 282 | customIP = blackListed->ip; 283 | } 284 | shouldCacheDomain = (blackListed == nullptr); 285 | 286 | if(shouldCacheDomain) 287 | { 288 | //Trying to exclude local hostnames from leaking 289 | shouldCacheDomain = (dns.domainString.contains(".") && !dns.domainString.endsWith("in-addr.arpa") && !dns.domainString.endsWith(".lan")); 290 | 291 | for(QString &provider : v2and3Providers) 292 | { 293 | if(provider == dns.domainString) 294 | { 295 | useDedicatedDNSCryptProviderToResolveV2And3Hosts = true; 296 | break; 297 | } 298 | } 299 | } 300 | 301 | //Rewritten and shortened 302 | if(!shouldCacheDomain || initialMode) 303 | { 304 | if(blockmode_returnlocalhost) 305 | { 306 | qDebug() << "Returning custom IP:" << QHostAddress(customIP).toString() << "for domain:" << dns.domainString; 307 | morphRequestIntoARecordResponse(datagram, customIP, dns.answeroffset, dnsTTL); 308 | serversock.writeDatagram(datagram, sender, senderPort); 309 | emit queryRespondedTo(ListEntry(dns.domainString, customIP)); 310 | } 311 | else 312 | emit queryRespondedTo(ListEntry(dns.domainString)); 313 | } 314 | else if(shouldCacheDomain) 315 | { 316 | DNSInfo *cached = getCachedEntry(dns.domainString, dns.question.qtype); 317 | if(cached) 318 | shouldCacheDomain = (QDateTime::currentDateTime() > cached->expiry); 319 | 320 | if(shouldCacheDomain) 321 | { 322 | if(!weDoStillHaveAConnection()) return; 323 | 324 | qDebug() << "Caching this domain->" << dns.domainString; 325 | if(cached) //If cached, update the expiry now, even though we're about to update it again in a moment 326 | cached->expiry = QDateTime::currentDateTime().addSecs(cachedMinutesValid * 60); 327 | 328 | //Here's where we forward the received request to a real dns server, if not cached yet or its time to update the cache for this domain 329 | //Only executes if the domain is whitelisted or not blacklisted (depending on which mode you're using) 330 | 331 | dns.sender = sender; 332 | dns.senderPort = senderPort; 333 | dns.ttl = dnsTTL; 334 | 335 | 336 | qDebug() << "Making DNS request type:" << dns.question.qtype << "for domain:" << dns.domainString << "request id:" << dns.header.id << "datagram:" << datagram; 337 | QString server = selectRandomDNSServer(); 338 | quint16 serverPort = DNSInfo::extractPort(server); 339 | if(serverPort == 0 || serverPort == 443) serverPort = 53; 340 | clientsock.writeDatagram(datagram, QHostAddress(server), serverPort); 341 | 342 | InitialResponse *ir = new InitialResponse(dns); 343 | if(ir) 344 | { 345 | connect(this, &SmallDNSServer::lookupDoneSendResponseNow, ir, &InitialResponse::lookupDoneSendResponseNow); 346 | connect(this, &SmallDNSServer::deleteObjectsTheresNoResponseFor, ir, &InitialResponse::deleteObjectsTheresNoResponseFor); 347 | } 348 | requestLastSentTime = QDateTime::currentDateTime(); 349 | sendrecvFlag = 0; 350 | } 351 | else if(cached) 352 | { 353 | if(dns.question.qtype == DNS_TYPE_A) 354 | { 355 | if(cached->ipaddresses.size() == 0) cached->ipaddresses.push_back(ipToRespondWith); 356 | //Let's use our cached IPs, and morph this request into a response containing them as appended dns answers 357 | morphRequestIntoARecordResponse(datagram, cached->ipaddresses, dns.answeroffset, dnsTTL); 358 | serversock.writeDatagram(datagram, sender, senderPort); 359 | emit queryRespondedTo(ListEntry(dns.domainString, cached->ipaddresses[0])); 360 | qDebug() << "Cached IPs returned! (first one):" << QHostAddress(cached->ipaddresses[0]) << "for domain:" << dns.domainString; 361 | } 362 | else 363 | { 364 | *(quint16*)cached->res.data() = *(quint16*)dns.req.data(); 365 | serversock.writeDatagram(cached->res, sender, senderPort); 366 | qDebug() << "Cached other record returned! of type:" << cached->question.qtype << "for domain:" << dns.domainString; 367 | } 368 | } 369 | } 370 | } 371 | } 372 | 373 | void SmallDNSServer::parseAndRespond(QByteArray &datagram, DNSInfo &dns) 374 | { 375 | parseResponse(datagram, dns); 376 | 377 | if(dns.isValid && dns.isResponse) 378 | { 379 | if(!dns.hasIPs && dns.question.qtype == DNS_TYPE_A) 380 | { 381 | if(dns.header.rcode == RCODE_NXDOMAIN || dns.header.rcode == RCODE_YXDOMAIN || dns.header.rcode == RCODE_XRRSET) 382 | { 383 | qDebug() << "For:" << dns.domainString << "NXDOMAIN (Non eXistent domain) or similar response code received, redirecting immediately to custom ip!"; 384 | dns.ipaddresses.push_back(ipToRespondWith); 385 | dns.hasIPs = true; 386 | emit lookupDoneSendResponseNow(dns, &serversock); 387 | } 388 | } 389 | else 390 | { 391 | emit lookupDoneSendResponseNow(dns, &serversock); 392 | } 393 | 394 | DNSInfo *cached = getCachedEntry(dns.domainString, dns.question.qtype); 395 | if(cached) 396 | { 397 | //Update the cached entry 398 | dns.expiry = QDateTime::currentDateTime().addSecs(cachedMinutesValid * 60); 399 | *cached = dns; 400 | qDebug() << "Updated cache of record type:" << dns.question.qtype << "for domain:" << dns.domainString << "with new expiry:" << dns.expiry; 401 | } 402 | else 403 | { 404 | //Or create the cache entry initially 405 | dns.expiry = QDateTime::currentDateTime().addSecs(cachedMinutesValid * 60); 406 | cachedDNSResponses.push_back(dns); 407 | } 408 | 409 | if(dns.hasIPs && dns.question.qtype == DNS_TYPE_A) 410 | emit queryRespondedTo(ListEntry(dns.domainString, dns.ipaddresses[0])); 411 | } 412 | responseLastReceivedTime = QDateTime::currentDateTime(); 413 | sendrecvFlag = 1; 414 | } 415 | 416 | void SmallDNSServer::decryptedLookupDoneSendResponseNow(QByteArray decryptedResponse, DNSInfo &dns) 417 | { 418 | parseAndRespond(decryptedResponse, dns); 419 | } 420 | 421 | void SmallDNSServer::processLookups() 422 | { 423 | QByteArray datagram; 424 | QHostAddress sender; 425 | quint16 senderPort; 426 | DNSInfo dns; 427 | 428 | while(clientsock.hasPendingDatagrams()) 429 | { 430 | datagram.resize(clientsock.pendingDatagramSize()); 431 | clientsock.readDatagram(datagram.data(), datagram.size(), &sender, &senderPort); 432 | parseAndRespond(datagram, dns); 433 | } 434 | } 435 | 436 | ListEntry* SmallDNSServer::getListEntry(const std::string &tame, int listType) 437 | { 438 | if(listType == TYPE_WHITELIST) 439 | { 440 | for(ListEntry &whiteListed : whitelist) 441 | { 442 | std::string wild = whiteListed.hostname.toUtf8().data(); 443 | if(GeneralTextCompare((char*)tame.c_str(), (char*)wild.c_str())) 444 | { 445 | return &whiteListed; 446 | } 447 | } 448 | } 449 | else if(listType == TYPE_BLACKLIST) 450 | { 451 | for(ListEntry &blackListed : blacklist) 452 | { 453 | std::string wild = blackListed.hostname.toUtf8().data(); 454 | if(GeneralTextCompare((char*)tame.c_str(), (char*)wild.c_str())) 455 | { 456 | return &blackListed; 457 | } 458 | } 459 | } 460 | return nullptr; 461 | } 462 | 463 | DNSInfo* SmallDNSServer::getCachedEntry(const QString &byDomain, quint16 andType) 464 | { 465 | size_t cachedSize = cachedDNSResponses.size(); 466 | for(size_t i = 0; i < cachedSize; i++) 467 | { 468 | DNSInfo *pDNS = &cachedDNSResponses[i]; 469 | 470 | if(pDNS->domainString == byDomain && pDNS->question.qtype == andType) 471 | return pDNS; 472 | } 473 | 474 | return nullptr; 475 | } 476 | 477 | bool SmallDNSServer::interpretHeader(const QByteArray &dnsmessage, DNSInfo &dns) 478 | { 479 | if(dnsmessage.size() >= DNS_HEADER_SIZE) 480 | { 481 | memcpy(&dns.header, dnsmessage.data(), DNS_HEADER_SIZE); 482 | //correcting values because of network byte order... 483 | dns.header.id = qFromBigEndian(dns.header.id); 484 | dns.header.q_count = qFromBigEndian(dns.header.q_count); 485 | dns.header.ans_count = qFromBigEndian(dns.header.ans_count); 486 | dns.header.auth_count = qFromBigEndian(dns.header.auth_count); 487 | dns.header.add_count = qFromBigEndian(dns.header.add_count); 488 | 489 | dns.isResponse = dns.header.QUERY_RESPONSE_FLAG; 490 | dns.isValid = true; 491 | } 492 | else 493 | dns.isValid = false; 494 | 495 | return dns.isValid; 496 | } 497 | 498 | void SmallDNSServer::parseRequest(const QByteArray &dnsrequest, DNSInfo &dns) 499 | { 500 | if(!interpretHeader(dnsrequest, dns)) 501 | return; 502 | 503 | if(dns.header.QUERY_RESPONSE_FLAG != 0) 504 | { 505 | dns.isValid = false; 506 | return; 507 | } 508 | 509 | dns.req = dnsrequest; 510 | getDomainString(dnsrequest, dns); 511 | 512 | //qDebug() << "for:" << dns.domainString << "parsed request header id:" << dns.header.id << "qcount:" << dns.header.q_count << "answer count:" << dns.header.ans_count 513 | // << "auth count:" << dns.header.auth_count << "add count:" << dns.header.add_count; 514 | } 515 | 516 | void SmallDNSServer::parseResponse(const QByteArray &dnsresponse, DNSInfo &dns) 517 | { 518 | if(!interpretHeader(dnsresponse, dns)) 519 | return; 520 | 521 | if(dns.header.QUERY_RESPONSE_FLAG != 1) 522 | { 523 | dns.isValid = false; 524 | return; 525 | } 526 | 527 | dns.res = dnsresponse; 528 | getDomainString(dnsresponse, dns); 529 | getHostAddresses(dnsresponse, dns); 530 | 531 | //qDebug() << "for:" << dns.domainString << "parsed response header id:" << dns.header.id << "qcount:" << dns.header.q_count << "answer count:" << dns.header.ans_count 532 | // << "auth count:" << dns.header.auth_count << "add count:" << dns.header.add_count << "whole response:" << dns.res; 533 | } 534 | 535 | QString SmallDNSServer::getDomainString(const QByteArray &dnsmessage, DNSInfo &dns) 536 | { 537 | QString fullname; 538 | const char *ptr = &dnsmessage.data()[DNS_HEADER_SIZE], *ptr_origin = &dnsmessage.data()[0]; 539 | const char *ptr_end = &dnsmessage.data()[dnsmessage.size()]; 540 | quint8 len; 541 | char partialname[64]; 542 | do 543 | { 544 | len = *ptr++; 545 | if(len == 0) break; 546 | if(len > 63 || (ptr + len) >= ptr_end) { dns.isValid = false; return fullname; } 547 | memcpy(partialname, ptr, len); 548 | partialname[len] = 0; 549 | fullname += partialname; 550 | 551 | ptr += len; 552 | if(*ptr != 0) fullname += "."; 553 | } 554 | while(len != 0); 555 | 556 | dns.domainString = fullname.toLower(); 557 | 558 | if(ptr < ptr_end) 559 | dns.question.qtype = qFromBigEndian(*(quint16*)ptr); 560 | ptr += 2; 561 | if(ptr < ptr_end) 562 | dns.question.qclass = qFromBigEndian(*(quint16*)ptr); 563 | ptr += 2; 564 | 565 | dns.answeroffset = (ptr - ptr_origin); 566 | 567 | //qDebug() << "got domain name string:" << fullname 568 | // << "qtype:" << dns.question.qtype << "qclass:" << dns.question.qclass 569 | // << "isresponse:" << dns.isResponse << "answer offset:" << dns.answeroffset; 570 | 571 | return fullname; 572 | } 573 | 574 | void SmallDNSServer::getHostAddresses(const QByteArray &dnsresponse, DNSInfo &dns) 575 | { 576 | dns.hasIPs = false; 577 | if(!dns.isResponse || dns.question.qtype != DNS_TYPE_A) return; //if not a response and containing an A record, then there's no IPs here to grab... 578 | 579 | ANSWER answer; 580 | const char *ptr = &dnsresponse.data()[dns.answeroffset]; 581 | const char *ptr_end = &dnsresponse.data()[dnsresponse.size()]; 582 | 583 | for(quint16 i = 0; i < dns.header.ans_count; i++) 584 | { 585 | if((ptr + DNS_HEADER_SIZE) >= ptr_end) 586 | break; 587 | 588 | answer.name = qFromBigEndian(*(quint16*)ptr); 589 | ptr += 2; 590 | answer.type = qFromBigEndian(*(quint16*)ptr); 591 | ptr += 2; 592 | answer.rclass = qFromBigEndian(*(quint16*)ptr); 593 | ptr += 2; 594 | answer.ttl = qFromBigEndian(*(quint32*)ptr); 595 | ptr += 4; 596 | answer.rdlength = qFromBigEndian(*(quint16*)ptr); 597 | ptr += 2; 598 | 599 | //qDebug() << "Interpreted answer name:" << answer.name << "type:" << answer.type << "rclass:" << answer.rclass << "ttl:" << answer.ttl << "rdlength:" << answer.rdlength; 600 | 601 | quint32 ip; 602 | if(answer.type == DNS_TYPE_A && answer.rdlength == 4) //if it's an A record which should be 4 bytes 603 | { 604 | memcpy(&ip, ptr, 4); 605 | ip = qFromBigEndian(ip); 606 | 607 | qDebug() << "Got IP:" << QHostAddress(ip).toString() << "for domain:" << dns.domainString; 608 | dns.ipaddresses.push_back(ip); 609 | dns.hasIPs = true; 610 | } 611 | 612 | if((ptr + answer.rdlength) < ptr_end) 613 | ptr += answer.rdlength; 614 | else 615 | break; 616 | } 617 | } 618 | 619 | //Thanks Kirk! 620 | /*By Kirk J. Krauss, August 26, 2008 621 | A simple wildcard text-matching algorithm in a single while loop */ 622 | 623 | //This function compares text strings, one of which can have wildcards ('*'). 624 | bool GeneralTextCompare( 625 | char * pTameText, // A string without wildcards 626 | char * pWildText, // A (potentially) corresponding string with wildcards 627 | bool bCaseSensitive, // By default, match on 'X' vs 'x' 628 | char cAltTerminator // For function names, for example, you can stop at the first '(' 629 | ) 630 | { 631 | bool bMatch = true; 632 | char * pAfterLastWild = 0; // The location after the last '*', if we’ve encountered one 633 | char * pAfterLastTame = 0; // The location in the tame string, from which we started after last wildcard 634 | char t, w; 635 | 636 | // Walk the text strings one character at a time. 637 | for(;;) 638 | { 639 | t = *pTameText; 640 | w = *pWildText; 641 | 642 | //qDebug() << "tame:" << t << "wild:" << w; 643 | 644 | // How do you match a unique text string? 645 | if (!t || t == cAltTerminator) 646 | { 647 | // Easy: unique up on it! 648 | if (!w || w == cAltTerminator) 649 | { 650 | break; // "x" matches "x" 651 | } 652 | else if (w == '*') 653 | { 654 | pWildText++; 655 | continue; // "x*" matches "x" or "xy" 656 | } 657 | else if (pAfterLastTame) 658 | { 659 | if (!(*pAfterLastTame) || *pAfterLastTame == cAltTerminator) 660 | { 661 | bMatch = false; 662 | break; 663 | } 664 | pTameText = pAfterLastTame++; 665 | pWildText = pAfterLastWild; 666 | continue; 667 | } 668 | 669 | bMatch = false; 670 | break; // "x" doesn't match "xy" 671 | } 672 | else 673 | { 674 | if (!bCaseSensitive) 675 | { 676 | // Lowercase the characters to be compared. 677 | if (t >= 'A' && t <= 'Z') 678 | { 679 | t += ('a' - 'A'); 680 | } 681 | 682 | if (w >= 'A' && w <= 'Z') 683 | { 684 | w += ('a' - 'A'); 685 | } 686 | } 687 | 688 | // How do you match a tame text string? 689 | if (t != w) 690 | { 691 | // The tame way: unique up on it! 692 | if (w == '*') 693 | { 694 | pAfterLastWild = ++pWildText; 695 | pAfterLastTame = pTameText; 696 | w = *pWildText; 697 | 698 | if (!w || w == cAltTerminator) 699 | { 700 | break; // "*" matches "x" 701 | } 702 | continue; // "*y" matches "xy" 703 | } 704 | else if (pAfterLastWild) 705 | { 706 | if (pAfterLastWild != pWildText) 707 | { 708 | pWildText = pAfterLastWild; 709 | w = *pWildText; 710 | 711 | if (!bCaseSensitive && w >= 'A' && w <= 'Z') 712 | { 713 | w += ('a' - 'A'); 714 | } 715 | 716 | if (t == w) 717 | { 718 | pWildText++; 719 | } 720 | } 721 | 722 | pTameText++; 723 | continue; // "*sip*" matches "mississippi" 724 | } 725 | else 726 | { 727 | bMatch = false; 728 | break; // "x" doesn't match "y" 729 | } 730 | } 731 | } 732 | 733 | pTameText++; 734 | pWildText++; 735 | //qDebug() << "t:" << pTameText << "w:" << pWildText; 736 | } 737 | 738 | return bMatch; 739 | } 740 | --------------------------------------------------------------------------------