From a61578a02e584082ebd375b043c699255cda196c Mon Sep 17 00:00:00 2001 From: James Coleman Date: Sun, 22 May 2016 16:14:17 -0500 Subject: [PATCH] First commit --- License.txt | 12 +++ databases/main.db | Bin 0 -> 3072 bytes dbSQLITE.php | 108 ++++++++++++++++++++++++++ index.php | 192 ++++++++++++++++++++++++++++++++++++++++++++++ readme.md | 85 ++++++++++++++++++++ updateGeckoDNS.sh | 23 ++++++ 6 files changed, 420 insertions(+) create mode 100755 License.txt create mode 100644 databases/main.db create mode 100644 dbSQLITE.php create mode 100644 index.php create mode 100644 readme.md create mode 100644 updateGeckoDNS.sh diff --git a/License.txt b/License.txt new file mode 100755 index 0000000..5108a4c --- /dev/null +++ b/License.txt @@ -0,0 +1,12 @@ +Copyright (c) 2016, Mr. Gecko's Media (James Coleman) +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/databases/main.db b/databases/main.db new file mode 100644 index 0000000000000000000000000000000000000000..821983ca231546d65c978bbdfc2b2658d8c916c4 GIT binary patch literal 3072 zcmWFz^vNtqRY=P(%1ta$FlJz3U}R))P*7lCV9*3&W*~+EejtMd#sSidNNik8O$Oa( zT)fPG7?_wgFfeUkzKBcVsQ73I5EBATa*XWa;^K@g(j|#WIjN<^sYS(Lg2_3^)iK0X zA;i(i$5lZIET*KO!Nmz-=OyN*Dk+4xMuaH%`2%sNkB<&Wt{}0vxIDio1tJF)%1JFt z%~4YD^b2tfa(4{^ivg`EOD#fDl$~0M#H-5BgPIOjosnN$Qj8>>lUQ6*W`ZtYh9*#2 zkdjyeGzP_Dkk;JP;^M?~RGEMvPhZENNCj`#NDZ)O!5-A)($r*P6Soy-WXQ}*Nv$X@ z%mL=^_{7qZd@w&A94zsMU<#DCS$IK#j-0EBiG)!#qaiRF0>dH%xIn%b&Huw9E=N5v J8Umz-004wmX-NP8 literal 0 HcmV?d00001 diff --git a/dbSQLITE.php b/dbSQLITE.php new file mode 100644 index 0000000..9f832e4 --- /dev/null +++ b/dbSQLITE.php @@ -0,0 +1,108 @@ +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + if ($_MGM['DBPersistent']) + $_MGM['DBConnection']->setAttribute(PDO::ATTR_PERSISTENT, TRUE); + if ($_MGM['DBConnection']==NULL) error("Database Connection Failed"); +} +function closeDatabase() { + global $_MGM; + if (isset($_MGM['DBConnection'])) { + $_MGM['DBConnection'] = NULL; + } +} +function escapeString($theString) { + global $_MGM; + return $_MGM['DBConnection']->quote($theString); +} +function quoteObject($theObject) { + global $_MGM; + if (is_null($theObject)) { + return "NULL"; + } else if (is_string($theObject)) { + return escapeString($theObject); + } else if (is_float($theObject) || is_integer($theObject)) { + return $theObject; + } else if (is_bool($theObject)) { + return ($theObject ? 1 : 0); + } + return "NULL"; +} +function databaseQuery($format) { + global $_MGM; + $result = NULL; + try { + if (isset($_MGM['DBConnection'])) { + $args = func_get_args(); + array_shift($args); + $args = array_map("quoteObject", $args); + $query = vsprintf($format, $args); + + $result = $_MGM['DBConnection']->query($query); + } + //if ($result==NULL) error("Failed to run query on database"); + } catch (Exception $e) { + //echo $e->getMessage()."
\n"; + //error("Failed to run query on database"); + } + return $result; +} +function databaseRowCount($theResult) { + global $_MGM; + if ($theResult==NULL) + return 0; + return $theResult->rowCount(); +} +function databaseFieldCount($theResult) { + global $_MGM; + if ($theResult==NULL) + return 0; + return $theResult->columnCount(); +} +function databaseLastID() { + global $_MGM; + $result = 0; + if (isset($_MGM['DBConnection'])) { + $result = $_MGM['DBConnection']->lastInsertId(); + } + return $result; +} +function databaseFetch($theResult) { + global $_MGM; + return $theResult->fetch(); +} +function databaseFetchNum($theResult) { + global $_MGM; + return $theResult->fetch(PDO::FETCH_NUM); +} +function databaseFetchAssoc($theResult) { + global $_MGM; + return $theResult->fetch(PDO::FETCH_ASSOC); +} +function databaseResultSeek($theResult, $theLocation) { + global $_MGM; + return false; +} +function databaseFreeResult($theResult) { + global $_MGM; + $theResult = NULL; +} +?> diff --git a/index.php b/index.php new file mode 100644 index 0000000..f02a9d8 --- /dev/null +++ b/index.php @@ -0,0 +1,192 @@ + + + + Generate password for storage in <?=$_MGM['title']?> database. + + +
+ + +
+ + &1", $output); + + if ($_MGM['debug']) { + echo "Output: \n"; + } + $foundReply = false; + $status = 0; + foreach ($output as $line) { + if ($_MGM['debug']) { + echo $line."\n"; + } + + if ($foundReply && $status==0) { + if (strpos($line, "status: NOERROR")!==false) { + $status = 1; + } else { + $status = 2; + } + } + if (strpos($line, "Reply from update query:")!==false) { + $foundReply = true; + } + } + + if ($status==1) { + echo "\nUpdate Successful"; + databaseQuery("UPDATE users SET lastupdate=%s, $dblast=%s WHERE username=%s", $_MGM['time'], $_MGM['ip'], $_MGM['user']['username']); + } else { + if ($_MGM['debug']) { + echo "\nCommand: ".$command."\n"; + echo "\nUpdate File:\n"; + readfile($updateFile); + } + echo "\nUpdate Unsuccessful"; + } + unlink($updateFile); +} else { + echo "No Update"; +} + +closeDatabase(); +?> \ No newline at end of file diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..658c5a0 --- /dev/null +++ b/readme.md @@ -0,0 +1,85 @@ +#GeckoDNS + +I needed a Dynamic DNS service of my own, so I wrote a quick one. This uses nsupdate with keys to update DNS records with current IP addresses. It uses simple username and password authentication over http. If you want security, you should run updates over TLS. The backend authenticates updates with the DNS server via TSGN signing. + +##Instructions + +###Modify `index.php` to your liking by making sure values are set right. +Mainly verify nsupdatePath is correct. + +###Configure Bind9 to allow updating for the zone you need Dynamic DNS for. + +Change directory to the location where your named.conf is located. + +Generate a key for updating. +``` +# dnssec-keygen -r /dev/urandom -a HMAC-MD5 -b 512 -n HOST example.com +Kexample.com.+157+42278 +``` + +Read the file outputted in a text editor and copy the key value. +``` +# cat Kexample.com.+157+42278.private +Private-key-format: v1.3 +Algorithm: 157 (HMAC_MD5) +Key: pbrxTbsWVoE8ys0529iKpLUHQzH389rmx39yxvsgvltVABGzR4hyHzycJnlFVMuBpPJI8qO8awma5PCEfDgu/Q== +Bits: AAA= +Created: 20160522202756 +Publish: 20160522202756 +Activate: 20160522202756 +``` + +Place the key in a new file in the following format. +``` +# nano example.com.key +key "example.com." { + algorithm hmac-md5; + secret "pbrxTbsWVoE8ys0529iKpLUHQzH389rmx39yxvsgvltVABGzR4hyHzycJnlFVMuBpPJI8qO8awma5PCEfDgu/Q=="; +}; +``` + +Edit named.conf and add the following: +``` +# nano named.conf +include "example.com.key"; + +zone "example.com" { + type master; + file "/var/named/example.com.hosts"; + allow-update { key "example.com."; }; +}; +``` + +The important part is `allow-update { key "example.com."; };` which allows anything which signs a message with that key to update the zone. + +###Upload GeckoDNS to a web server which has access to running nsupdate. + +###Add your zone key file in the `keys` folder of GeckoDNS. + +###Visit https://website.com/GeckoDNS/?passwd to generate a hash of your password for updating dns. + +###Create user account with details. +``` +# sqlite3 databases/main.db +sqlite> INSERT INTO "users" VALUES('username','7589bc703af770d39785d714c1e32ec49145031885a8ac4a2e5f5001b9f2ec85ef274fd962e88ab0d85ff55aae90bb3be873c347eb75a1099c051d04569574fac24dbb071da6b7868182f0715885145f',1,'127.0.0.1','example.com.key','example.com.','example.com.,subdomain.example.com.',NULL,NULL,NULL,NULL); +``` + +###Configure nginx (or apache) to block access to private folders. +Nginx config, I'm not writing Apache config. Sorry. +``` +location ~* /GeckoDNS/(databases|keys) { + deny all; +} +``` + +###Copy and configure cron `updateGeckoDNS.sh` to have proper username/password/update urls on computer you want to update the DNS. + +###Configure cronjob on the computer you want to update the DNS. + +``` +# crontab -e +*/30 * * * * /bin/bash /usr/local/bin/updateGeckoDNS.sh >/dev/null 2>&1 +``` + +##Final words +I do not know if I would ever update this from this point, however there are some things in place so I can add on to the system. Maybe in the future it will be designed more of a service than a personal Dynamic DNS system. A good thing to change would be to separate zones from users to allow multiple zones per account and custom TTL per host. \ No newline at end of file diff --git a/updateGeckoDNS.sh b/updateGeckoDNS.sh new file mode 100644 index 0000000..471a786 --- /dev/null +++ b/updateGeckoDNS.sh @@ -0,0 +1,23 @@ +#/bin/bash + +#Username and password. +username="username" +password="password" + +#The ipv4 subdomain needs to be created if you have both IPv6 and IPv4 on the website. +#The subdomain isn't a requirement. +#You can do https://website.com/GeckoDNS/ if you don't have the subdomain made. +ipv4update="https://ipv4.website.com/GeckoDNS/" + +#Lave blank if you do not do IPv6. +ipv6update="https://ipv6.website.com/GeckoDNS/" + +if [ ! -z "$ipv4update" ]; then + curl -4 "$ipv4update?username=$username&password=$password" + echo "" +fi + +if [ ! -z "$ipv6update" ]; then + curl -6 "$ipv6update?username=$username&password=$password" + echo "" +fi \ No newline at end of file