iceycode
10/21/2017 - 2:38 PM

Network Administration - Useful Scripts & Configurations

Some configuration scripts meant for open-source routers running on LEDE (should also work on OpenWRT), as well as scripts to run on clients

#### If upgrading an already installed LEDE firmware, then configurations will be saved

# SSH/Telnet into the recently updated router
# Using Putty or ideally a program that has SSH2
ssh root@{ip_address} P@55w0rd1 # or leave out password if none

# If no password, set one using
passwd # will be prompted to enter password 2x



################### Automating Package Updates
# Can be done 1 of 3 ways (see link under references for more info)
# Setup user profile, which will act to automate updating packages
###### Create an update script
nano ~/.profile

<# Options
    1. crontab -e # add script to LuCI --> System --> Scheduled Tasks
    2. Startup script on SSH 
--> 3. Add to same profile initialized before, will slow SSH since runs on connection
#>

### 1. Scheduled Tasks
crontab -e # add below lines
1 0 * * 0 /bin/opkg update # Update list of available packages every Sunday 00:01
# crontab and fstab must end with the last line a space or comment

### 3. See profile file: LEDE_update-on-ssh-profile.sh

###### Update using one command
### CAVEATS: Please be warned that package upgrades are processed without order.
opkg update
eval $(opkg list_installed | sed 's/ - .*//' | sed 's/^/opkg upgrade /')

####### Automating packaging
## IMPORTANT: when updating the the firmeware, LEDE will not autosave
## To enable autosave on firmware update, add it to custom files to save:
echo  '/root/.profile #my profile with update script '  >> /etc/sysupgrade.conf

########## Recommmended Post-Installation Steps
/# opkg install diffutils
### locate all -opkg files
/# find /etc -name *-opkg
### compare old customized /etc/config/snmpd with new generic file /etc/config/snmpd-opkg
/# diff /etc/config/snmpd /etc/config/snmpd-opkg
### merge in any needed changes to the active version of the configuration file
root@lede:/# vi /etc/config/snmpd
### if the new version provided by the package maintainer should replace the old config file then just swap it in
/# mv /etc/config/snmpd-opkg /etc/config/snmpd 
### clean up by removing the package manager-version of the configuration file
/# rm /etc/config/snmpd-opkg
### Some user-installed packages need to be enabled and started, for example to start snmpd:
/# /etc/init.d/snmpd enable && /etc/init.d/snmpd start
### Perform a manual reboot after your post-upgrade steps. It is a good idea to do a device reboot and ensure all expected functionality is working as before.
reboot


################# UPGRADING LEDE FIRMWARE ###############################
## NOTE: only do after installing a "factory" image first
## After initial install, updating the LEDE firmware of router via commandline

###### METHOD 1: GUI
##  It is easier & safer (for those less familiar w/ LEDE/OpenWRT) to use GUI if possible
##    If using GUI, go to: LuCI --> System --> Update firmware


###### METHOD 2: Command line
#    1. Download the desired upgrade file to your LEDE's /tmp directory, which is stored in the device RAM:
#    2. Check free memory is available: Run free. Proceed, if “free Mem” is the size of your firmware file + some extra mem (at least twice the size of your firmware file is perfect).
#    3. Set the following variables to the download address of your LEDE firmware file (you must customize the URL!)
#    4. Check to see if checksums are valid, if not DO NOT PROCEED & download firmware again.

# set download link & checksums variables
DOWNLOAD_LINK="http://URLOFFIRMWAREBIN"; SHA256SUMS="lhttp://URLOFSHA256"
# Download and check the firmware checksum with:
cd /tmp;wget $DOWNLOAD_LINK;wget $SHA256SUMS;sha256sum -c sha256sums 2>/dev/null|grep OK

# Run "free"
free
# only proceed if "free Mem" is at least 2x size of firmware
# if not enough RAM, free up...
/# rm -r /tmp/opkg-lists/ # package index
/# sync && echo 3 > /proc/sys/vm/drop_caches # drops caches


# In the screen output, look for the correct checksum verification:
FILE_NAME: OK  #  Only proceed if this shows

# To install the downloaded firemware



function random-mac {   
    $mac = "02"
    while ($mac.length -lt 12) 
	{ 
		$mac += "{0:X}" -f $(get-random -min 0 -max 16) 
	} 
		
    $Delimiter = "-"
		for ($i = 0 ; $i -le 10 ; $i += 2) 
		{ $newmac += $mac.substring($i,2) + $Delimiter }
		$setmac = $newmac.substring(0,$($newmac.length - $Delimiter.length)) 
 $setmac
}


function disconnect-wifi { 
    $CurrentSSID = (& netsh wlan show profiles | Select-String 'Current User Profile' | Foreach-Object {$_.ToString()}).replace("    Current User Profile : ","$null")
    Write-Host "Current WLAN SSID: $CurrentSSID"  -ForegroundColor Yellow

    $WIFI = Get-WmiObject -Class Win32_NetworkAdapterConfiguration | Where { $_.IpEnabled -eq $true -and $_.DhcpEnabled -eq $true}
    Write-Host "Releasing IP addresses:" ($WIFI.IPAddress | select -first 1)  -ForegroundColor Yellow 
    $WIFI.ReleaseDHCPLease() | out-Null 

    # Make sure the Release have happened, else it give it 2 sec extra. 
    $WIFI = Get-WmiObject -Class Win32_NetworkAdapterConfiguration | Where { $_.IpEnabled -eq $true -and $_.DhcpEnabled -eq $true} 
    if ($WIFI.DefaultIPGateway -ne $Null) { 
    Write-Output "Release of IP Address had not completed, waiting 1 Seconds" 
    sleep -Seconds 2
    }

    Write-Host "Disconnecting from WiFi" -ForegroundColor Yellow 
    & netsh wlan disconnect | Out-Null
} 


function new-wifimac ($wifiadapter, $ssid, $newmac){ 

    Write-Output "Wifi AdapterName: $wifiadapter" 
    Write-Output "SSID: $ssid" 
    Write-Output "New MAC Address to set: $($newmac)" 

    $oldmac = (Get-NetAdapter -Name $wifiadapter).MACAddress 
    Write-Output "OLD MAC Address: $oldmac" 

    if ($oldmac -like $newmac) {
        Write-Host "Old MAC and New MAC are identical, generating a new MAC Address" -ForegroundColor Red
        $newmac = random-mac
        Write-Output "New MAC Address to set: $newmac" 
        }

    Get-NetAdapter -Name $wifiadapter | Set-NetAdapter -MACAddress $newmac -Confirm:$false
    Get-NetAdapter -Name $wifiadapter | Disable-NetAdapter -Confirm:$false
    Get-NetAdapter -Name $wifiadapter | Enable-NetAdapter -Confirm:$false
    $currentmac = (Get-NetAdapter -Name $wifiadapter).MACAddress 
    Write-Output "NEW MAC Address: $currentmac" 

    Write-Host "Connecting to SSID: $ssid" -ForegroundColor Yellow 
    & netsh wlan connect name=$ssid ssid=$ssid

    $NoIP = 0
    Do { 
        $WIFI = Get-WmiObject -Class Win32_NetworkAdapterConfiguration | Where { $_.IpEnabled -eq $true -and $_.DhcpEnabled -eq $true}
        
        if ($WIFI.DefaultIPGateway -ne $null) { 
            $NoIP = 5
        }
        else {
            sleep -Seconds 2 
            Write-Host "Waiting for IP Address" 
            $NoIP += 1
        }
    } While ($NoIP -lt 5) 
    Write-Host "New IP addresses" ($WIFI.IPAddress | select -first 1)  -ForegroundColor Yellow 
}



function dns_fix($logFile){
    Invoke-Command -ScriptBlock {
        
    }    
}


function test-wifi ($probe){ 
    if (Test-NetConnection -ComputerName $probe -CommonTCPPort HTTP -InformationLevel Quiet) { 
        $result = "Working" 
    } 
    else { 
        $result = "NotWorking" 
    }
$result 
}


# Specify $SSID manually 
# $ssid = 'SSID-to-Connect-to' 
# 
# Or use the currently used SSID to reconnect to. 
$ssid = (& netsh wlan show interfaces | Select-String ' SSID ' | Foreach-Object {$_.ToString()}).replace("    SSID                   : ","$null")

# Specify WLAN Adapter Name Manually 
# $wifiadapter = 'vEthernet (External Wi-Fi)'
# 
# Or Try to identify the Wi-Fi Adapter 
$wifiadapter = (Get-NetAdapter | where Status -EQ "Up" | where MediaType -EQ "802.3" | where MacAddress -EQ (Get-WmiObject -Class Win32_NetworkAdapterConfiguration | Where { $_.IpEnabled -eq $true -and $_.DhcpEnabled -eq $true} | select *).MACAddress.replace(":","-")).Name

# Specify a MAC Address manually
# $newmac = "02-F4-D7-B2-FE-D8"
#
# Or generate a new Random MAC Address
$newmac = random-mac

disconnect-wifi
new-wifimac -wifiadapter $wifiadapter -ssid $ssid -newmac $newmac 
test-wifi -probe www.msftncsi.com

#!/bin/sh

set -e

