Refactoring for travis, make

pull/18/head
Hugo Landau 8 years ago
parent 217e831b6e
commit f2741ec585

@ -1,12 +1,24 @@
language: go
go:
- 1.5
- tip
before_install:
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then travis_retry sudo apt-get update -qq; fi
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then travis_retry sudo apt-get install -y libcap-dev; fi
notifications:
irc:
channels:
- "chat.freenode.net##hl-t"
skip_join: true
- 1.5.2
addons:
apt:
packages:
- libcap-dev
- gcc-multilib
- libc6-dev:i386
- libcap-dev:i386
sudo: false
install:
- go get -v -t ./...
script:
- source ./.travis/script
after_success:
- source ./.travis/after_success
env:
# GITHUB_TOKEN for automatic releases
- secure: "at1oJs7ib7glx3W+zk+OkT041LdknVXirIhN403CIihVUrlOhODY7yCTgvF4Rk0jYBJiT35Q2qxpgfWF2qGnsNsQmjG3ydDWQDCepDc/CgXfLyoiSTJK5vTK72dYWTVsBTycXbj1CbSy2X2ah/KWjc4RcgZ67ER7mDpRU5nFeow="

@ -0,0 +1,32 @@
#!/bin/bash
# Only upload version tags.
if ! [[ "$TRAVIS_TAG" =~ ^v[0-9] ]]; then
echo Skipping release upload because this build is not for a release tag.
return 0
fi
if [ -z "$GITHUB_TOKEN" ]; then
echo "Don't appear to have GitHub token, cannot continue."
return 0
fi
# Make archives.
echo Archiving releases...
SRC_DIR="$(pwd)"
cd "$GOPATH/releasing/idist"
for x in *; do
echo "$x"
cp "$GOPATH/src/github.com/$TRAVIS_REPO_SLUG/.travis/dist-readme.md" "$x"/README.md || \
cp "$GOPATH/src/github.com/$TRAVIS_REPO_SLUG/README.md" "$x/" || true
tar -zcf "../dist/$(basename "$x").tar.gz" "$x"
done
# Must be in the right directory when calling ghr.
cd "$SRC_DIR"
echo Uploading releases...
TRAVIS_REPO_OWNER="$(echo "$TRAVIS_REPO_SLUG" | sed 's#/.*$##g')"
travis_retry ghr -u "$TRAVIS_REPO_OWNER" "$TRAVIS_TAG" "$GOPATH/releasing/dist/"
echo Done

@ -0,0 +1,34 @@
#!/bin/bash
go test -v ./...
RESULT=$?
echo Done tests with exit code $RESULT
if [ "$RESULT" != "0" ]; then
return $RESULT
fi
# Test cross-compilation. The binaries produced are also used for release
# upload in after_success if this is a release tag.
echo Cross-compiling releases...
mkdir -p "$GOPATH/releasing/idist" "$GOPATH/releasing/dist"
# cgo crosscompile
REPOS="github.com/$TRAVIS_REPO_SLUG"
gox -cgo -osarch 'linux/386 linux/amd64' -output "$GOPATH/releasing/idist/{{.Dir}}-$TRAVIS_TAG-{{.OS}}_{{.Arch}}/bin/x" $REPOS
RESULT1=$?
# non-cgo crosscompile
gox -osarch 'darwin/386 darwin/amd64 linux/arm freebsd/386 freebsd/amd64 freebsd/arm openbsd/386 openbsd/amd64 netbsd/386 netbsd/amd64 netbsd/arm dragonfly/amd64 solaris/amd64' -output "$GOPATH/releasing/idist/{{.Dir}}-$TRAVIS_TAG-{{.OS}}_{{.Arch}}/bin/x" $REPOS
RESULT2=$?
echo cgo crosscompile exited with code $RESULT1
echo non-cgo crosscompile exited with code $RESULT2
if [ "$RESULT1" != "0" ]; then
return $RESULT1
fi
if [ "$RESULT2" != "0" ]; then
return $RESULT2
fi