if [[ $# -ne 3 ]] ; then
   echo "Usage: $0 </dev/disk> <ssid> <passphase>"
   exit 1
fi

DISK="$1"
SSID="$2"
PASS="$3"

if [[ ! -b "${DISK}" ]] ; then
   echo "Not a block device: ${DISK}"
   exit 1
fi

if [[ "${USER}" != "root" ]] ; then
   echo "Must run as root."
   exit 1
fi

echo Mounting
mkdir root
mount "${DISK}2" root

cat << EOF >> root/etc/systemd/network/wlan0.network
[Match]
Name=wlan0

[Network]
DHCP=yes
EOF

wpa_passphrase "${SSID}" "${PASS}" > root/etc/wpa_supplicant/wpa_supplicant-wlan0.conf

ln -s \
   /usr/lib/systemd/system/wpa_supplicant@.service \
   root/etc/systemd/system/multi-user.target.wants/wpa_supplicant@wlan0.service

echo Unmounting
umount root

echo Cleaning up
rmdir root
# Cron example for datasky.ftp.sh - will update on 5 minute intervals.
# Works for mac, linux (or any OS with a cron scheduler)

# If you're not familiar with the cron scheduler, you can search for "install a cron", cron is the standard scheduler available on most non-windows systems, mac's, routers, NAS boxes and so on
# Using IPv4 transport

# Test on the console using ..:
# curl http://sync.afraid.org/u/8XFYnYnVMPrHt4LKiF1VtP7X/

# To install into cron, on the console enter: crontab -e
# Then paste in the 2 lines at the bottom of this page, then save
# You can check the "/tmp/freedns_datasky_ftp_sh.log" file on your system to verify its happening each 5 minutes
#_______________________PASTE BELOW 2 LINES______________________________
$ACCOUNT_URL_TO_UPDATE = "" # !!!!!! CHANGE THIS BEFORE ADDING TO ROUTER
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin
0,5,10,15,20,25,30,35,40,45,50,55 * * * * sleep 32 ; curl -s http://sync.afraid.org/u/8XFYnYnVMPrHt4LKiF1VtP7X/ >> /tmp/freedns_{{$ACCOUNT_URL_TO_UPDATE}}.log 2>/dev/null
## Authoritative, validating, recursive caching DNS
## unbound.conf -- https://calomel.org
#
server:
  # log verbosity
    verbosity: 1

  # specify the interfaces to answer queries from by ip-address.  The default
  # is to listen to localhost (127.0.0.1 and ::1).  specify 0.0.0.0 and ::0 to
  # bind to all available interfaces.  specify every interface[@port] on a new
  # 'interface:' labeled line.  The listen interfaces are not changed on
  # reload, only on restart.
    interface: 127.0.0.1

  # port to answer queries from
    port: 53

  # Enable IPv4, "yes" or "no".
    do-ip4: yes

  # Enable IPv6, "yes" or "no".
    do-ip6: no

  # Enable UDP, "yes" or "no".
    do-udp: yes

  # Enable TCP, "yes" or "no". If TCP is not needed, Unbound is actually
  # quicker to resolve as the functions related to TCP checks are not done.i
  # NOTE: you may need tcp enabled to get the DNSSEC results from *.edu domains
  # due to their size.
    do-tcp: yes

  # control which client ips are allowed to make (recursive) queries to this
  # server. Specify classless netblocks with /size and action.  By default
  # everything is refused, except for localhost.  Choose deny (drop message),
  # refuse (polite error reply), allow (recursive ok), allow_snoop (recursive
  # and nonrecursive ok)
    access-control: 10.0.0.0/8 allow
    access-control: 127.0.0.0/8 allow
    access-control: 192.168.0.0/16 allow

  # Read  the  root  hints from this file. Default is nothing, using built in
  # hints for the IN class. The file has the format of  zone files,  with  root
  # nameserver  names  and  addresses  only. The default may become outdated,
  # when servers change,  therefore  it is good practice to use a root-hints
  # file.  get one from ftp://FTP.INTERNIC.NET/domain/named.cache
    root-hints: "/var/unbound/etc/root.hints"

  # enable to not answer id.server and hostname.bind queries.
    hide-identity: yes

  # enable to not answer version.server and version.bind queries.
    hide-version: yes

  # Will trust glue only if it is within the servers authority.
  # Harden against out of zone rrsets, to avoid spoofing attempts. 
  # Hardening queries multiple name servers for the same data to make
  # spoofing significantly harder and does not mandate dnssec.
    harden-glue: yes

  # Require DNSSEC data for trust-anchored zones, if such data is absent, the
  # zone becomes  bogus.  Harden against receiving dnssec-stripped data. If you
  # turn it off, failing to validate dnskey data for a trustanchor will trigger
  # insecure mode for that zone (like without a trustanchor).  Default on,
  # which insists on dnssec data for trust-anchored zones.
    harden-dnssec-stripped: yes

  # Use 0x20-encoded random bits in the query to foil spoof attempts.
  # http://tools.ietf.org/html/draft-vixie-dnsext-dns0x20-00
  # While upper and lower case letters are allowed in domain names, no significance
  # is attached to the case. That is, two names with the same spelling but
  # different case are to be treated as if identical. This means calomel.org is the
  # same as CaLoMeL.Org which is the same as CALOMEL.ORG.
    use-caps-for-id: yes

  # the time to live (TTL) value lower bound, in seconds. Default 0.
  # If more than an hour could easily give trouble due to stale data.
    cache-min-ttl: 3600

  # the time to live (TTL) value cap for RRsets and messages in the
  # cache. Items are not cached for longer. In seconds.
    cache-max-ttl: 86400

  # perform prefetching of close to expired message cache entries.  If a client
  # requests the dns lookup and the TTL of the cached hostname is going to
  # expire in less than 10% of its TTL, unbound will (1st) return the ip of the
  # host to the client and (2nd) pre-fetch the dns request from the remote dns
  # server. This method has been shown to increase the amount of cached hits by
  # local clients by 10% on average.
    prefetch: yes

  # number of threads to create. 1 disables threading. This should equal the number
  # of CPU cores in the machine. Our example machine has 4 CPU cores.
    num-threads: 4


  ## Unbound Optimization and Speed Tweaks ###

  # the number of slabs to use for cache and must be a power of 2 times the
  # number of num-threads set above. more slabs reduce lock contention, but
  # fragment memory usage.
    msg-cache-slabs: 8
    rrset-cache-slabs: 8
    infra-cache-slabs: 8
    key-cache-slabs: 8

  # Increase the memory size of the cache. Use roughly twice as much rrset cache
  # memory as you use msg cache memory. Due to malloc overhead, the total memory
  # usage is likely to rise to double (or 2.5x) the total cache memory. The test
  # box has 4gig of ram so 256meg for rrset allows a lot of room for cacheed objects.
    rrset-cache-size: 256m
    msg-cache-size: 128m

  # buffer size for UDP port 53 incoming (SO_RCVBUF socket option). This sets
  # the kernel buffer larger so that no messages are lost in spikes in the traffic.
    so-rcvbuf: 1m

  ## Unbound Optimization and Speed Tweaks ###


  # Enforce privacy of these addresses. Strips them away from answers.  It may
  # cause DNSSEC validation to additionally mark it as bogus.  Protects against
  # 'DNS Rebinding' (uses browser as network proxy).  Only 'private-domain' and
  # 'local-data' names are allowed to have these private addresses. No default.
    private-address: 192.168.0.0/16
    private-address: 172.16.0.0/12
    private-address: 10.0.0.0/8

  # Allow the domain (and its subdomains) to contain private addresses.
  # local-data statements are allowed to contain private addresses too.
    private-domain: "home.lan"

  # If nonzero, unwanted replies are not only reported in statistics, but also
  # a running total is kept per thread. If it reaches the threshold, a warning
  # is printed and a defensive action is taken, the cache is cleared to flush
  # potential poison out of it.  A suggested value is 10000000, the default is
  # 0 (turned off). We think 10K is a good value.
    unwanted-reply-threshold: 10000

  # IMPORTANT FOR TESTING: If you are testing and setup NSD or BIND  on
  # localhost you will want to allow the resolver to send queries to localhost.
  # Make sure to set do-not-query-localhost: yes . If yes, the above default
  # do-not-query-address entries are present.  if no, localhost can be queried
  # (for testing and debugging). 
    do-not-query-localhost: no

  # File with trusted keys, kept up to date using RFC5011 probes, initial file
  # like trust-anchor-file, then it stores metadata.  Use several entries, one
  # per domain name, to track multiple zones. If you use forward-zone below to
  # query the Google DNS servers you MUST comment out this option or all DNS
  # queries will fail.
  # auto-trust-anchor-file: "/var/unbound/etc/root.key"

  # Should additional section of secure message also be kept clean of unsecure
  # data. Useful to shield the users of this validator from potential bogus
  # data in the additional section. All unsigned data in the additional section
  # is removed from secure messages.
    val-clean-additional: yes

  # Blocking Ad Server domains. Google's AdSense, DoubleClick and Yahoo
  # account for a 70 percent share of all advertising traffic. Block them.
  # local-zone: "doubleclick.net" redirect
  # local-data: "doubleclick.net A 127.0.0.1"
  # local-zone: "googlesyndication.com" redirect
  # local-data: "googlesyndication.com A 127.0.0.1"
  # local-zone: "googleadservices.com" redirect
  # local-data: "googleadservices.com A 127.0.0.1"
  # local-zone: "google-analytics.com" redirect
  # local-data: "google-analytics.com A 127.0.0.1"
  # local-zone: "ads.youtube.com" redirect
  # local-data: "ads.youtube.com A 127.0.0.1"
  # local-zone: "adserver.yahoo.com" redirect
  # local-data: "adserver.yahoo.com A 127.0.0.1"
  # local-zone: "ask.com" redirect
  # local-data: "ask.com A 127.0.0.1"


  # Unbound will not load if you specify the same local-zone and local-data
  # servers in the main configuration as well as in this "include:" file. We
  # suggest commenting out any of the local-zone and local-data lines above if
  # you suspect they could be included in the unbound_ad_servers servers file.
  #include: "/etc/unbound/unbound_ad_servers"

  # locally served zones can be configured for the machines on the LAN.

    local-zone: "home.lan." static

    local-data: "firewall.home.lan.  IN A 10.0.0.1"
    local-data: "laptop.home.lan.    IN A 10.0.0.2"
    local-data: "xboxone.home.lan.   IN A 10.0.0.3"
    local-data: "ps4.home.lan.       IN A 10.0.0.4"
    local-data: "dhcp5.home.lan.     IN A 10.0.0.5"
    local-data: "dhcp6.home.lan.     IN A 10.0.0.6"
    local-data: "dhcp7.home.lan.     IN A 10.0.0.7"

    local-data-ptr: "10.0.0.1  firewall.home.lan"
    local-data-ptr: "10.0.0.2  laptop.home.lan"
    local-data-ptr: "10.0.0.3  xboxone.home.lan"
    local-data-ptr: "10.0.0.4  ps4.home.lan"
    local-data-ptr: "10.0.0.5  dhcp5.home.lan"
    local-data-ptr: "10.0.0.6  dhcp6.home.lan"
    local-data-ptr: "10.0.0.7  dhcp7.home.lan"

  # Unbound can query your NSD or BIND server for private domain queries too.
  # On our NSD page we have NSD configured to serve the private domain,
  # "home.lan". Here we can tell Unbound to connect to the NSD server when it
  # needs to resolve a *.home.lan hostname or IP.
  #
  # private-domain: "home.lan"
  # local-zone: "0.0.10.in-addr.arpa." nodefault
  # stub-zone:
  #      name: "home.lan"
  #      stub-addr: 10.0.0.111@53

  # If you have an internal or private DNS names the external DNS servers can
  # not resolve, then you can assign domain name strings to be redirected to a
  # seperate dns server. For example, our comapny has the domain
  # organization.com and the domain name internal.organization.com can not be
  # resolved by Google's public DNS, but can be resolved by our private DNS
  # server located at 1.1.1.1. The following tells Unbound that any
  # organization.com domain, i.e. *.organization.com be dns resolved by 1.1.1.1
  # instead of the public dns servers.
  #
  # forward-zone:
  #    name: "organization.com"
  #    forward-addr: 1.1.1.1        # Internal or private DNS

  # Use the following forward-zone to forward all queries to Google DNS,
  # OpenDNS.com or your local ISP's dns servers for example. To test resolution
  # speeds use "drill calomel.org @8.8.8.8" and look for the "Query time:" in
  # milliseconds.
  #
   forward-zone:
      name: "."
      forward-addr: 8.8.4.4        # Google
      forward-addr: 8.8.8.8        # Google
      forward-addr: 37.235.1.174   # FreeDNS
      forward-addr: 37.235.1.177   # FreeDNS
      forward-addr: 50.116.23.211  # OpenNIC
      forward-addr: 64.6.64.6      # Verisign
      forward-addr: 64.6.65.6      # Verisign
      forward-addr: 74.82.42.42    # Hurricane Electric
      forward-addr: 84.200.69.80   # DNS Watch
      forward-addr: 84.200.70.40   # DNS Watch
      forward-addr: 91.239.100.100 # censurfridns.dk
      forward-addr: 109.69.8.51    # puntCAT
      forward-addr: 208.67.222.220 # OpenDNS
      forward-addr: 208.67.222.222 # OpenDNS
      forward-addr: 216.146.35.35  # Dyn Public
      forward-addr: 216.146.36.36  # Dyn Public

#
#
## Authoritative, validating, recursive caching DNS
## unbound.conf -- https://calomel.org
;       This file holds the information on root name servers needed to 
;       initialize cache of Internet domain name servers
;       (e.g. reference this file in the "cache  .  <file>"
;       configuration file of BIND domain name servers). 
; 
;       This file is made available by InterNIC 
;       under anonymous FTP as
;           file                /domain/named.cache 
;           on server           FTP.INTERNIC.NET
;       -OR-                    RS.INTERNIC.NET
; 
;       last update:     October 24, 2017 
;       related version of root zone:     2017102400
; 
; FORMERLY NS.INTERNIC.NET 
;
.                        3600000      NS    A.ROOT-SERVERS.NET.
A.ROOT-SERVERS.NET.      3600000      A     198.41.0.4
A.ROOT-SERVERS.NET.      3600000      AAAA  2001:503:ba3e::2:30
; 
; FORMERLY NS1.ISI.EDU 
;
.                        3600000      NS    B.ROOT-SERVERS.NET.
B.ROOT-SERVERS.NET.      3600000      A     199.9.14.201
B.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:200::b
; 
; FORMERLY C.PSI.NET 
;
.                        3600000      NS    C.ROOT-SERVERS.NET.
C.ROOT-SERVERS.NET.      3600000      A     192.33.4.12
C.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:2::c
; 
; FORMERLY TERP.UMD.EDU 
;
.                        3600000      NS    D.ROOT-SERVERS.NET.
D.ROOT-SERVERS.NET.      3600000      A     199.7.91.13
D.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:2d::d
; 
; FORMERLY NS.NASA.GOV
;
.                        3600000      NS    E.ROOT-SERVERS.NET.
E.ROOT-SERVERS.NET.      3600000      A     192.203.230.10
E.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:a8::e
; 
; FORMERLY NS.ISC.ORG
;
.                        3600000      NS    F.ROOT-SERVERS.NET.
F.ROOT-SERVERS.NET.      3600000      A     192.5.5.241
F.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:2f::f
; 
; FORMERLY NS.NIC.DDN.MIL
;
.                        3600000      NS    G.ROOT-SERVERS.NET.
G.ROOT-SERVERS.NET.      3600000      A     192.112.36.4
G.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:12::d0d
; 
; FORMERLY AOS.ARL.ARMY.MIL
;
.                        3600000      NS    H.ROOT-SERVERS.NET.
H.ROOT-SERVERS.NET.      3600000      A     198.97.190.53
H.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:1::53
; 
; FORMERLY NIC.NORDU.NET
;
.                        3600000      NS    I.ROOT-SERVERS.NET.
I.ROOT-SERVERS.NET.      3600000      A     192.36.148.17
I.ROOT-SERVERS.NET.      3600000      AAAA  2001:7fe::53
; 
; OPERATED BY VERISIGN, INC.
;
.                        3600000      NS    J.ROOT-SERVERS.NET.
J.ROOT-SERVERS.NET.      3600000      A     192.58.128.30
J.ROOT-SERVERS.NET.      3600000      AAAA  2001:503:c27::2:30
; 
; OPERATED BY RIPE NCC
;
.                        3600000      NS    K.ROOT-SERVERS.NET.
K.ROOT-SERVERS.NET.      3600000      A     193.0.14.129
K.ROOT-SERVERS.NET.      3600000      AAAA  2001:7fd::1
; 
; OPERATED BY ICANN
;
.                        3600000      NS    L.ROOT-SERVERS.NET.
L.ROOT-SERVERS.NET.      3600000      A     199.7.83.42
L.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:9f::42
; 
; OPERATED BY WIDE
;
.                        3600000      NS    M.ROOT-SERVERS.NET.
M.ROOT-SERVERS.NET.      3600000      A     202.12.27.33
M.ROOT-SERVERS.NET.      3600000      AAAA  2001:dc3::35
; End of file
##############   Script FreeDNS.afraid.org   ##################
##############   PARSER EDITION   ##################
##############   CREATED LESHIY_ODESSA   ##################
   
# Specify the "Direct URL", which is https://freedns.afraid.org/dynamic/
# If RouterOS version 5.xx, then remove from the URL encryption - "https" change this to "http". Also see below.
# In front of the sign "?" put a backslash "\".
:global "direct-url" "http://freedns.afraid.org/dynamic/update.php\?dedC0TirYibYdzBYnnhVRiJJb8Q6iDY1Mji3mQ=="

# Specify the URL API "ASCII"
# Log in under your account and open the page https://freedns.afraid.org/api/
# Then copy the URL of your site - Available API Interfaces : ASCII (!!! NOT XML !!!)
# ATTENTION!!!! Before the question mark, put a backslash "\".
# If RouterOS version 5.xx, then remove from the URL encryption - "https" change this to "http".
:global "api-url" "http://freedns.afraid.org/api/\?action=getdyndns&sha=62egb6606ci46cbe6eo8iga61de6ia101858a08n"
    
# Specify your domain or subdomain.
:global "dns-domain" "name.com"

# Define variables for the external (WAN) interface
# Case sensitive.
:global "out-interface" "pppoe"
       
# !!!!!!!!!!!!!!!!! Nothing more do not need to edit!!!!!!!!!!!!!!!!!
       
# Check whether the file with the IP domain - freedns.txt
:if ([:len [/file find name=freedns.txt]] > 0) do={
} else={
/tool fetch url=$"api-url" dst-path="/freedns.txt"
}
# Find out the IP address of the domain using the API and parsing.
# Split the file
:local "result" [/file get freedns.txt contents]
:local "startloc" ([:find $"result" $"dns-domain"] + ([:len $"dns-domain"] + 1))
:local "endloc" ([:find $"result" $"direct-url" -1] -1)
:global "dns-domain-ip" [:pick $"result" $"startloc" $"endloc"]
       
# Find the current IP address on the external interface
:global "current-ip" [/ip address get [find interface=$"out-interface"] address]
    
# Obtained from IP addresses to be excluded subnet mask
:set "current-ip" [:pick $"current-ip" 0 ([:len $"current-ip"]-3) ]
       
# Compare the external IP with the IP address of the DNS domain.
:if ($"current-ip" != $"dns-domain-ip") do={

# If different, then sent to freedns.afraid.org our external IP by using Direct URL
:log info ("Service Dynamic DNS: old IP address $"dns-domain-ip" for $"dns-domain" CHANGED to -> $"current-ip"")
/tool fetch url=$"direct-url" keep-result=no
# Download the file with the new IP after 5 sec.
:delay 5
/tool fetch url=$"api-url" dst-path="/freedns.txt"
} else={
# Not to clog the log, you need to comment out this line.
:log info ("IP address is NOT CHANGED, the update is not required")
}
    
# Since version RouterOS version 6.0rc12 supported encryption /tool fetch mode=https
# In :global "direct-url" need to change to httpS://
# For RouterOS version 6.xx
# /tool fetch mode=https url=$"direct url"
# :global "direct-url" "https://freedns.afraid.org/dynamic/update.php\?UVdjU2lzQmQwSkdjZW9aWkNleTdJdXFtOjg2NTI0NzE="

#      http://wiki.mikrotik.com/wiki/Manual:Scripting
#      http://wiki.mikrotik.com/wiki/Manual:Scripting-examples
#      http://wiki.mikrotik.com/wiki/Manual:Tools/Fetch
#      http://forum.ixbt.com/topic.cgi?id=14:60498-86#2373

##############Script FreeDNS.afraid.org##################
# Need to set script scheduler
###
# Note part of overall script - use this once script on router/comp
#-> /system scheduler
#-> add disabled=no interval=1m name=freedns.afraid.org on-event="/system script run freedns.afraid.org" policy=ftp,reboot,read,write,policy,test,winbox,password,sniff,sensitive,api start-time=startup
/* Tool godns - Golang DDNS update client

To 

Source: github.com/TimothyYe/godns
*/
{
  "provider": "HE",
  "email": "",
  "password": "YourPassword",
  "login_token": "",
  "domains": [{
      "domain_name": "example.com",
      "sub_domains": ["www","test"]
    },{
      "domain_name": "example2.com",
      "sub_domains": ["www","test"]
    }
  ],
  "ip_url": "http://members.3322.org/dyndns/getip",
  "log_path":"/users/timothy/workspace/src/godns/godns.log",
  "log_size":16,
  "log_num":3,
  "socks5_proxy": ""
}
#!/bin/sh
##############################################################################
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# Copyright (C) 2016 Eric Luehrsen
#
##############################################################################
#
# These are iptools that might be useful in a larger package, if provided
# elsewhere for common use. One example that many may find useful is turning
# flexible IPV6 colon dividers into PTR. Otherwise these are incomplete and
# would need robustness improvements for more generic applications.
#
##############################################################################

domain_ptr_ip6() {
  # Get the nibble rounded /CIDR ...ip6.arpa.
  echo "$1" | awk -F: \
  'BEGIN { OFS = "" ; }
  { CIDR = $0 ;
  sub(/.*\//,"",CIDR) ;
  CIDR = (CIDR / 4) ;
  sub(/\/[0-9]+/,"",$0) ;
  ct_stop = 9 - NF ;
  for(i=1; i<=NF; i++) {
    if(length($i) == 0) {
      for(j=1; j<=ct_stop; j++) { $i = ($i "0000") ; } }
    else { $i = substr(("0000" $i), length($i)+5-4) ; } } ;
  y = $0 ;
  ct_start = length(y) - 32 + CIDR ;
  for(i=ct_start; i>0; i--) { x = (x substr(y,i,1)) ; } ;
  gsub(/./,"&\.",x) ;
  x = (x "ip6.arpa") ;
  print x }'
}

##############################################################################

host_ptr_ip6() {
  # Get complete host ...ip6.arpa.
  echo "$1" | awk -F: \
  'BEGIN { OFS = "" ; }
  { sub(/\/[0-9]+/,"",$0) ;
  ct_stop = 9 - NF ;
  for(i=1; i<=NF; i++) {
    if(length($i) == 0) {
      for(j=1; j<=ct_stop; j++) { $i = ($i "0000") ; } }
    else { $i = substr(("0000" $i), length($i)+5-4) ; } } ;
  y = $0 ;
  ct_start = length(y);
  for(i=ct_start; i>0; i--) { x = (x substr(y,i,1)) ; } ;
  sub(/[0-9]+\//,"",x) ;
  gsub(/./,"&\.",x) ;
  x = (x "ip6.arpa") ;
  print x }'
}

##############################################################################

domain_ptr_ip4() {
  # Get the byte rounded /CIDR ...in-addr.arpa.
  echo "$1" | awk \
  '{ CIDR = $0 ;
  sub(/.*\//,"",CIDR) ;
  CIDR = (CIDR / 8) ;
  dtxt = $0 ;
  sub(/\/.*/,"",dtxt) ;
  split(dtxt, dtxt, ".") ;
  for(i=1; i<=CIDR; i++) { x = (dtxt[i] "." x) ; }
  x = (x "in-addr.arpa") ;
  print x }'
}

##############################################################################

host_ptr_ip4() {
  # Get omplete host ...in-addr.arpa.
  echo "$1" | awk -F. \
  '{ x = ( $4"."$3"."$2"."$1".in-addr.arpa" ) ;
  sub(/\/[0-9]+/,"",x) ;
  print x }'
}

##############################################################################

valid_subnet6() {
  case "$1" in
    # GA
    [1-9][0-9a-f][0-9a-f][0-9a-f]":"*) echo "ok" ;;
    # ULA
    f[cd][0-9a-f][0-9a-f]":"*) echo "ok" ;;
    # fe80::, ::1, and such
    *) echo "not" ;;
  esac
}

##############################################################################

valid_subnet4() {
  case "$1" in
    # Link, Local, and Such
    169"."254"."*) echo "not" ;;
    127"."*) echo "not" ;;
    0"."*) echo "not" ;;
    255"."*) echo "not" ;;
    # Other Normal
    25[0-4]"."[0-9]*) echo "ok" ;;
    2[0-4][0-9]"."[0-9]*) echo "ok" ;;
    1[0-9][0-9]"."[0-9]*) echo "ok" ;;
    [0-9][0-9]"."[0-9]*) echo "ok" ;;
    [0-9]"."[0-9]*) echo "ok" ;;
    # Not Right
    *) echo "not";;
  esac
}

##############################################################################

private_subnet() {
  case "$1" in
    10"."*) echo "ok" ;;
    172"."1[6-9]"."*) echo "ok" ;;
    172"."2[0-9]"."*) echo "ok" ;;
    172"."3[0-1]"."*) echo "ok" ;;
    192"."168"."*) echo "ok" ;;
    f[cd][0-9a-f][0-9a-f]":"*) echo "ok" ;;
    *) echo "not" ;;
  esac
}

##############################################################################
#!/bin/sh
##############################################################################
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# Copyright (C) 2016 Eric Luehrsen
#
##############################################################################
#
# Unbound is a full featured recursive server with many options. The UCI
# provided tries to simplify and bundle options. This should make Unbound
# easier to deploy. Even light duty routers may resolve recursively instead of
# depending on a stub with the ISP. The UCI also attempts to replicate dnsmasq
# features as used in base LEDE/OpenWrt. If there is a desire for more
# detailed tuning, then manual conf file overrides are also made available.
#
##############################################################################