@ -0,0 +1,85 @@
PROJNAME=github.com/hlandau/ncdns
BINARIES=$(PROJNAME) $(PROJNAME)/ncdt $(PROJNAME)/ncdumpzone
###############################################################################
# v1.8 NNSC:github.com/hlandau/degoutils/_stdenv/Makefile.ref
# This is a standard Makefile for building Go code designed to be copied into
# other projects. Code below this line is not intended to be modified.
-include Makefile.extra
-include Makefile.assets
## Paths
ifeq ($(GOPATH),)
# for some reason export is necessary for FreeBSD's gmake
export GOPATH := $(shell pwd)
endif
ifeq ($(GOBIN),)
export GOBIN := $(GOPATH)/bin
endif
ifeq ($(PREFIX),)
export PREFIX := /usr/local
endif
DIRS=src bin public
## Quieting
Q=@
QI=@echo -e "\t[$(1)]\t $(2)";
ifeq ($(V),1)
Q=
QI=
endif
## Buildinfo
BUILDNAME?=$(shell date -u "%Y%m%d%H%M%S") on $(shell hostname -f)
BUILDINFO=$(shell (echo built $(BUILDNAME); go list -f '{{range $$imp := .Deps}}{{printf "%s\n" $$imp}}{{end}}' $(1) | sort -u | xargs go list -f '{{if not .Standard}}{{.ImportPath}}{{end}}' | awk "{print \"$$GOPATH/src/\" \$$0}" | (while read line; do x="$$line"; while [ ! -e "$$x/.git" -a ! -e "$$x/.hg" ]; do x=$${x%/*}; if [ "$$x" = "" ]; then break; fi; done; echo "$$x"; done) | sort -u | (while read line; do echo git $${line\#$$GOPATH/src/} $$(git -C "$$line" rev-parse HEAD) $$(git -C "$$line" describe --all --dirty=+ --abbrev=99 --always); done)) | base64 -w 0)
BUILDINFO_FLAG=
ifeq ($(USE_BUILDINFO),1)
BUILDINFO_FLAG= -ldflags "-X github.com/hlandau/degoutils/buildinfo.RawBuildInfo=$(call BUILDINFO,$(1))"
endif
## Standard Rules
all: prebuild-checks $(DIRS)
$(call QI,GO-INSTALL,$(BINARIES))go install $(BUILDFLAGS) $(call BUILDINFO_FLAG,$(BINARIES)) $(BINARIES)
prebuild-checks:
$(call QI,RELOCATE)if [ `find . -iname '*.go' | grep -v ./src/ | wc -l` != 0 ]; then \
if [ -e "$(GOPATH)/src/$(PROJNAME)/" ]; then \
echo "$$GOPATH/src/$(PROJNAME)/ already exists, can't auto-relocate. Since you appear to have a GOPATH configured, just use go get -u '$(PROJNAME)/...; go install $(BINARIES)'. Alternatively, move this Makefile to either GOPATH or an empty directory outside GOPATH (preferred) and run it. Or delete '$$GOPATH/src/$(PROJNAME)/'."; \
exit 1; \
fi; \
mkdir -p "$(GOPATH)/src/$(PROJNAME)/"; \
for x in ./* ./.*; do \
[ "$$x" == "./src" ] && continue; \
mv -n "$$x" "$(GOPATH)/src/$(PROJNAME)/"; \
done; \
ln -s "$(GOPATH)/src/$(PROJNAME)/Makefile"; \
[ -e "$(GOPATH)/src/$(PROJNAME)/_doc" ] && ln -s "$(GOPATH)/src/$(PROJNAME)/_doc" doc; \
fi; \
exit 0
$(DIRS): | .gotten
$(call QI,DIRS)mkdir -p $(GOPATH)/src $(GOBIN); \
if [ ! -e "src" ]; then \
ln -s $(GOPATH)/src src; \
fi; \
if [ ! -e "bin" ]; then \
ln -s $(GOBIN) bin; \
fi
.gotten:
$(call QI,GO-GET,$(PROJNAME))go get $(PROJNAME)/...
$(Q)touch .gotten
.NOTPARALLEL: prebuild-checks $(DIRS)
.PHONY: all test install prebuild-checks
test:
$(call QI,GO-TEST,$(PROJNAME))for x in $(PROJNAME); do go test -cover -v $$x/...; done
install: all
$(call QI,INSTALL,$(BINARIES))for x in $(BINARIES); do \
install -Dp $(GOBIN)/`basename "$$x"` $(DESTDIR)$(PREFIX)/bin; \
done

@ -0,0 +1,149 @@
ncdns
=====
A Go daemon to bridge Namecoin to DNS. The daemon acts as an authoritative
nameserver and queries a Namecoin daemon over JSON-RPC in order to obtain zone
data.
The daemon can optionally sign zones with DNSSEC and supports the use of DS
records in Namecoin. It works best when used by Unbound or another recursive
resolver, or as an authoritative nameserver for a stub zone.
Using ncdns to provide a suffix
-------------------------------
The daemon acts as an authoritative nameserver for any name containing a 'bit'
label. For example, all of the following queries return the same records:
- example.bit.
- example.bit.example.com.
This enables the easy use of suffixes. (Note that this will cause a different
hostname to be transmitted for protocols like HTTP, and server configuration
may need to be modified to enable this. In some cases there may be no simple
solution to enabling arbitrary suffix use with a given piece of server
software, in which known suffixes can be configured; patches for such software
would be desirable.)
Using ncdns with a recursive resolver
-------------------------------------
Of course the daemon can also be used simply as an authoritative nameserver for
bit. directly. One way to do this is to run a recursive resolver (such as
Unbound) and configure it to serve the zone as a 'stub zone'. Here is an example
unbound configuration:
server:
do-not-query-localhost: no
stub-zone:
name: bit.
stub-addr: 127.0.0.1@1153
If you don't want to use DNSSEC, also add:
server:
domain-insecure: bit.
If you do want to use DNSSEC, see the instructions below.
Note how you can specify a port other than 53. This allows you to run both
Unbound and ncdns on the same machine. Alternately, you could add an additional
loopback IP address (127.0.0.2) and bind ncdns to that. This is useful if your
recursive resolver doesn't support a port number other than 53.
Using DNSSEC
------------
To use DNSSEC, generate keys with `dnssec-keygen` or `ldns-keygen`. You will need
to generate a key-signing key and a zone-signing key:
# Generate KSK.
$ dnssec-keygen -a RSASHA256 -3 -b 2048 -f KSK bit
# Generate ZSK.
$ dnssec-keygen -a RSASHA256 -3 -b 2048 bit
Each of these commands will generate a pair of files, a `.key` file and a
`.private` file. Make a note of which is the KSK and which is the ZSK. If you
forget, check the comments inside the .key file. (If there are no comments for
some reason, a KSK usually contains the string `DNSKEY 256` and a ZSK
`DNSKEY 257`.)
(You could substitute something else for `bit` as ncdns doesn't care. However
if you want to use the key as a trust anchor with a recursive resolver such as
unbound, you should specify `bit`.)
If using Unbound as a recursive resolver, you should add the KSK's public key file
as a trust anchor to unbound like so:
server:
trust-anchor-file: "/etc/unbound/keys/bit.key"
`bit.key` should be the file containing the KSK DNSKEY (or DS) which ncdns is
configured to use.
Building
--------
On non-Windows platforms:
1. Ensure you have the Go tools installed.
2. If using Linux, ensure you have the `libcap` development headers
installed. (Most distributions will have a package called `libcap-dev` or
similar.)
3. Run `make`. The source repository will be retrieved via `go get`
automatically. You must have the Go compiler tools installed.
On Windows platforms:
1. Ensure you have the Go tools installed.
2. Ensure you have the GOPATH environment variable set. (For those not not
familar with Go, setting it to the path to an empty directory will suffice.
The directory will be filled with build files.)
3. Run `go get github.com/hlandau/ncdns`. The ncdns source code will be
retrieved automatically and ncdns will be built. The binary will be at
$GOPATH/bin/ncdns.
ncdns can be run as a Windows service; see the output of `ncdns --help`.
Configuration
-------------
ncdns uses a configuration file which is looked for at `../etc/ncdns.conf`
(relative to the executable path) and `/etc/ncdns/ncdns.conf`. You can override
this and all options on the command line. An annotated example configuration
file `ncdns.conf.example` is available in doc.
You will need to setup a `namecoind`, `namecoin-qt` or compatible Namecoin node
and enable the JSON-RPC interface. You will then need to provide `ncdns` with
the address of this interface and any necessary username and password via the
configuration file.
If you only want to resolve .bit names yourself, here is a suggested setup on
Linux:
- Install `namecoind` (or `namecoin-qt`) and set it to start automatically
at boot or login. Set up the JSON-RPC interface and make sure it works
by making a test query: `namecoind name_show d/example`.
- Write a ncdns configuration file and set ncdns up to start at boot.
Since Unbound will tie up port 53, set a different port (ideally one >=1024,
so it needn't be run as root.) Test that ncdns works by trying to resolve
a `.bit` domain. If you want to use DNSSEC, generate keys as shown above
and configure ncdns appropriately.
- Install and setup the Unbound recursive resolver on your system. Set it up
to start at boot. See above for configuration suggestions. If you wish to
use DNSSEC, add the ncdns DNSKEY to Unbound as a trust anchor as shown
above. (Make sure Unbound listens only on localhost.)
- Edit `/etc/resolv.conf` to point to the Unbound resolver at 127.0.0.1.
(If this file is generated automatically via DHCP or similar, you may
find these changes keep getting wiped out. Either reconfigure whatever
keeps overwriting it to stop doing so, or, as a stopgap measure, make
the file immutable using `chattr +i`.)
Licence
-------
Licenced under the GPLv3 or later.
© 2014-2015 Hugo Landau <hlandau@devever.net>

@ -0,0 +1,112 @@
### ncdns will look for its configuration file in the following directories.
### The first configuration file found is used and all others are ignored.
###
### /etc/ncdns/ncdns.conf ) Non-Windows only
### /etc/ncdns.conf )
### (executable path)/ncdns.conf
### (executable path)/../etc/ncdns/ncdns.conf
### (executable path)/../etc/ncdns.conf
###
### You may explicitly specify a path to the configuration file on the
### command line by passing '-conf=PATH'.
[ncdns]
### This is a TOML configuration file. Values must be in quotes where shown.
### Basic Settings (Required)
### -------------------------
### The interface to bind to. Defaults to ":53", which causes ncdns to attempt to
### bind to all interfaces on port 53. Unless you are running ncdns as root you
### will probably find that this fails. On Linux, you can run the following
### command on the ncdns binary to authorize it to bind to ports under 1024.
###
### sudo setcap 'cap_net_bind_service=+ep' ./ncdns
###
### On BSD, there are sysctls to disable the low port restrictions.
###
### IMPORTANT NOTE: For Go versions 1.5.0 and 1.5.1 (but not 1.4.x or earlier
### or 1.5.2 when released, or any later version, or HEAD) there is a bug which
### means ncdns cannot listen on privileged ports on Linux systems. This bug
### manifests as ncdns hanging once executed without ever beginning to serve
### requests. This bug will manifest whenever ncdns is executed as root or with
### a non-empty capability set, so it precludes use of setcap to bind to privileged
### ports just as it precludes the use of conventional privilege dropping.
###
#bind="127.0.0.1:53"
### namecoind access (Required)
### ---------------------------
### You must configure the RPC address, username and password ## of a trusted
### (i.e. local) namecoind instance.
### The address, in "hostname:port" format, of the Namecoin JSON-RPC interface.
#namecoinrpcaddress="127.0.0.1:8336"
### The username with which to connect to the Namecoin JSON-RPC interface.
#namecoinrpcusername="user"
### The password with which to connect to the Namecoin JSON-RPC interface.
#namecoinrpcpassword="password"
### ncdns caches values retrieved from Namecoin. This value limits the number of
### items ncdns may store in its cache. The default value is 100.
#cachemaxentries=150
### Nameserver Identity (Optional)
### ------------------------------
### ncdns needs to be able to state the hostname and IP address at which the
### nameserver lies. If you are only using ncdns locally you can avoid configuring
### these.
###
### If SelfName is specified, ncdns lists the name specified as an NS record at
### the zone apex:
###
### bit. IN NS ns1.example.com.
###
### This requires that you be able to assign the ncdns instance a hostname.
###
### If SelfName is left blank (the default), ncdns will generate an internal
### psuedo-hostname under the zone, which will resolve to the value of SelfIP.
###
### The default value of SelfIP is the bogus IP of "127.127.127.127", which will
### work acceptably in some cases (e.g. with Unbound).
#selfname="ns1.example.com."
#selfip="192.0.2.1"
### DNSSEC (Optional)
### -----------------
### The following options concern DNSSEC and are optional.
### Leaving them all blank will disable DNSSEC.
### Path to the file containing the KSK public key.
#publickey="etc/Kbit.+008+12345.key"
### Path to the file containing the KSK private key.
#privatekey="etc/Kbit.+008+12345.private"
### Path to the file containing the ZSK public key.
#zonepublickey="etc/Kbit.+008+12345.key"
### Path to the file containing the ZSK private key.
#zoneprivatekey="etc/Kbit.+008+12345.private"
### HTTP server (Optional)
### ----------------------
### Use of the HTTP server is optional.
### Set this to enable the HTTP server. If you leave this blank, the HTTP
### server will not be enabled.
#httplistenaddr=":8202"
### The template directory is usually detected automatically. If it cannot be found
### automatically, you must set the full path to it here manually. Paths will be
### interpreted relative to the configuration file.
#tplpath="../tpl"

@ -0,0 +1,110 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<!-- This is the information page for {{.CanonicalSuffix}}. You should not use it unless you
are running a service endorsed by {{.CanonicalSuffix}}. If you want to run your own service,
you should change all references to {{.CanonicalSuffix}}. -->
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Namecoin DNS</title>
<style type="text/css">
body { margin: 0; padding: 0; }
.lookup-form { max-width: 53em;
background-color: #D0D0D0;
box-shadow: 0.4em 0.4em 0 #000000;
font-family: monospace;
float: right;
margin-right: 1em;
}
.lookup-form p { margin-bottom: 0; }
.lookup-form fieldset {
border: solid #A0A0A0;
border-width: 14px 7px 7px 7px;
margin: 0;
}
.lookup-form legend {
background-color: #C0C0C0;
xcolor: #FFFFFF;
font-weight: bold;
}
.lookup-form input[type="text"] {
font-family: monospace;
}
#logo {
transform: rotate(90deg) translateY(-4em) translateX(1.5em);
transform-origin: left top;
display: inline-block;
position: absolute;
top: 0;
left: 0;
opacity: .1;
user-select: none;
-moz-user-select: none;
cursor: default;
}
#logo > div {
font-family: "Trebuchet MS", sans-serif;
font-size: 4em;
text-shadow: 1px -1px #000000;
}
#logo1 {
color: #111111;
text-shadow: 1px -1px #000000;
}
#logo2, #logo3 {
color: #666666;
}
#main {
padding: 1em;
padding-left: 3.5em;
}
#statusline {
font-size: small;
padding-top: 1em;
}
.rv { background-color: #E0E0E0; }
.jsonField { width: 100%; box-sizing: border-box; }
#navbar {
background-color: #dddddd;
padding-left: 3.15em;
}
#navbar ul, #navbar ul li { list-style: none; margin: 0; padding: 0; }
#navbar ul li { display: inline-block; }
#navbar ul li a { display: block; padding: 0.2em 0.5em 0.2em 0.5em; text-decoration: none; color: #000000; }
#navbar ul li a:hover {
color: #666666; }
#imain { min-height: 80vh; }
.testnotice {
border: solid 0.5em #FF0000;
background-color: #FFDDDD;
padding: 1em;
margin-bottom: 0.5em;
font-weight: bold;
font-size: 1.2em;
}
</style>
</head>
<body>
<div id="logo"><div>
{{.CanonicalSuffixHTML}}
</div></div>
<div id="navbar">
<ul>
<li><a href="/">{{.CanonicalSuffix}}</a></li>
<li><a href="/lookup">Lookup Domain or Validate JSON</a></li>
</ul>
</div>
<div id="main">
<div id="imain">
{{template "Main" .}}
</div>
<div id="statusline">
Served by {{.SelfName}} at {{.Time}}
</div>
</div>
</body>
</html>

@ -0,0 +1,50 @@
{{define "Main"}}
<form method="POST" action="/lookup" class="lookup-form">
<fieldset>
<legend>Check a domain name</legend>
<input type="text" name="q" value="{{.Query}}" autofocus="autofocus" placeholder="Enter domain name in form d/example or example.bit" size="67" required="required" maxlength="67" pattern="^(d/[a-z0-9_-]+|[a-z0-9_-]+\.bit\.?)$" x-moz-errormessage="Must be in the form d/example or example.bit." />
<input type="submit" value="Lookup Domain" />
<p>To specify the JSON to validate rather than looking it up via Namecoin, specify it below. (You must still specify the name for the purposes of relative name lookup.)</p>
<textarea name="value" class="jsonField" rows="10">{{.JSONValue}}</textarea>
</fieldset>
</form>
{{if .Query}}
<pre>
{{if .NameParseError}}
Invalid name: {{.Query}}
{{else}}
Namecoin Name: <span class="rv">{{.NamecoinName}}</span>
Domain Name: <span class="rv">{{.DomainName}}</span>
Bare Name: <span class="rv">{{.BareName}}</span>
Exists: {{if .ExistenceError}}{{.ExistenceError}}{{else}}Yes{{end}}
{{if not .ExistenceError}}Expired: {{.Expired}}{{end}}
{{if not .ExistenceError}}
Valid: {{.Valid}}
Raw Value:
<span class="rv">{{.Value}}</span>
{{if .ParseErrors}}
Parse Errors:{{range .ParseErrors}}
{{.}}{{end}}
{{end}}{{if .ParseWarnings}}
Parse Warnings:{{range .ParseWarnings}}
{{.}}{{end}}
{{end}}
{{.NCValue}}
{{if .Advanced}}
Parsed Value: {{.NCValueFmt | printf "%# v"}}
{{end}}
RRs:{{range .RRs}}
<span class="rv">{{.}}</span>{{end}}
{{if .RRError}}
RR Generation Error: {{.RRError}}
{{end}}
{{end}}
{{end}}
</pre>
{{end}}
{{end}}

@ -0,0 +1,165 @@
{{define "Main"}}<h1>Namecoin DNS Services</h1>
<p><strong>Access any Namecoin .bit domain by appending "{{.TLD}}".</strong> For example, <em>example.bit</em> becomes <em>example.{{.CanonicalSuffix}}</em>. <a href="#caveats">Caveats.</a></p>
<a name="lookup"></a>
<form method="GET" action="/lookup" class="lookup-form">
<fieldset>
<legend>Check a domain name</legend>
<input type="text" name="q" value="" placeholder="Enter domain name in form d/example or example.bit" size="67" required="required" maxlength="67" pattern="^(d/[a-z0-9_-]+|[a-z0-9_-]+\.bit\.?)$" x-moz-errormessage="Must be in the form d/example or example.bit." />
<input type="submit" value="Lookup Domain" />
<p>You can use this lookup tool to check the validity of a domain's configuration.</p>
<p>Other tools: <a href="/lookup">Validate JSON</a></p>
</fieldset>
</form>
<p>{{.CanonicalSuffix}} provides public Namecoin authoritative DNS services. The nameservers it provides can be used
to convert domain names into Namecoin suffixes, or directly to query the .bit zone.</p>
<ol>
<li><p>The {{.CanonicalSuffix}} nameservers are authoritative for the .bit zone. For example:</p>
<pre>$ dig A nf.bit. @{{.SelfName}}
94.23.252.190</pre>
<p>You can use the nameservers in this mode by configuring a suitable DNS resolver.
Unbound is recommended due to its support for {{if .HasDNSSEC}} DNSSEC and {{end}} configurable
stub zones. <a href="#unbound">See how to configure Unbound.</a></p>
</li>
<li><p>The {{.CanonicalSuffix}} nameservers are authoritative for any matching suffix. A suffix matches
if it contains the label "bit". Such suffixes are automatically aliased to the "bit" zone.
For example, "example.{{.CanonicalSuffix}}" is equivalent to "example.bit", but because it uses an ICANN TLD,
it can be accessed without prior configuration.</p>
<p>Since the {{.CanonicalSuffix}} nameservers automatically recognise any suffix containing the label "bit", you
can convert any suitable name (of the form bit.<em>tld</em>, or rather more verbosely bit.<em>yourdomain.tld</em>) to a .bit suffix by changing its nameservers to those of {{.CanonicalSuffix}}.</p>
<p>There are a number of caveats to this mode of operation; see <a href="#caveats">Caveats</a>.</p>
</li>
</ol>
<p>Both of these modes of operation require you to trust the <em>{{.CanonicalSuffix}}</em> operator (and the operator of {{.TLD}}, and ICANN, etc.); see <a href="#caveats">Caveats</a>.</p>
<a name="ns"></a>
<h2>Nameservers</h2>
<p>The following nameservers are provided for public use in the modes described above:</p>
<ol>
{{range .CanonicalNameservers}}
<li>{{.}}</li>
{{end}}
</ol>
<a name="unbound"></a>
<h2>Configuring Unbound</h2>
<p>The following is an example of the directives which should be placed in an Unbound configuration file:</p>
<pre>server:
# (other directives omitted){{if .HasDNSSEC}}
trust-anchor-file: "/etc/unbound/keys/{{.CanonicalSuffix}}.key"{{end}}
stub-zone:
name: bit.
{{range .CanonicalNameservers}} stub-host: {{.}}
{{end}} stub-prime: yes</pre>
{{if .HasDNSSEC}}<p>You will need to place the {{.CanonicalSuffix}} trust anchor (a DS record) in <code>/etc/unbound/keys/{{.CanonicalSuffix}}.key</code>. See <a href="#dnssec">DNSSEC</a>.</p>{{end}}
<p>See the <a href="http://www.unbound.net/">Unbound</a> documentation for information on setting up Unbound.</p>
<a name="caveats"></a>
<h2>Caveats</h2>
<p>Using a suffix has the following caveats:</p>
<ul>
<h3>Operational Caveats</h3>
<li>Due to the use of virtual hosting, some websites may not work correctly with a suffix as they may
not recognise the hostname as that of the desired website. This can be rectified by the website operator via appropriate configuration, as most common webservers support the specification of virtual hostnames using regexes. See <a href="#www-config">Webserver Configuration</a>.</li>
<li>Namecoin domains which delegate to nameservers are highly unlikely to work with a suffix, unless such nameservers have been specially modified to recognise .bit suffixes. For most nameserver software, this would require a patch, and this in itself is not feasible for those using hosted DNS services. However, domains which delegate to nameservers are currently rare. No patches are yet available.</li>
<h3>Trust Caveats</h3>
<li><p>Since the {{.CanonicalSuffix}} service is a central service, it is subject to attack, control and usurpation. Use of the {{.CanonicalSuffix}} service does not and cannot offer you the same level of trust and certainty of name data that is provided by using your own Namecoin node and DNS resolution daemon. As such, <strong>the {{.CanonicalSuffix}} service is suitable for low-security applications only</strong> (whether used in .bit or suffix mode).</p>
<p>Since {{.CanonicalSuffix}} supports <a href="#dnssec">DNSSEC</a>, you can however at the very least protect yourself from MitM attacks against {{.CanonicalSuffix}}. This requires you to use a validating resolver such as <a href="http://www.unbound.net/">Unbound</a> (<a href="#unbound">configuration example</a>).</p> If you do this, then the risks inherent in the use of the {{.CanonicalSuffix}} are limited to the following threats:</p>
<ol>
<h4>False Name Attacks</h4>
<li>The operator of {{.CanonicalSuffix}} starts acting maliciously or otherwise begins serving false name information.</li>
<li>The operator of the {{.TLD}} TLD usurps control of the {{.CanonicalSuffix}} domain and changes the nameservers and DNSSEC keys registered for the domain. They then start executing attack no. 1.</li>
<li>The operator of the root zone (IANA/ICANN), a court, a law enforcement authority or a government applies pressure or successfully coerces or legally or contractually obliges the operator of the {{.TLD}} TLD to execute attack no. 2.</li>
<li>The {{.CanonicalSuffix}} nameservers become compromised and this access is used to make them serve false name data.</li>
<li>The organizations proviing hosting for the {{.CanonicalSuffix}} nameservers decide to execute attack 5.</li>
<h4>Denial of Service Attacks</h4>
<li>The operator of {{.CanonicalSuffix}} ceases operating, thus preventing use of the {{.CanonicalSuffix}} suffix or the {{.CanonicalSuffix}} nameservers.</li>
<li>The operator of the {{.TLD}} TLD suspends the {{.CanonicalSuffix}} domain, thus preventing use of the {{.CanonicalSuffix}} suffix.</li>
<li>The operator of the root zone (IANA/ICANN), a court, a law enforcement authority or a government applies pressure or successfully coerces or legally or contractually obliges the operator of the {{.TLD}} TLD to execute attack no. 6.</li>
<li>The {{.CanonicalSuffix}} service is placed under a resource consumption denial of service attack (i.e. bandwidth consumption or CPU consumption).</li>
<li>An ISP or other network provider is compelled to blackhole or otherwise intercept traffic to the {{.CanonicalSuffix}} nameservers.</li>
<li>All organizations providing hosting for all {{.CanonicalSuffix}} nameservers decide to terminate service to those nameservers, possibly due to compulsion by another entity.</li>
<h4>Privacy Attacks</h4>
<li>The operator of {{.CanonicalSuffix}} begins logging requests made<!---->.</li>
<li>An ISP or other network provider begins logging requests made to the {{.CanonicalSuffix}} nameservers.</li>
<li>The {{.CanonicalSuffix}} nameservers become compromised and they are reconfigured to begin logging requests made; these logs are then transferred to the attacker.</li>
<h4>Stale Data Attacks</h4>
<li>The Namecoin nodes used to provide data to the {{.CanonicalSuffix}} nameservers are Sybilled or otherwise prevented from communicating with the Namecoin network. Thus new name data is no longer seen, and old name data for all names is sustained perpetually.</li>
<h4>Other</h4>
<li>Of course, all attacks applicable to Namecoin itself also apply.</li>
</ol>
<p>The necessarily trusted parties in terms of False Name attacks are therefore the {{.CanonicalSuffix}} operators, the organizations providing hosting for the {{.CanonicalSuffix}} nameservers, the {{.TLD}} TLD registry (which doubles as the registrar) and ICANN/IANA, but also all courts, law enforcement agencies and/or governments of competent jurisdiction or practical authority.</p>
</li>
</ul>
<a name="dnssec"></a>
<h2>DNSSEC</h2>
{{if .HasDNSSEC}}
<p>The {{.CanonicalSuffix}} nameservers support DNSSEC. For use as a suffix, operation is automatic so long as you use a validating resolver. (Third party suffixes using the {{.CanonicalSuffix}} nameservers should avoid attempting to configure DS records at this time due to the potential need for KSK rollover.)</p>
<p>If using the {{.CanonicalSuffix}} nameservers to access .bit directly, a DNSSEC trust anchor must be configured. You should use a validating resolver to lookup the DS records for {{.CanonicalSuffix}} and use those as the trust anchor. See <a href="#unbound">Unbound</a> for details on how to configure Unbound.</p>
{{else}}
<p>The {{.CanonicalSuffix}} nameservers do <strong>not</strong> support DNSSEC.</p>
{{end}}
<a name="www-config"></a>
<h2>Webserver Configuration</h2>
<h3>Apache</h3>
<p>You can configure a virtual host in Apache which responds to any hostname of the form "example.bit.X." using the following:</p>
<pre>&lt;VirtualHost ...&gt;
ServerName example.bit
ServerAlias example.bit.*
&lt;/VirtualHost&gt;</pre>
<h3>Nginx</h3>
<p>You can configure a virtual host in nginx which responds to any hostname of the form "example.bit.X." using the following:</p>
<pre>server {
listen 80;
server_name example.bit example.bit.*;
}</pre>
<p>nginx also supports regexes for server names; see the <a href="http://nginx.org/en/docs/http/server_names.html">nginx documentation</a>.</p>
<h3>Lighttpd</h3>
<p>Lighttpd can use regexes to match hostnames, so configuring suffix support is easy:</p>
<pre>$HTTP["host"] =~ "(^|\.)example\.bit(\..*)?$" {
...
}</pre>
<h2>Origin Issues</h2>
<p>Web browsers use a database of <a href="http://publicsuffix.org/">public suffixes</a> to determine the maximum domain scope at which a cookie can be set. For example, a site a.b.c.com can set a cookie at a.b.c.com and c.com but not com. Conversely, domains such as this one can have cookies set on them by domains under them. example.{{.CanonicalSuffix}} can set a cookie for {{.CanonicalSuffix}}, thereby creating a “supercookie” which tracks users over all domains under the suffix.</p>
<p>The optimal solution to this is to have the domain placed on the <a href="http://publicsuffix.org/">public suffix list</a>. However even when this is done it may take some time to be rolled out.</p>
<p>This page will erase all cookies visible to it whenever you visit it. Thus visiting this page will always erase any suffix-wide supercookies. This is the least (and most) that can be done about the issue without the use of the public suffix list.</p>
<a name="source"></a>
<h2>Source Code</h2>
<p>Each {{.CanonicalSuffix}} nameserver runs a Namecoin full node and <a href="https://github.com/hlandau/ncdns.t">ncdns</a>, a daemon for serving DNS records from the Namecoin .bit zone. ncdns relies on the full node.</p>
<p>This has the advantage that each nameserver is operationally completely independent of one another (aside from possessing the same zone signing private key, as described above).</p>
<p>This software is open source. </p>
<h2>Point of Contact</h2>
<p>Send enquiries, issues, questions, threats, etc. to <a href="mailto:{{.Hostmaster}}">{{.Hostmaster}}</a>.
{{end}}

@ -348,6 +348,7 @@ func (b *Backend) resolveName(name string) (jsonValue string, err error) {
result := make(chan struct{}, 1)
go func() {
jsonValue, err = b.nc.Query(name)
log.Errore(err, "failed to query namecoin")
result <- struct{}{}
}()

Loading…
Cancel
Save