UNBOUND_B_SLAAC6_MAC=0
UNBOUND_B_DNSSEC=0
UNBOUND_B_DNS64=0
UNBOUND_B_EXT_STATS=0
UNBOUND_B_GATE_NAME=0
UNBOUND_B_HIDE_BIND=1
UNBOUND_B_LOCL_BLCK=0
UNBOUND_B_LOCL_SERV=1
UNBOUND_B_MAN_CONF=0
UNBOUND_B_NTP_BOOT=1
UNBOUND_B_PRIV_BLCK=1
UNBOUND_B_QUERY_MIN=0
UNBOUND_B_QRY_MINST=0

UNBOUND_D_CONTROL=0
UNBOUND_D_DOMAIN_TYPE=static
UNBOUND_D_DHCP_LINK=none
UNBOUND_D_EXTRA_DNS=0
UNBOUND_D_LAN_FQDN=0
UNBOUND_D_PROTOCOL=mixed
UNBOUND_D_RESOURCE=small
UNBOUND_D_RECURSION=passive
UNBOUND_D_WAN_FQDN=0

UNBOUND_IP_DNS64="64:ff9b::/96"

UNBOUND_N_EDNS_SIZE=1280
UNBOUND_N_FWD_PORTS=""
UNBOUND_N_RX_PORT=53
UNBOUND_N_ROOT_AGE=9

UNBOUND_TTL_MIN=120

UNBOUND_TXT_DOMAIN=lan
UNBOUND_TXT_FWD_ZONE=""
UNBOUND_TXT_HOSTNAME=thisrouter

##############################################################################

# keep track of local-domain: assignments during inserted resource records
UNBOUND_LIST_DOMAINS=""

##############################################################################

UNBOUND_LIBDIR=/usr/lib/unbound
UNBOUND_VARDIR=/var/lib/unbound

UNBOUND_PIDFILE=/var/run/unbound.pid

UNBOUND_SRV_CONF=$UNBOUND_VARDIR/unbound_srv.conf
UNBOUND_EXT_CONF=$UNBOUND_VARDIR/unbound_ext.conf
UNBOUND_DHCP_CONF=$UNBOUND_VARDIR/unbound_dhcp.conf
UNBOUND_CONFFILE=$UNBOUND_VARDIR/unbound.conf

UNBOUND_KEYFILE=$UNBOUND_VARDIR/root.key
UNBOUND_HINTFILE=$UNBOUND_VARDIR/root.hints
UNBOUND_TIMEFILE=$UNBOUND_VARDIR/hotplug.time

UNBOUND_CTLKEY_FILE=$UNBOUND_VARDIR/unbound_control.key
UNBOUND_CTLPEM_FILE=$UNBOUND_VARDIR/unbound_control.pem
UNBOUND_SRVKEY_FILE=$UNBOUND_VARDIR/unbound_server.key
UNBOUND_SRVPEM_FILE=$UNBOUND_VARDIR/unbound_server.pem

##############################################################################

UNBOUND_ANCHOR=/usr/sbin/unbound-anchor
UNBOUND_CONTROL=/usr/sbin/unbound-control
UNBOUND_CONTROL_CFG="$UNBOUND_CONTROL -c $UNBOUND_CONFFILE"

##############################################################################

. /lib/functions.sh
. /lib/functions/network.sh

. $UNBOUND_LIBDIR/dnsmasq.sh
. $UNBOUND_LIBDIR/iptools.sh
. $UNBOUND_LIBDIR/rootzone.sh

##############################################################################

copy_dash_update() {
  # TODO: remove this function and use builtins when this issues is resovled.
  # Due to OpenWrt/LEDE divergence "cp -u" isn't yet universally available.
  local filetime keeptime


  if [ -f $UNBOUND_KEYFILE.keep ] ; then
    # root.key.keep is reused if newest
    filetime=$( date -r $UNBOUND_KEYFILE +%s )
    keeptime=$( date -r $UNBOUND_KEYFILE.keep +%s )


    if [ $keeptime -gt $filetime ] ; then
      cp $UNBOUND_KEYFILE.keep $UNBOUND_KEYFILE
    fi


    rm -f $UNBOUND_KEYFILE.keep
  fi
}

##############################################################################

create_interface_dns() {
  local cfg="$1"
  local ipcommand logint ignore ifname ifdashname
  local name names address addresses
  local ulaprefix if_fqdn host_fqdn mode mode_ptr

  # Create local-data: references for this hosts interfaces (router).
  config_get logint "$cfg" interface
  config_get_bool ignore "$cfg" ignore 0
  network_get_device ifname "$cfg"

  ifdashname="${ifname//./-}"
  ipcommand="ip -o address show $ifname"
  addresses=$( $ipcommand | awk '/inet/{sub(/\/.*/,"",$4); print $4}' )
  ulaprefix=$( uci_get network.@globals[0].ula_prefix )
  host_fqdn="$UNBOUND_TXT_HOSTNAME.$UNBOUND_TXT_DOMAIN"
  if_fqdn="$ifdashname.$host_fqdn"


  if [ -z "${ulaprefix%%:/*}" ] ; then
    # Nonsense so this option isn't globbed below
    ulaprefix="fdno:such:addr::/48"
  fi


  if [ "$ignore" -gt 0 ] ; then
    mode="$UNBOUND_D_WAN_FQDN"
  else
    mode="$UNBOUND_D_LAN_FQDN"
  fi


  case "$mode" in
  3)
    mode_ptr="$host_fqdn"
    names="$host_fqdn  $UNBOUND_TXT_HOSTNAME"
    ;;

  4)
    if [ -z "$ifdashname" ] ; then
      # race conditions at init can rarely cause a blank device return
      # the record format is invalid and Unbound won't load the conf file
      mode_ptr="$host_fqdn"
      names="$host_fqdn  $UNBOUND_TXT_HOSTNAME"
    else
      mode_ptr="$if_fqdn"
      names="$if_fqdn  $host_fqdn  $UNBOUND_TXT_HOSTNAME"
    fi
    ;;

  *)
    mode_ptr="$UNBOUND_TXT_HOSTNAME"
    names="$UNBOUND_TXT_HOSTNAME"
    ;;
  esac


  if [ "$mode" -gt 1 ] ; then
    {
      for address in $addresses ; do
        case $address in
        fe80:*|169.254.*)
          echo "  # note link address $address"
          ;;

        [1-9a-f]*:*[0-9a-f])
          # GA and ULA IP6 for HOST IN AAA records (ip command is robust)
          for name in $names ; do
            echo "  local-data: \"$name. 120 IN AAAA $address\""
          done
          echo "  local-data-ptr: \"$address 120 $mode_ptr\""
          ;;

        [1-9]*.*[0-9])
          # Old fashioned HOST IN A records
          for name in $names ; do
            echo "  local-data: \"$name. 120 IN A $address\""
          done
          echo "  local-data-ptr: \"$address 120 $mode_ptr\""
          ;;
        esac
      done
      echo
    } >> $UNBOUND_CONFFILE

  elif [ "$mode" -gt 0 ] ; then
    {
      for address in $addresses ; do
        case $address in
        fe80:*|169.254.*)
          echo "  # note link address $address"
          ;;

        "${ulaprefix%%:/*}"*)
          # Only this networks ULA and only hostname
          echo "  local-data: \"$UNBOUND_TXT_HOSTNAME. 120 IN AAAA $address\""
          echo "  local-data-ptr: \"$address 120 $UNBOUND_TXT_HOSTNAME\""
          ;;

        [1-9]*.*[0-9])
          echo "  local-data: \"$UNBOUND_TXT_HOSTNAME. 120 IN A $address\""
          echo "  local-data-ptr: \"$address 120 $UNBOUND_TXT_HOSTNAME\""
          ;;
        esac
      done
      echo
    } >> $UNBOUND_CONFFILE
  fi
}

##############################################################################

create_local_zone() {
  local target="$1"
  local partial domain found


  if [ -n "$UNBOUND_LIST_DOMAINS" ] ; then
    for domain in $UNBOUND_LIST_DOMAINS ; do
      case $target in
      *"${domain}")
        found=1
        break
        ;;

      [A-Za-z0-9]*.[A-Za-z0-9]*)
        found=0
        ;;

      *) # no dots
        found=1
        break
        ;;
      esac
    done
  else
    found=0
  fi


  if [ $found -eq 0 ] ; then
    # New Zone! Bundle local-zones: by first two name tiers "abcd.tld."
    partial=$( echo "$target" | awk -F. '{ j=NF ; i=j-1; print $i"."$j }' )
    UNBOUND_LIST_DOMAINS="$UNBOUND_LIST_DOMAINS $partial"
    echo "  local-zone: $partial. transparent" >> $UNBOUND_CONFFILE
  fi
}

##############################################################################

create_host_record() {
  local cfg="$1"
  local ip name

  # basefiles dhcp "domain" clause which means host A, AAAA, and PRT record
  config_get ip   "$cfg" ip
  config_get name "$cfg" name


  if [ -n "$name" -a -n "$ip" ] ; then
    create_local_zone "$name"

    {
      case $ip in
      fe80:*|169.254.*)
        echo "  # note link address $ip for host $name"
        ;;

      [1-9a-f]*:*[0-9a-f])
        echo "  local-data: \"$name. 120 IN AAAA $ip\""
        echo "  local-data-ptr: \"$ip 120 $name\""
        ;;

      [1-9]*.*[0-9])
        echo "  local-data: \"$name. 120 IN A $ip\""
        echo "  local-data-ptr: \"$ip 120 $name\""
        ;;
      esac
    } >> $UNBOUND_CONFFILE
  fi
}

##############################################################################

create_mx_record() {
  local cfg="$1"
  local domain relay pref

  # Insert a static MX record
  config_get domain "$cfg" domain
  config_get relay  "$cfg" relay
  config_get pref   "$cfg" pref 10


  if [ -n "$domain" -a -n "$relay" ] ; then
    create_local_zone "$domain"
    echo "  local-data: \"$domain. 120 IN MX $pref $relay.\"" \
          >> $UNBOUND_CONFFILE
  fi
}

##############################################################################

create_srv_record() {
  local cfg="$1"
  local srv target port class weight

  # Insert a static SRV record such as SIP server
  config_get srv    "$cfg" srv
  config_get target "$cfg" target
  config_get port   "$cfg" port
  config_get class  "$cfg" class 10
  config_get weight "$cfg" weight 10


  if [ -n "$srv" -a -n "$target" -a -n "$port" ] ; then
    create_local_zone "$srv"
    echo "  local-data: \"$srv. 120 IN SRV $class $weight $port $target.\"" \
          >> $UNBOUND_CONFFILE
  fi
}

##############################################################################

create_cname_record() {
  local cfg="$1"
  local cname target

  # Insert static CNAME record
  config_get cname  "$cfg" cname
  config_get target "$cfg" target


  if [ -n "$cname" -a -n "$target" ] ; then
    create_local_zone "$cname"
    echo "  local-data: \"$cname. 120 IN CNAME $target.\"" >> $UNBOUND_CONFFILE
  fi
}

##############################################################################

create_access_control() {
  local cfg="$1"
  local subnets subnets4 subnets6
  local validip4 validip6

  network_get_subnets  subnets4 "$cfg"
  network_get_subnets6 subnets6 "$cfg"
  subnets="$subnets4 $subnets6"


  if [ -n "$subnets" ] ; then
    for subnet in $subnets ; do
      validip4=$( valid_subnet4 $subnet )
      validip6=$( valid_subnet6 $subnet )


      if [ "$validip4" = "ok" -o "$validip6" = "ok" ] ; then
        # For each "network" UCI add "access-control:" white list for queries
        echo "  access-control: $subnet allow" >> $UNBOUND_CONFFILE
      fi
    done
  fi
}

##############################################################################

create_domain_insecure() {
  echo "  domain-insecure: \"$1\"" >> $UNBOUND_CONFFILE
}

##############################################################################

unbound_mkdir() {
  local dhcp_origin=$( uci_get dhcp.@odhcpd[0].leasefile )
  local dhcp_dir=$( dirname $dhcp_origin )
  local filestuff


  if [ "$UNBOUND_D_DHCP_LINK" = "odhcpd" -a ! -d "$dhcp_dir" ] ; then
    # make sure odhcpd has a directory to write (not done itself, yet)
    mkdir -p "$dhcp_dir"
  fi


  if [ -f $UNBOUND_KEYFILE ] ; then
    filestuff=$( cat $UNBOUND_KEYFILE )


    case "$filestuff" in
      *"state=2 [  VALID  ]"*)
        # Lets not lose RFC 5011 tracking if we don't have to
        cp -p $UNBOUND_KEYFILE $UNBOUND_KEYFILE.keep
        ;;
    esac
  fi


  # Blind copy /etc/ to /var/lib/
  mkdir -p $UNBOUND_VARDIR
  rm -f $UNBOUND_VARDIR/dhcp_*
  touch $UNBOUND_CONFFILE
  touch $UNBOUND_SRV_CONF
  touch $UNBOUND_EXT_CONF
  cp -p /etc/unbound/* $UNBOUND_VARDIR/


  if [ ! -f $UNBOUND_HINTFILE ] ; then
    if [ -f /usr/share/dns/root.hints ] ; then
      # Debian-like package dns-root-data
      cp -p /usr/share/dns/root.hints $UNBOUND_HINTFILE

    elif [ ! -f "$UNBOUND_TIMEFILE" ] ; then
      logger -t unbound -s "iterator will use built-in root hints"
    fi
  fi


  if [ ! -f $UNBOUND_KEYFILE ] ; then
    if [ -f /usr/share/dns/root.key ] ; then
      # Debian-like package dns-root-data
      cp -p /usr/share/dns/root.key $UNBOUND_KEYFILE

    elif [ -x $UNBOUND_ANCHOR ] ; then
      $UNBOUND_ANCHOR -a $UNBOUND_KEYFILE

    elif [ ! -f "$UNBOUND_TIMEFILE" ] ; then
      logger -t unbound -s "validator will use built-in trust anchor"
    fi
  fi


  copy_dash_update


  # Ensure access and prepare to jail
  chown -R unbound:unbound $UNBOUND_VARDIR
  chmod 755 $UNBOUND_VARDIR
  chmod 644 $UNBOUND_VARDIR/*


  if [ -f $UNBOUND_CTLKEY_FILE -o -f $UNBOUND_CTLPEM_FILE \
    -o -f $UNBOUND_SRVKEY_FILE -o -f $UNBOUND_SRVPEM_FILE ] ; then
    # Keys (some) exist already; do not create new ones
    chmod 640 $UNBOUND_CTLKEY_FILE $UNBOUND_CTLPEM_FILE \
              $UNBOUND_SRVKEY_FILE $UNBOUND_SRVPEM_FILE

  elif [ -x /usr/sbin/unbound-control-setup ] ; then
    case "$UNBOUND_D_CONTROL" in
    [2-3])
      # unbound-control-setup for encrypt opt. 2 and 3, but not 4 "static"
      /usr/sbin/unbound-control-setup -d $UNBOUND_VARDIR

      chown -R unbound:unbound  $UNBOUND_CTLKEY_FILE $UNBOUND_CTLPEM_FILE \
                                $UNBOUND_SRVKEY_FILE $UNBOUND_SRVPEM_FILE

      chmod 640 $UNBOUND_CTLKEY_FILE $UNBOUND_CTLPEM_FILE \
                $UNBOUND_SRVKEY_FILE $UNBOUND_SRVPEM_FILE

      cp -p $UNBOUND_CTLKEY_FILE /etc/unbound/unbound_control.key
      cp -p $UNBOUND_CTLPEM_FILE /etc/unbound/unbound_control.pem
      cp -p $UNBOUND_SRVKEY_FILE /etc/unbound/unbound_server.key
      cp -p $UNBOUND_SRVPEM_FILE /etc/unbound/unbound_server.pem
      ;;
    esac
  fi
}

##############################################################################

unbound_control() {
  if [ "$UNBOUND_D_CONTROL" -gt 1 ] ; then
    if [ ! -f $UNBOUND_CTLKEY_FILE -o ! -f $UNBOUND_CTLPEM_FILE \
      -o ! -f $UNBOUND_SRVKEY_FILE -o ! -f $UNBOUND_SRVPEM_FILE ] ; then
      # Key files need to be present; if unbound-control-setup was found, then
      # they might have been made during unbound_makedir() above.
      UNBOUND_D_CONTROL=0
    fi
  fi


  case "$UNBOUND_D_CONTROL" in
  1)
    {
      # Local Host Only Unencrypted Remote Control
      echo "remote-control:"
      echo "  control-enable: yes"
      echo "  control-use-cert: no"
      echo "  control-interface: 127.0.0.1"
      echo "  control-interface: ::1"
      echo
    } >> $UNBOUND_CONFFILE
    ;;

  2)
    {
      # Local Host Only Encrypted Remote Control
      echo "remote-control:"
      echo "  control-enable: yes"
      echo "  control-use-cert: yes"
      echo "  control-interface: 127.0.0.1"
      echo "  control-interface: ::1"
      echo "  server-key-file: \"$UNBOUND_SRVKEY_FILE\""
      echo "  server-cert-file: \"$UNBOUND_SRVPEM_FILE\""
      echo "  control-key-file: \"$UNBOUND_CTLKEY_FILE\""
      echo "  control-cert-file: \"$UNBOUND_CTLPEM_FILE\""
      echo
    } >> $UNBOUND_CONFFILE
    ;;

  [3-4])
    {
      # Network Encrypted Remote Control
      # (3) may auto setup and (4) must have static key/pem files
      # TODO: add UCI list for interfaces to bind
      echo "remote-control:"
      echo "  control-enable: yes"
      echo "  control-use-cert: yes"
      echo "  control-interface: 0.0.0.0"
      echo "  control-interface: ::0"
      echo "  server-key-file: \"$UNBOUND_SRVKEY_FILE\""
      echo "  server-cert-file: \"$UNBOUND_SRVPEM_FILE\""
      echo "  control-key-file: \"$UNBOUND_CTLKEY_FILE\""
      echo "  control-cert-file: \"$UNBOUND_CTLPEM_FILE\""
      echo
    } >> $UNBOUND_CONFFILE
    ;;
  esac


  {
    # Amend your own extended clauses here like forward zones or disable
    # above (local, no encryption) and amend your own remote encrypted control
    echo
    echo "include: $UNBOUND_EXT_CONF" >> $UNBOUND_CONFFILE
    echo
  } >> $UNBOUND_CONFFILE
}

##############################################################################

unbound_conf() {
  local cfg="$1"
  local rt_mem rt_conn modulestring

  # Make fresh conf file
  echo > $UNBOUND_CONFFILE


  {
    # Make fresh conf file
    echo "# $UNBOUND_CONFFILE generated by UCI $( date )"
    echo
    # No threading
    echo "server:"
    echo "  username: unbound"
    echo "  num-threads: 1"
    echo "  msg-cache-slabs: 1"
    echo "  rrset-cache-slabs: 1"
    echo "  infra-cache-slabs: 1"
    echo "  key-cache-slabs: 1"
    echo
    # Interface Wildcard (access contol handled by "option local_service")
    echo "  interface: 0.0.0.0"
    echo "  interface: ::0"
    echo "  outgoing-interface: 0.0.0.0"
    echo "  outgoing-interface: ::0"
    echo
    # Logging
    echo "  verbosity: 1"
    echo "  statistics-interval: 0"
    echo "  statistics-cumulative: no"
  } >> $UNBOUND_CONFFILE


  if [ "$UNBOUND_B_EXT_STATS" -gt 0 ] ; then
    {
      # Log More
      echo "  extended-statistics: yes"
      echo
    } >> $UNBOUND_CONFFILE

  else
    {
      # Log Less
      echo "  extended-statistics: no"
      echo
    } >> $UNBOUND_CONFFILE
  fi


  case "$UNBOUND_D_PROTOCOL" in
    ip4_only)
      {
        echo "  do-ip4: yes"
        echo "  do-ip6: no"
      } >> $UNBOUND_CONFFILE
      ;;

    ip6_only)
      {
        echo "  do-ip4: no"
        echo "  do-ip6: yes"
      } >> $UNBOUND_CONFFILE
      ;;

    ip6_prefer)
      {
        echo "  do-ip4: yes"
        echo "  do-ip6: yes"
        echo "  prefer-ip6: yes"
      } >> $UNBOUND_CONFFILE
      ;;

    *)
      {
        echo "  do-ip4: yes"
        echo "  do-ip6: yes"
      } >> $UNBOUND_CONFFILE
      ;;
  esac


  {
    # protocol level tuning
    echo "  edns-buffer-size: $UNBOUND_N_EDNS_SIZE"
    echo "  msg-buffer-size: 8192"
    echo "  port: $UNBOUND_N_RX_PORT"
    echo "  outgoing-port-permit: 10240-65535"
    echo
  } >> $UNBOUND_CONFFILE


  {
    # Other harding and options for an embedded router
    echo "  harden-short-bufsize: yes"
    echo "  harden-large-queries: yes"
    echo "  harden-glue: yes"
    echo "  harden-below-nxdomain: no"
    echo "  harden-referral-path: no"
    echo "  use-caps-for-id: no"
    echo
  } >> $UNBOUND_CONFFILE


  {
    # Default Files
    echo "  use-syslog: yes"
    echo "  chroot: \"$UNBOUND_VARDIR\""
    echo "  directory: \"$UNBOUND_VARDIR\""
    echo "  pidfile: \"$UNBOUND_PIDFILE\""
  } >> $UNBOUND_CONFFILE


  if [ -f "$UNBOUND_HINTFILE" ] ; then
    # Optional hints if found
    echo "  root-hints: \"$UNBOUND_HINTFILE\"" >> $UNBOUND_CONFFILE
  fi


  if [ "$UNBOUND_B_DNSSEC" -gt 0 -a -f "$UNBOUND_KEYFILE" ] ; then
    {
      echo "  auto-trust-anchor-file: \"$UNBOUND_KEYFILE\""
      echo
    } >> $UNBOUND_CONFFILE

  else
    echo >> $UNBOUND_CONFFILE
  fi


  case "$UNBOUND_D_RESOURCE" in
    # Tiny - Unbound's recommended cheap hardware config
    tiny)   rt_mem=1  ; rt_conn=1 ;;
    # Small - Half RRCACHE and open ports
    small)  rt_mem=8  ; rt_conn=5 ;;
    # Medium - Nearly default but with some added balancintg
    medium) rt_mem=16 ; rt_conn=10 ;;
    # Large - Double medium
    large)  rt_mem=32 ; rt_conn=10 ;;
    # Whatever unbound does
    *) rt_mem=0 ; rt_conn=0 ;;
  esac


  if [ "$rt_mem" -gt 0 ] ; then
    {
      # Set memory sizing parameters
      echo "  outgoing-range: $(($rt_conn*64))"
      echo "  num-queries-per-thread: $(($rt_conn*32))"
      echo "  outgoing-num-tcp: $(($rt_conn))"
      echo "  incoming-num-tcp: $(($rt_conn))"
      echo "  rrset-cache-size: $(($rt_mem*256))k"
      echo "  msg-cache-size: $(($rt_mem*128))k"
      echo "  key-cache-size: $(($rt_mem*128))k"
      echo "  neg-cache-size: $(($rt_mem*64))k"
      echo "  infra-cache-numhosts: $(($rt_mem*256))"
      echo
    } >> $UNBOUND_CONFFILE

  elif [ ! -f "$UNBOUND_TIMEFILE" ] ; then
    logger -t unbound -s "default memory resource consumption"
  fi

  # Assembly of module-config: options is tricky; order matters
  modulestring="iterator"


  if [ "$UNBOUND_B_DNSSEC" -gt 0 ] ; then
    if [ ! -f "$UNBOUND_TIMEFILE" -a "$UNBOUND_B_NTP_BOOT" -gt 0 ] ; then
      # DNSSEC chicken and egg with getting NTP time
      echo "  val-override-date: -1" >> $UNBOUND_CONFFILE
    fi


    {
      echo "  harden-dnssec-stripped: yes"
      echo "  val-clean-additional: yes"
      echo "  ignore-cd-flag: yes"
    } >> $UNBOUND_CONFFILE


    modulestring="validator $modulestring"
  fi


  if [ "$UNBOUND_B_DNS64" -gt 0 ] ; then
    echo "  dns64-prefix: $UNBOUND_IP_DNS64" >> $UNBOUND_CONFFILE

    modulestring="dns64 $modulestring"
  fi


  {
    # Print final module string
    echo "  module-config: \"$modulestring\""
    echo
  }  >> $UNBOUND_CONFFILE


  if [ "$UNBOUND_B_QRY_MINST" -gt 0 -a "$UNBOUND_B_QUERY_MIN" -gt 0 ] ; then
    {
      # Some query privacy but "strict" will break some name servers
      echo "  qname-minimisation: yes"
      echo "  qname-minimisation-strict: yes"
    } >> $UNBOUND_CONFFILE

  elif [ "$UNBOUND_B_QUERY_MIN" -gt 0 ] ; then
    # Minor improvement on query privacy
    echo "  qname-minimisation: yes" >> $UNBOUND_CONFFILE

  else
    echo "  qname-minimisation: no" >> $UNBOUND_CONFFILE
  fi


  case "$UNBOUND_D_RECURSION" in
    passive)
      {
        echo "  prefetch: no"
        echo "  prefetch-key: no"
        echo "  target-fetch-policy: \"0 0 0 0 0\""
        echo
      } >> $UNBOUND_CONFFILE
      ;;

    aggressive)
      {
        echo "  prefetch: yes"
        echo "  prefetch-key: yes"
        echo "  target-fetch-policy: \"3 2 1 0 0\""
        echo
      } >> $UNBOUND_CONFFILE
      ;;

    *)
      if [ ! -f "$UNBOUND_TIMEFILE" ] ; then
        logger -t unbound -s "default recursion configuration"
      fi
      ;;
  esac


  {
    # Reload records more than 10 hours old
    # DNSSEC 5 minute bogus cool down before retry
    # Adaptive infrastructure info kept for 15 minutes
    echo "  cache-min-ttl: $UNBOUND_TTL_MIN"
    echo "  cache-max-ttl: 36000"
    echo "  val-bogus-ttl: 300"
    echo "  infra-host-ttl: 900"
    echo
  } >> $UNBOUND_CONFFILE


  if [ "$UNBOUND_B_HIDE_BIND" -gt 0 ] ; then
    {
      # Block server id and version DNS TXT records
      echo "  hide-identity: yes"
      echo "  hide-version: yes"
      echo
    } >> $UNBOUND_CONFFILE
  fi


  if [ "$UNBOUND_B_PRIV_BLCK" -gt 0 ] ; then
    {
      # Remove _upstream_ or global reponses with private addresses.
      # Unbounds own "local zone" and "forward zone" may still use these.
      # RFC1918, RFC3927, RFC4291, RFC6598, RFC6890
      echo "  private-address: 10.0.0.0/8"
      echo "  private-address: 100.64.0.0/10"
      echo "  private-address: 169.254.0.0/16"
      echo "  private-address: 172.16.0.0/12"
      echo "  private-address: 192.168.0.0/16"
      echo "  private-address: fc00::/8"
      echo "  private-address: fd00::/8"
      echo "  private-address: fe80::/10"
    } >> $UNBOUND_CONFFILE
  fi


  if [ "$UNBOUND_B_LOCL_BLCK" -gt 0 ] ; then
    {
      # Remove DNS reponses from upstream with loopback IP
      # Black hole DNS method for ad blocking, so consider...
      echo "  private-address: 127.0.0.0/8"
      echo "  private-address: ::1/128"
      echo
    } >> $UNBOUND_CONFFILE

  else
    echo >> $UNBOUND_CONFFILE
  fi


  # Except and accept domains as insecure (DNSSEC); work around broken domains
  config_list_foreach "$cfg" "domain_insecure" create_domain_insecure
  echo >> $UNBOUND_CONFFILE
}

##############################################################################

unbound_access() {
  # TODO: Unbound 1.6.0 added "tags" and "views", so we can add tags to
  # each access-control IP block, and then divert access.
  # -- "guest" WIFI will not be allowed to see local zone data
  # -- "child" LAN can black whole a list of domains to http~deadpixel


  if [ "$UNBOUND_B_LOCL_SERV" -gt 0 ] ; then
    # Only respond to queries from which this device has an interface.
    # Prevent DNS amplification attacks by not responding to the universe.
    config_load network
    config_foreach create_access_control interface


    {
      echo "  access-control: 127.0.0.0/8 allow"
      echo "  access-control: ::1/128 allow"
      echo "  access-control: fe80::/10 allow"
      echo
    } >> $UNBOUND_CONFFILE

  else
    {
      echo "  access-control: 0.0.0.0/0 allow"
      echo "  access-control: ::0/0 allow"
      echo
    } >> $UNBOUND_CONFFILE
  fi


  {
    # Amend your own "server:" stuff here
    echo "  include: $UNBOUND_SRV_CONF"
    echo
  } >> $UNBOUND_CONFFILE
}

##############################################################################

unbound_adblock() {
  # TODO: Unbound 1.6.0 added "tags" and "views"; lets work with adblock team
  local adb_enabled adb_file

  if [ ! -x /usr/bin/adblock.sh -o ! -x /etc/init.d/adblock ] ; then
    adb_enabled=0
  else
    /etc/init.d/adblock enabled && adb_enabled=1 || adb_enabled=0
  fi


  if [ "$adb_enabled" -gt 0 ] ; then
    {
      # Pull in your selected openwrt/pacakges/net/adblock generated lists
      for adb_file in $UNBOUND_VARDIR/adb_list.* ; do
        echo "  include: $adb_file"
      done
      echo
    } >> $UNBOUND_CONFFILE
  fi
}

##############################################################################

unbound_hostname() {
  if [ -n "$UNBOUND_TXT_DOMAIN" ] ; then
    {
      # TODO: Unbound 1.6.0 added "tags" and "views" and we could make
      # domains by interface to prevent DNS from "guest" to "home"
      echo "  local-zone: $UNBOUND_TXT_DOMAIN. $UNBOUND_D_DOMAIN_TYPE"
      echo "  domain-insecure: $UNBOUND_TXT_DOMAIN"
      echo "  private-domain: $UNBOUND_TXT_DOMAIN"
      echo
      echo "  local-zone: $UNBOUND_TXT_HOSTNAME. $UNBOUND_D_DOMAIN_TYPE"
      echo "  domain-insecure: $UNBOUND_TXT_HOSTNAME"
      echo "  private-domain: $UNBOUND_TXT_HOSTNAME"
      echo
    } >> $UNBOUND_CONFFILE


    case "$UNBOUND_D_DOMAIN_TYPE" in
    deny|inform_deny|refuse|static)
      {
        # avoid upstream involvement in RFC6762 like responses (link only)
        echo "  local-zone: local. $UNBOUND_D_DOMAIN_TYPE"
        echo "  domain-insecure: local"
        echo "  private-domain: local"
        echo
      } >> $UNBOUND_CONFFILE
      ;;
    esac


    if [ "$UNBOUND_D_LAN_FQDN" -gt 0 -o "$UNBOUND_D_WAN_FQDN" -gt 0 ] ; then
      config_load dhcp
      config_foreach create_interface_dns dhcp
    fi


    if [ -f "$UNBOUND_DHCP_CONF" ] ; then
      {
        # Seed DHCP records because dhcp scripts trigger externally
        # Incremental Unbound restarts may drop unbound-control add records
        echo "  include: $UNBOUND_DHCP_CONF"
        echo
      } >> $UNBOUND_CONFFILE
    fi
  fi
}

##############################################################################

unbound_records() {
  if [ "$UNBOUND_D_EXTRA_DNS" -gt 0 ] ; then
    # Parasite from the uci.dhcp.domain clauses
    config_load dhcp
    config_foreach create_host_record domain
  fi


  if [ "$UNBOUND_D_EXTRA_DNS" -gt 1 ] ; then
    config_foreach create_srv_record srvhost
    config_foreach create_mx_record mxhost
  fi


  if [ "$UNBOUND_D_EXTRA_DNS" -gt 2 ] ; then
    config_foreach create_cname_record cname
  fi


  echo >> $UNBOUND_CONFFILE
}

##############################################################################

unbound_uci() {
  local cfg="$1"
  local dnsmasqpath hostnm

  hostnm=$( uci_get system.@system[0].hostname | awk '{print tolower($0)}' )
  UNBOUND_TXT_HOSTNAME=${hostnm:-thisrouter}

  config_get_bool UNBOUND_B_SLAAC6_MAC "$cfg" dhcp4_slaac6 0
  config_get_bool UNBOUND_B_DNS64      "$cfg" dns64 0
  config_get_bool UNBOUND_B_EXT_STATS  "$cfg" extended_stats 0
  config_get_bool UNBOUND_B_HIDE_BIND  "$cfg" hide_binddata 1
  config_get_bool UNBOUND_B_LOCL_SERV  "$cfg" localservice 1
  config_get_bool UNBOUND_B_MAN_CONF   "$cfg" manual_conf 0
  config_get_bool UNBOUND_B_QUERY_MIN  "$cfg" query_minimize 0
  config_get_bool UNBOUND_B_QRY_MINST  "$cfg" query_min_strict 0
  config_get_bool UNBOUND_B_PRIV_BLCK  "$cfg" rebind_protection 1
  config_get_bool UNBOUND_B_LOCL_BLCK  "$cfg" rebind_localhost 0
  config_get_bool UNBOUND_B_DNSSEC     "$cfg" validator 0
  config_get_bool UNBOUND_B_NTP_BOOT   "$cfg" validator_ntp 1

  config_get UNBOUND_IP_DNS64    "$cfg" dns64_prefix "64:ff9b::/96"

  config_get UNBOUND_N_EDNS_SIZE "$cfg" edns_size 1280
  config_get UNBOUND_N_RX_PORT   "$cfg" listen_port 53
  config_get UNBOUND_N_ROOT_AGE  "$cfg" root_age 9

  config_get UNBOUND_D_CONTROL     "$cfg" unbound_control 0
  config_get UNBOUND_D_DOMAIN_TYPE "$cfg" domain_type static
  config_get UNBOUND_D_DHCP_LINK   "$cfg" dhcp_link none
  config_get UNBOUND_D_EXTRA_DNS   "$cfg" add_extra_dns 0
  config_get UNBOUND_D_LAN_FQDN    "$cfg" add_local_fqdn 0
  config_get UNBOUND_D_PROTOCOL    "$cfg" protocol mixed
  config_get UNBOUND_D_RECURSION   "$cfg" recursion passive
  config_get UNBOUND_D_RESOURCE    "$cfg" resource small
  config_get UNBOUND_D_WAN_FQDN    "$cfg" add_wan_fqdn 0

  config_get UNBOUND_TTL_MIN     "$cfg" ttl_min 120
  config_get UNBOUND_TXT_DOMAIN  "$cfg" domain lan

  UNBOUND_LIST_DOMAINS="nowhere $UNBOUND_TXT_DOMAIN"

  if [ "$UNBOUND_D_DHCP_LINK" = "none" ] ; then
    config_get_bool UNBOUND_B_DNSMASQ   "$cfg" dnsmasq_link_dns 0


    if [ "$UNBOUND_B_DNSMASQ" -gt 0 ] ; then
      UNBOUND_D_DHCP_LINK=dnsmasq


      if [ ! -f "$UNBOUND_TIMEFILE" ] ; then
        logger -t unbound -s "Please use 'dhcp_link' selector instead"
      fi
    fi
  fi


  if [ "$UNBOUND_D_DHCP_LINK" = "dnsmasq" ] ; then
    if [ ! -x /usr/sbin/dnsmasq -o ! -x /etc/init.d/dnsmasq ] ; then
      UNBOUND_D_DHCP_LINK=none
    else
      /etc/init.d/dnsmasq enabled || UNBOUND_D_DHCP_LINK=none
    fi


    if [ "$UNBOUND_D_DHCP_LINK" = "none" -a ! -f "$UNBOUND_TIMEFILE" ] ; then
      logger -t unbound -s "cannot forward to dnsmasq"
    fi
  fi


  if [ "$UNBOUND_D_DHCP_LINK" = "odhcpd" ] ; then
    if [ ! -x /usr/sbin/odhcpd -o ! -x /etc/init.d/odhcpd ] ; then
      UNBOUND_D_DHCP_LINK=none
    else
      /etc/init.d/odhcpd enabled || UNBOUND_D_DHCP_LINK=none
    fi


    if [ "$UNBOUND_D_DHCP_LINK" = "none" -a ! -f "$UNBOUND_TIMEFILE" ] ; then
      logger -t unbound -s "cannot receive records from odhcpd"
    fi
  fi


  if [ "$UNBOUND_N_EDNS_SIZE" -lt 512 \
    -o 4096 -lt "$UNBOUND_N_EDNS_SIZE" ] ; then
    logger -t unbound -s "edns_size exceeds range, using default"
    UNBOUND_N_EDNS_SIZE=1280
  fi


  if [ "$UNBOUND_N_RX_PORT" -ne 53 ] \
  && [ "$UNBOUND_N_RX_PORT" -lt 1024 -o 10240 -lt "$UNBOUND_N_RX_PORT" ] ; then
    logger -t unbound -s "privileged port or in 5 digits, using default"
    UNBOUND_N_RX_PORT=53
  fi


  if [ "$UNBOUND_TTL_MIN" -gt 1800 ] ; then
    logger -t unbound -s "ttl_min could have had awful side effects, using 300"
    UNBOUND_TTL_MIN=300
  fi
}

##############################################################################

_resolv_setup() {
  if [ "$UNBOUND_N_RX_PORT" != "53" ] ; then
    return
  fi

  if [ -x /etc/init.d/dnsmasq ] && /etc/init.d/dnsmasq enabled \
  && nslookup localhost 127.0.0.1#53 >/dev/null 2>&1 ; then
    # unbound is configured for port 53, but dnsmasq is enabled and a resolver
    #   listens on localhost:53, lets assume dnsmasq manages the resolver file.
    # TODO:
    #   really check if dnsmasq runs a local (main) resolver in stead of using
    #   nslookup that times out when no resolver listens on localhost:53.
    return
  fi

  # unbound is designated to listen on 127.0.0.1#53,
  #   set resolver file to local.
  rm -f /tmp/resolv.conf
  {
    echo "# /tmp/resolv.conf generated by Unbound UCI $( date )"
    echo "nameserver 127.0.0.1"
    echo "nameserver ::1"
    echo "search $UNBOUND_TXT_DOMAIN"
  } > /tmp/resolv.conf
}

##############################################################################

_resolv_teardown() {
  case $( cat /tmp/resolv.conf ) in
  *"generated by Unbound UCI"*)
    # our resolver file, reset to auto resolver file.
    rm -f /tmp/resolv.conf
    ln -s /tmp/resolv.conf.auto /tmp/resolv.conf
    ;;
  esac
}

##############################################################################

unbound_start() {
  config_load unbound
  config_foreach unbound_uci unbound


  unbound_mkdir


  if [ "$UNBOUND_B_MAN_CONF" -eq 0 ] ; then
    unbound_conf
    unbound_access
    unbound_adblock

    if [ "$UNBOUND_D_DHCP_LINK" = "dnsmasq" ] ; then
      dnsmasq_link
    else
      unbound_hostname
      unbound_records
    fi

    unbound_control
  fi


  _resolv_setup
}

##############################################################################

unbound_stop() {
  _resolv_teardown


  rootzone_update
}

##############################################################################
# Some configurations found on the OpenWRT site & LEDE-project site
# for popular DDNS provider services
#The default is to use 'domain' together with 'service_name' set to 'dnsomatic.com'.
# 'domain' needs to be set to FQDN to update/verify. :!: NEVER use 'all.dnsomatic.com'!
# To update all services registered with DNS-O-Matic in one configuration/section use the following settings
### dns-o-matic
service_name	delete / --custom--
update_url	http://[USERNAME]:[PASSWORD]@updates.dnsomatic.com/nic/update?hostname=all.dnsomatic.com&myip=[IP]&wildcard=NOCHG&mx=NOCHG&backmx=NOCHG
domain		[Only ONE of your defined hostnames to verify update was send]
username	[Your username]
password	[Your password]

### duckdns
# Must install SSL
update_url	http://www.duckdns.org/update?domains=[USERNAME]&token=[PASSWORD]&ip=[IP]
domain		[Your FQDN]
username	[Your Host without ".duckdns.org"]
password	[Your token]
use_https	1
cacert		[path to certificate file or directory]


### freedns.afraid.org
# a simple configuration section
service_name	freedns.afraid.org
domain		[Your FQDN]
username	[NOT used. Set to a character of your choice, because LuCI does not accept empty field]
password	[Your authorisation token, NOT your account password]
## To find your authorisation token, go to http://freedns.afraid.org/dynamic/, login, click "Direct URL".
# On the location bar of your browser, copy the authorisation token,
# which is the part after http://freedns.afraid.org/dynamic/update.php? url
# and paste it in the password field.

### he
# simplest setup, lacking documentation on wiki
service_name    he.com
domain      [Your FQDN]
username    [username]
password    [password]
#!/bin/sh
##############################################################################
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# Copyright (C) 2016 Eric Luehrsen
#
##############################################################################
#
# This script facilitates alternate installation of Unbound+odhcpd and no
# need for dnsmasq. There are some limitations, but it works and is small.
# The lease file is parsed to make "zone-data:" and "local-data:" entries.
#
# config odhcpd 'odhcpd'
#   option leasetrigger '/usr/lib/unbound/odhcpd.sh'
#
##############################################################################

# Common file location definitions
. /usr/lib/unbound/unbound.sh

##############################################################################

odhcpd_settings() {
  # This trigger is out of normal init context, so we need to read some UCI.
  local cfg="$1"
  config_get UNBOUND_D_DHCP_LINK  "$cfg" dhcp_link none
  config_get_bool UNBOUND_B_SLAAC6_MAC "$cfg" dhcp4_slaac6 0
  config_get UNBOUND_TXT_DOMAIN "$cfg" domain lan
}

##############################################################################

odhcpd_zonedata() {
  local dns_ls_add=$UNBOUND_VARDIR/dhcp_dns.add
  local dns_ls_del=$UNBOUND_VARDIR/dhcp_dns.del
  local dhcp_ls_new=$UNBOUND_VARDIR/dhcp_lease.new
  local dhcp_ls_old=$UNBOUND_VARDIR/dhcp_lease.old
  local dhcp_ls_add=$UNBOUND_VARDIR/dhcp_lease.add
  local dhcp_ls_del=$UNBOUND_VARDIR/dhcp_lease.del
  local dhcp_origin=$( uci_get dhcp.@odhcpd[0].leasefile )

  config_load unbound
  config_foreach odhcpd_settings unbound


  if [ "$UNBOUND_D_DHCP_LINK" = "odhcpd" -a -f "$dhcp_origin" ] ; then
    # Capture the lease file which could be changing often
    cat $dhcp_origin | sort > $dhcp_ls_new
    touch $dhcp_ls_old
    sort $dhcp_ls_new $dhcp_ls_old $dhcp_ls_old | uniq -u > $dhcp_ls_add
    sort $dhcp_ls_old $dhcp_ls_new $dhcp_ls_new | uniq -u > $dhcp_ls_del

    # Go through the messy business of coding up A, AAAA, and PTR records
    # This static conf will be available if Unbound restarts asynchronously
    awk -v hostfile=$UNBOUND_DHCP_CONF -v domain=$UNBOUND_TXT_DOMAIN \
        -v bslaac=$UNBOUND_B_SLAAC6_MAC -v bisolt=0 -v bconf=1 \
        -f /usr/lib/unbound/odhcpd.awk $dhcp_ls_new

    # Deleting and adding all records into Unbound can be a burden in a
    # high density environment. Use unbound-control incrementally.
    awk -v hostfile=$dns_ls_del -v domain=$UNBOUND_TXT_DOMAIN \
        -v bslaac=$UNBOUND_B_SLAAC6_MAC -v bisolt=0 -v bconf=0 \
        -f /usr/lib/unbound/odhcpd.awk $dhcp_ls_del

    awk -v hostfile=$dns_ls_add -v domain=$UNBOUND_TXT_DOMAIN \
        -v bslaac=$UNBOUND_B_SLAAC6_MAC -v bisolt=0 -v bconf=0 \
        -f /usr/lib/unbound/odhcpd.awk $dhcp_ls_add


    if [ -f "$dns_ls_del" ] ; then
      cat $dns_ls_del | $UNBOUND_CONTROL_CFG local_datas_remove
    fi


    if [ -f "$dns_ls_add" ] ; then
      cat $dns_ls_add | $UNBOUND_CONTROL_CFG local_datas
    fi


    # prepare next round
    mv $dhcp_ls_new $dhcp_ls_old
    rm -f $dns_ls_del $dns_ls_add $dhcp_ls_del $dhcp_ls_add
  fi
}

##############################################################################

odhcpd_zonedata

##############################################################################
###=================== Unbound and odhcpd ======================###
## dnsmasq must be disabled if using this method
## Also must install unbound-control, because the lease records are added and removed without starting, stopping, flushing cache, or re-writing conf files...
# (restart overhead can be excessive with even a few mobile devices.)
# Use editor of choice: vi/nano (or other)
# vi /etc/config/dhcp
nano /etc/config/unbound
...
config unbound
  # name your router in DNS
  option add_local_fqdn '1'
  option add_wan_fqdn '1'
  option dhcp_link 'odhcpd'
  # add SLAAC inferred from DHCPv4
  option dhcp4_slaac6 '1'
  option domain 'lan'
  option domain_type 'static'
  option listen_port '53'
  option rebind_protection '1'
  # install unbound-control and set this
  option unbound_control '1'
  ...
  

nano /etc/config/dhcp
...
config dhcp 'lan'
  option dhcpv4 'server'
  option dhcpv6 'server'
  option interface 'lan'
  option leasetime '12h'
  option ra 'server'
  option ra_management '1'
  # odhcpd should issue ULA [fd00::/8] by default

config odhcpd 'odhcpd'
  option maindhcp '1'
  option leasefile '/var/lib/odhcpd/dhcp.leases'
  # this is where the magic happens
  option leasetrigger '/usr/lib/unbound/odhcpd.sh'
  

############################ Network Configurations
### Depending on how router is being used and for what, configurations will vary
### In this case, I am using a standalone modem and primary router A
###  with a secondary router B that acts as an ethernet (wired) bridge
uci show network # shows current network configuration

# Update a file using vi or nano
vi /etc/

### create a loopback network interface
config interface loopback
    option ifname lo
    option proto static
    option ipaddr 127.0.0.1
    option netmask 255.0.0.0
config interface lan
    option ifname eth0
    option type bridge
    option proto static
    option ipaddr 192.168.1.2
    option netmask 255.255.255.0
    option gateway 192.168.1.1
    option dns 192.168.0.1
    

###----------LAN as Bridge for WIFI -----------###
# Telnet/SSH/SSH2 (least to most secure)
# Run command below to write to interface 'lan'
cat /etc/config/network

### Step 1: find and alter 'lan'
...
config interface 'lan'
        option type 'bridge'
        option ifname 'eth0.1'
        option proto 'static'
        option netmask '255.255.255.0'
        option ip6assign '60'
        option ipaddr '192.168.1.1'
...


### Step 2: change the existing wireless network, 
# use vi/nano to alter wifi:
vi /etc/config/wireless
# Now locate the existing wifi-iface section and make the following changes, making sure to adjust to your specific network needs:
$PASSWORD = ""; $SSID = ""; $DEVICE = "w"
config wifi-device wifi0
    option type atheros
    option country EN
    option channel auto
config wifi-iface
    option device wifi0
    option network lan
    option mode ap
    option ssid $SSID
    option encryption psk2
    option key '$PASSWORD'






#### dns_verify.sh
#
NETS="192.168.10 172.168.20"
IPS=$(seq 1 10)  ## for Linux
#
# IPS=$(jot 254 1)  ## for OpenBSD or FreeBSD
# IPS=$(seq 1 254)  ## for Linux  
#
echo
echo -e "\tip        ->     hostname      -> ip"
echo '--------------------------------------------------------'  
for NET in $NETS; do
  for n in $IPS; do
    A=${NET}.${n}
    HOST=$(dig -x $A +short)
    if test -n "$HOST"; then
      ADDR=$(dig $HOST +short)
      if test "$A" = "$ADDR"; then
        echo -e "ok\t$A -> $HOST -> $ADDR"
      elif test -n "$ADDR"; then
        echo -e "fail\t$A -> $HOST -> $ADDR"
      else
        echo -e "fail\t$A -> $HOST -> [unassigned]"
      fi
    fi
  done
done

echo ""
echo "DONE."
#!/bin/sh

opkg update
opkg install openvpn-openssl luci-app-openvpn
opkg install nano libustream-openssl ca-bundle ca-certificates


# Get the certificate & ovpn file using wget (or curl)
cd /etc/openvpn
wget http://www.ipvanish.com/software/configs/ca.ipvanish.com.crt
wget https://www.ipvanish.com/software/configs/ipvanish-US-Los-Angeles-lax-a01.ovpn



# Use nano to add username & url-encoded password the downloaded OVPN file 
Next, I took the instructions from the following site: https://github.com/jlund/streisand/wiki/Setting-an-OpenWrt-Based-Router-as-OpenVPN-Client

# a new OpenVPN instance:
uci set openvpn.provider=openvpn
uci set openvpn.provider.enabled='1'
uci set openvpn.provider.config='/etc/openvpn/ipvanish-US-Los-Angeles-lax-a01.ovpn'
# NOTE: use whatever your file is above

###--------- Add user login info --------
nano ipvanish-US-Los-Angeles-lax-a01.ovpn
# Modify the line that says: auth-user-pass and make it look like this:
auth-user-pass /tmp/auth.conf
# Also, add the following line somewhere to force the openvpn client to route traffic over this tunnel
redirect-gateway def1
# Press “Ctrl-X” to exit, and Y to save when prompted

# Next we need to create the user/password file mentioned above:

touch /tmp/auth.conf
echo "YOUR_VPN_USER_NAME" > /tmp/auth.conf
echo "YOUR_VPN_PASSWORD" >> /tmp/auth.conf


### Adding configuration 


# a new network interface for tun:
uci set network.providervpn=interface
uci set network.providervpn.proto='none' #dhcp #none
uci set network.providervpn.ifname='tun0'

# a new firewall zone (for VPN):
uci add firewall zone
uci set firewall.@zone[-1].name='vpn'
uci set firewall.@zone[-1].input='REJECT'
uci set firewall.@zone[-1].output='ACCEPT'
uci set firewall.@zone[-1].forward='REJECT'
uci set firewall.@zone[-1].masq='1'
uci set firewall.@zone[-1].mtu_fix='1'
uci add_list firewall.@zone[-1].network='providervpn'

# enable forwarding from LAN to VPN:
uci add firewall forwarding
uci set firewall.@forwarding[-1].src='lan'
uci set firewall.@forwarding[-1].dest='vpn'

# Finally, you should commit UCI changes:
uci commit
#!/bin/sh

if wget -q --spider https://lede-project.org/start; then  # if LEDE website/wiki is available we update
  echo "You are connected to the internet. Checking for updates, please wait..." && echo
  opkg update > /dev/null 2>&1 #silenced standard output and error output

  opkgInstalled="$(opkg list-installed 2> /dev/null | wc -l)" #silencing error output
  opkgUpgradable="$(opkg list-upgradable 2> /dev/null | wc -l)" #silencing error output

  echo "$opkgInstalled packages are installed." && echo "$opkgUpgradable packages can be upgraded." && echo
  
  memLimit=32000 # in bytes
  if [ "$(grep MemFree /proc/meminfo | awk '{print$2}')" -lt $memLimit ]; then
    for opkg_package_lists in /var/opkg-lists/*
    do
      if [ -f "$opkg_package_lists" ]; then #prevent error if opkg update fails
        rm -r /var/opkg-lists/*
        echo "Warning: Memory limit $memLimit bytes. Removed downloaded package lists to save memory."
        echo #only remove when free RAM is less than set memory limit (default 32 MiB)
      fi
    done
  fi
  else
  echo "You are not connected to the internet. Unable to check for updates." && echo
fi
### IMPORTANT: make sure to run the update command 

#!/bin/sh

opkgInstalled="$(opkg list-installed 2> /dev/null | wc -l)" #silencing error output
opkgUpgradable="$(opkg list-upgradable 2> /dev/null | wc -l)" #silencing error output

echo "$opkgInstalled packages are installed." && echo "$opkgUpgradable packages can be upgraded." && echo

# use command below to write to profile
# nano ./profile 

README

Network scripts for powershell, batch and command line, as well as configurations to use for LEDE (can also be used on OpenWRT).

This README also includes tools to update DDNS & other network utilities.

DDNS Update Clients

Dynamic DNS/Tunnelbroker services:

List of Programs for Servers/Clients

LEDE/OpenWRT References

Below is a list of tutorials/docs for setting up a router running LEDE firmeware.

An initial tutorial on setting up a Bridged AP.

Official Site for LEDE project

OpenWRT & Other Docs

Tools for Checking Network Configuration(s)

Startup Scripts

BIND & Unbound

Recursive, validating & & authoritative serving DNS solutions. Add some of the scripts copied below into the appropriate paths.

The architecture:

                  INTERNET DNS
                       |
                       |
                -- Unbound #1 --
              /                  \   private authoritative only
LAN Clients -- --- Unbound #2 --  --   BIND or NSD dns server
              \                  /        ( 10.0.0.111 )
                -- Unbound #3 --

Step 1:

To query hostname, Unbound starts at top fo root DNS servers & works way down to authoritative servers. IN the process, it uses a file containing them for hints, placed in /var/unbound/etc/root.hints.

Obtain file:

wget ftp://FTP.INTERNIC.NET/domain/named.cache -O /var/unbound/etc/root.hints

Step 2:

Auto-trust-anchor-file: which contains the key for the root server so DNSSEC can be validated. We need to tell Unbound that we trust the root server so it can start to develop a chain of trust down to the hostname we want resolved and validated using DNSSEC.

Create file in "/var/unbound/etc/root.key", placing following line & verifying root zone anchor by going to the IANA index of root-anchors.

. IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5

Step 3:

Make sure Unbound is installed, then place the following unbound.conf in place of own.

Location on OpenBSD: /var/unbound/etc/unbound.conf