The GNU Name System
-------------------

The GNU Name System (GNS) is secure and decentralized naming system. It
allows its users to register names as top-level domains (TLDs) and
resolve other namespaces within their TLDs.

GNS is designed to provide:

-  Censorship resistance
-  Query privacy
-  Secure name resolution
-  Compatibility with DNS

For the initial configuration and population of your GNS installation,
please follow the GNS setup instructions. The remainder of this chapter
will provide some background on GNS and then describe how to use GNS in
more detail.

Unlike DNS, GNS does not rely on central root zones or authorities.
Instead any user administers their own root and can can create arbitrary
name value mappings. Furthermore users can delegate resolution to other
users’ zones just like DNS NS records do. Zones are uniquely identified
via public keys and resource records are signed using the corresponding
public key. Delegation to another user’s zone is done using special PKEY
records and petnames. A petname is a name that can be freely chosen by
the user. This results in non-unique name-value mappings as www.bob to
one user might be www.friend for someone else.

Start Zones
~~~~~~~~~~~

In the default configuration, there are two zones defined and shipped
with GNUnet:

The first is “gnunet.org”, which points to the authoritate zone of the
GNUnet project. It can be used to resolve, for example,
“www.gnunet.org”.

“.pin” is another default zone which points to a special zone also
managed by gnunet.org. Users may register submodomains on a first-come
first-served-basis at https://fcfs.gnunet.org.

Use gnunet-config -s gns to view the GNS configuration, including all
configured zones that are operated by other users. The respective
configuration entry names start with a “.”, e.g. “.pin”.

You can configure any number of top-level domains, and point them to the
respective zones of your friends! For this, simply obtain the respective
public key (you will learn how below) and extend the configuration:

::

   $ gnunet-config -s gns -o .myfriend -V PUBLIC_KEY

Zones and Egos
~~~~~~~~~~~~~~

In GNUnet, identity management is about managing egos. Egos can
correspond to pseudonyms or real-world identities. If you value your
privacy, you are encouraged to use separate egos for separate
activities.

Technically, an ego is first of all a public-private key pair, and thus
egos also always correspond to a GNS zone. Egos are managed by the
IDENTITY service. Note that this service has nothing to do with the peer
identity. The IDENTITY service essentially stores the private keys under
human-readable names, and keeps a mapping of which private key should be
used for particular important system functions.

You probably should create at least one zone of your own. You can create
any number of zones using the gnunet-identity tool using:

::

   $ gnunet-identity --create="myzone"

Henceforth, on your system you control the TLD “myzone”.

All of your zones can be listed (displayed) using the gnunet-identity
command line tool as well:

::

   $ gnunet-identity --display

Maintaining Zones
~~~~~~~~~~~~~~~~~

Now you can add (or edit, or remove) records in your GNS zone using the
gnunet-namestore-gtk GUI or using the gnunet-namestore command-line
tool. In either case, your records will be stored in an SQL database
under control of the gnunet-service-namestore. Note that if multiple
users use one peer, the namestore database will include the combined
records of all users. However, users will not be able to see each
other’s records if they are marked as private.

To provide a short example for editing your own zone, suppose you have
your own web server with the IP 1.2.3.4. Then you can put an A record (A
records in DNS are for IPv4 IP addresses) into your local zone “myzone”
using the command:

::

   $ gnunet-namestore -z myzone -a -n www -t A -V 1.2.3.4 -e 1d

Similar commands will work for other types of DNS and GNS records, the
syntax largely depending on the type of the record. Naturally, most
users may find editing the zones using the gnunet-namestore-gtk GUI to
be easier.

Each zone in GNS has a public-private key. Usually, gnunet-namestore and
gnunet-setup will access your private key as necessary, so you do not
have to worry about those. What is important is your public key (or
rather, the hash of your public key), as you will likely want to give it
to others so that they can securely link to you.

A central operation in GNS is the ability to securely delegate to other
zones. Basically, by adding a delegation you make all of the names from
the other zone available to yourself. This section describes how to
create delegations.

Suppose you have a friend who you call ’bob’ who also uses GNS. You can
then delegate resolution of names to Bob’s zone by adding a PKEY record
to their local zone:

::

   $ gnunet-namestore -a -n bob --type PKEY -V XXXX -e 1d -z myzone

Note that “XXXX” in the command above must be replaced with the hash of
Bob’s public key (the output your friend obtained using the
gnunet-identity command from the previous section and told you, for
example by giving you a business card containing this information as a
QR code).

Assuming Bob has an “A” record for their website under the name of “www”
in his zone, you can then access Bob’s website under “www.bob.myzone” —
as well as any (public) GNS record that Bob has in their zone by
replacing www with the respective name of the record in Bob’s zone.

Furthermore, if Bob has themselves a (public) delegation to Carol’s zone
under “carol”, you can access Carol’s records under
“NAME.carol.bob.myzone” (where “NAME” is the name of Carol’s record you
want to access).

Resolving GNS records
~~~~~~~~~~~~~~~~~~~~~

Next, you should try resolving your own GNS records. The method we found
to be the most uncomplicated is to do this by explicitly resolving using
gnunet-gns. For this exercise, we will assume that you used the string
“gnu” for the pseudonym (or label) of your GNS zone. If you used
something else, replace “.gnu” with your real pseudonym in the examples
below.

In the shell, type:

::

   $ gnunet-gns -u www.gnunet.org
   www.gnunet.org:
   Got `A' record: ...

That shows that resolution works, once GNS is integrated with the
application.

Integration with Browsers (DNS2GNS service)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Most OSes allow you to either modify your ``/etc/resolv.conf`` directly
or through ``resolvectl``. We are going to configure the dns2gns service
in order to translate DNS name queries by applications to GNS name
queries where applicable and else fall back to DNS.

Optionally, you may want to configure your dns2gns service to run on a
non-priviledged port like 5353. But, in case you are going to edit
``/etc/resolv.conf`` directly, the dns2gns service MUST run on port 53
as you cannot specify the port number. A ``$FALLBACK_DNS`` variable
should be a DNS server you trust such as your local router:

::

   $ gnunet-config -s dns2gns -o OPTIONS -V "-d $FALLBACK_DNS -p 5252"
   $ gnunet-arm -i dns2gns # Make sure the service is started

If you edit your resolv.conf directly, it should contain and entry like
this:

::

   nameserver 127.0.0.1

In any case, it is very likely that the method of modification of your
resolver is OS specific. Recently, the combination of NetworkManager and
systemd-resolved is becoming increasingly popular.

If you use resolvectl and systemd-resolved you can temporarily set the
nameserver like this:

::

   $ resolvectl $INTERFACE 127.0.0.1:5353

Where ``$INTERFACE`` is your network interface such as ``eth0``.

In order to automatically set the DNS2GNS server if it is running
already you can use NetworkManager-dispatcher. First, enable it:

::

   $ sudo systemctl enable NetworkManager-dispatcher.service
   $ sudo systemctl start NetworkManager-dispatcher.service

Then, create a script ``/etc/NetworkManager/dispatch.h/10-dns2-gns.sh``:

::

   #!/bin/sh
   interface=$1
   status=$2

   if [ "$interface" = "eth0" ]; then
     case $status in
       up)
         if nc -u -z 127.0.0.1 5353; then
         resolvectl dns $interface 127.0.0.1:5353
       fi
       ;;
       down)
       ;;
     esac
   fi

Make sure the script is owned by root and executable:

::

   $ sudo root:root /etc/NetworkManager/dispatch.d/10-dns2gns.sh
   $ sudo +x /etc/NetworkManager/dispatch.d/10-dns2gns.sh

You can test accessing this website using your browser or curl:

::

   $ curl www.gnunet.org

Note that “gnunet.org” is a domain that also exists in DNS and for which
the GNUnet project webservers can provide trusted TLS certificates. When
using non-DNS names with GNS or aliases, this may result in issues when
accessing HTTPS websites with browsers. In order learn how to provide
relief for this issue, read on.

Integration with Browsers (SOCKS proxy)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

While we recommend integrating GNS using the DNS2GNS service or the
NSSwitch plugin, you can also integrate GNS directly with your browser
via the gnunet-gns-proxy. This method can have the advantage that the
proxy can validate TLS/X.509 records and thus strengthen web security;
however, the proxy is still a bit brittle, so expect subtle failures. We
have had reasonable success with Chromium, and various frustrations with
Firefox in this area recently.

The first step is to start the proxy. As the proxy is (usually) not
started by default, this is done as a unprivileged user using gnunet-arm
-i gns-proxy. Use gnunet-arm -I as a unprivileged user to check that the
proxy was actually started. (The most common error for why the proxy may
fail to start is that you did not run gnunet-gns-proxy-setup-ca during
installation.) The proxy is a SOCKS5 proxy running (by default) on port
7777. Thus, you need to now configure your browser to use this proxy.
With Chromium, you can do this by starting the browser as a unprivileged
user using chromium –proxy-server=“socks5://localhost:7777” For Firefox
(or Icecat), select “Edit-Preferences” in the menu, and then select the
“Advanced” tab in the dialog and then “Network”:

Here, select “Settings…” to open the proxy settings dialog. Select
“Manual proxy configuration” and enter localhost with port 7777 under
SOCKS Host. Furthermore, set the checkbox “Proxy DNS when using SOCKS
v5” at the bottom of the dialog. Finally, push “OK”.

You must also go to about:config and change the
browser.fixup.alternate.enabled option to false, otherwise the browser
will autoblunder an address like www.gnu to www.gnu.com. If you want to
resolve @ in your own TLDs, you must additionally set
browser.fixup.dns_first_use_for_single_words to true.

After configuring your browser, you might want to first confirm that it
continues to work as before. (The proxy is still experimental and if you
experience “odd” failures with some webpages, you might want to disable
it again temporarily.) Next, test if things work by typing
“http://test.gnu/” into the URL bar of your browser. This currently
fails with (my version of) Firefox as Firefox is super-smart and tries
to resolve “http://www.test.gnu/” instead of “test.gnu”. Chromium can be
convinced to comply if you explicitly include the “http://” prefix —
otherwise a Google search might be attempted, which is not what you
want. If successful, you should see a simple website.

Note that while you can use GNS to access ordinary websites, this is
more an experimental feature and not really our primary goal at this
time. Still, it is a possible use-case and we welcome help with testing
and development.

Creating a Business Card
~~~~~~~~~~~~~~~~~~~~~~~~

Before we can really use GNS, you should create a business card. Note
that this requires having LaTeX installed on your system. If you are
using a Debian GNU/Linux based operating system, the following command
should install the required components. Keep in mind that this requires
3GB of downloaded data and possibly even more when unpacked. On a GNU
Guix based system texlive 2017 has returns a DAG size of 5032.4 MiB. The
packages which are confirmed to be required are:

-  texlive-units
-  texlive-labels
-  texlive-pst-barcode
-  texlive-luatex85
-  texlive-preview
-  texlive-pdfcrop
-  texlive-koma-script

**We welcome any help in identifying the required components of the
TexLive Distribution. This way we could just state the required
components without pulling in the full distribution of TexLive.**

::

   apt-get install texlive-full

Start creating a business card by clicking the “Copy” button in
gnunet-namestore-gtk. Next, you should start the gnunet-bcd program (in
the terminal, on the command-line). You do not need to pass any options,
and please be not surprised if there is no output:

::

   $ gnunet-bcd # does not return

Then, start a browser and point it to http://localhost:8888/ where
gnunet-bcd is running a Web server!

First, you might want to fill in the “GNS Public Key” field by
right-clicking and selecting “Paste”, filling in the public key from the
copy you made in gnunet-namestore-gtk. Then, fill in all of the other
fields, including your GNS NICKname. Adding a GPG fingerprint is
optional. Once finished, click “Submit Query”. If your LaTeX
installation is incomplete, the result will be disappointing. Otherwise,
you should get a PDF containing fancy 5x2 double-sided translated
business cards with a QR code containing your public key and a GNUnet
logo. We’ll explain how to use those a bit later. You can now go back to
the shell running gnunet-bcd and press CTRL-C to shut down the Web
server.

Be Social
~~~~~~~~~

Next, you should print out your business card and be social. Find a
friend, help them install GNUnet and exchange business cards with them.
Or, if you’re a desperate loner, you might try the next step with your
own card. Still, it’ll be hard to have a conversation with yourself
later, so it would be better if you could find a friend. You might also
want a camera attached to your computer, so you might need a trip to the
store together.

Before we get started, we need to tell gnunet-qr which zone it should
import new records into. For this, run:

::

   $ gnunet-identity -s namestore -e NAME

where NAME is the name of the zone you want to import records into. In
our running example, this would be “gnu”.

Henceforth, for every business card you collect, simply run:

::

   $ gnunet-qr

to open a window showing whatever your camera points at. Hold up your
friend’s business card and tilt it until the QR code is recognized. At
that point, the window should automatically close. At that point, your
friend’s NICKname and their public key should have been automatically
imported into your zone.

Assuming both of your peers are properly integrated in the GNUnet
network at this time, you should thus be able to resolve your friends
names. Suppose your friend’s nickname is “Bob”. Then, type

::

   $ gnunet-gns -u test.bob

to check if your friend was as good at following instructions as you
were.

Backup of Identities and Egos
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

One should always backup their files, especially in these SSD days (our
team has suffered 3 SSD crashes over a span of 2 weeks). Backing up peer
identity and zones is achieved by copying the following files:

The peer identity file can be found in
``~/.local/share/gnunet/private_key.ecc``.

The private keys of your egos are stored in the directory
``~/.local/share/gnunet/identity/egos/``. They are stored in files whose
filenames correspond to the zones’ ego names. These are probably the
most important files you want to backup from a GNUnet installation.

Note: All these files contain cryptographic keys and they are stored
without any encryption. So it is advisable to backup encrypted copies of
them.

Revocation
~~~~~~~~~~

Now, in the situation of an attacker gaining access to the private key
of one of your egos, the attacker can create records in the respective
GNS zone and publish them as if you published them. Anyone resolving
your domain will get these new records and when they verify they seem
authentic because the attacker has signed them with your key.

To address this potential security issue, you can pre-compute a
revocation certificate corresponding to your ego. This certificate, when
published on the P2P network, flags your private key as invalid, and all
further resolutions or other checks involving the key will fail.

A revocation certificate is thus a useful tool when things go out of
control, but at the same time it should be stored securely. Generation
of the revocation certificate for a zone can be done through
gnunet-revocation. For example, the following command (as unprivileged
user) generates a revocation file revocation.dat for the zone zone1:
gnunet-revocation -f revocation.dat -R zone1

The above command only pre-computes a revocation certificate. It does
not revoke the given zone. Pre-computing a revocation certificate
involves computing a proof-of-work and hence may take up to 4 to 5 days
on a modern processor. Note that you can abort and resume the
calculation at any time. Also, even if you did not finish the
calculation, the resulting file will contain the signature, which is
sufficient to complete the revocation process even without access to the
private key. So instead of waiting for a few days, you can just abort
with CTRL-C, backup the revocation certificate and run the calculation
only if your key actually was compromised. This has the disadvantage of
revocation taking longer after the incident, but the advantage of saving
a significant amount of energy. So unless you believe that a key
compromise will need a rapid response, we urge you to wait with
generating the revocation certificate. Also, the calculation is
deliberately expensive, to deter people from doing this just for fun (as
the actual revocation operation is expensive for the network, not for
the peer performing the revocation).

To avoid TL;DR ones from accidentally revocating their zones, we are not
giving away the command, but it is uncomplicated: the actual revocation
is performed by using the -p option of gnunet-revocation.

What’s next?
~~~~~~~~~~~~

This may seem not like much of an application yet, but you have just
been one of the first to perform a decentralized secure name lookup
(where nobody could have altered the value supplied by your friend) in a
privacy-preserving manner (your query on the network and the
corresponding response were always encrypted). So what can you really do
with this? Well, to start with, you can publish your GnuPG fingerprint
in GNS as a “CERT” record and replace the public web-of-trust with its
complicated trust model with explicit names and privacy-preserving
resolution. Also, you should read the next chapter of the tutorial and
learn how to use GNS to have a private conversation with your friend.
Finally, help us with the next GNUnet release for even more applications
using this new public key infrastructure.

Resource Records
~~~~~~~~~~~~~~~~

GNS supports the majority of the DNS records as defined in `RFC
1035 <http://www.ietf.org/rfc/rfc1035.txt>`__. Additionally, GNS defines
some new record types the are unique to the GNS system. For example,
GNS-specific resource records are used to give petnames for zone
delegation, revoke zone keys and provide some compatibility features.

For some DNS records, GNS does extended processing to increase their
usefulness in GNS. In particular, GNS introduces special names referred
to as “zone relative names”. Zone relative names are allowed in some
resource record types (for example, in NS and CNAME records) and can
also be used in links on webpages. Zone relative names end in “.+” which
indicates that the name needs to be resolved relative to the current
authoritative zone. The extended processing of those names will expand
the “.+” with the correct delegation chain to the authoritative zone
(replacing “.+” with the name of the location where the name was
encountered) and hence generate a valid GNS name.

The GNS currently supports the record types as defined in
`GANA <https://git.gnunet.org/gana.git/tree/gnu-name-system-record-types/registry.rec>`__.
In addition, GNS supports DNS record types, such as A, AAAA or TXT.

For a complete description of the records, please refer to the
specification at `LSD0001 <https://lsd.gnunet.org/lsd0001>`__.

In the following, we discuss GNS records with specific behaviour or
special handling in GNUnet.

VPN
^^^

GNS allows easy access to services provided by the GNUnet Virtual Public
Network. When the GNS resolver encounters a VPN record it will contact
the VPN service to try and allocate an IPv4/v6 address (if the queries
record type is an IP address) that can be used to contact the service.

**Example**

I want to provide access to the VPN service “web.gnu.” on port 80 on
peer ABC012: Name: www; RRType: VPN; Value: 80 ABC012 web.gnu.

The peer ABC012 is configured to provide an exit point for the service
“web.gnu.” on port 80 to it’s server running locally on port 8080 by
having the following lines in the gnunet.conf configuration file:

::

   [web.gnunet.]
   TCP_REDIRECTS = 80:localhost4:8080

Synchronizing with legacy DNS
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

If you want to support GNS but the master database for a zone is only
available and maintained in DNS, GNUnet includes the gnunet-zoneimport
tool to monitor a DNS zone and automatically import records into GNS.
Today, the tool does not yet support DNS AF(X)R, as we initially used it
on the “.fr” zone which does not allow us to perform a DNS zone
transfer. Instead, gnunet-zoneimport reads a list of DNS domain names
from stdin, issues DNS queries for each, converts the obtained records
(if possible) and stores the result in the namestore.

The zonemaster service then takes the records from the namestore,
publishes them into the DHT which makes the result available to the GNS
resolver. In the GNS configuration, non-local zones can be configured to
be intercepted by specifying “.tld = PUBLICKEY” in the configuration
file in the “[gns]” section.

Note that the namestore by default also populates the namecache. This
pre-population is cryptographically expensive. Thus, on systems that
only serve to import a large (millions of records) DNS zone and that do
not have a local gns service in use, it is thus advisable to disable the
namecache by setting the option “DISABLE” to “YES” in section
“[namecache]”.

Migrating an existing DNS zone into GNS
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Ascension is a tool to migrate existing DNS zones into GNS.

Compared to the gnunet-zoneimport tool it strictly uses AXFR or IXFR
depending on whether or not there exists a SOA record for the zone. If
that is the case it will take the serial as a reference point and
request the zone. The server will either answer the IXFR request with a
correct incremental zone or with the entire zone, which depends on the
server configuration.

Before you can migrate any zone though, you need to start a local GNUnet
peer. To migrate the Syrian top level domain - one of the few top level
domains that support zone transfers - into GNS use the following
command:

::

   $ ascension sy. -n ns1.tld.sy. -p

The -p flag will tell GNS to put these records on the DHT so that other
users may resolve these records by using the public key of the zone.

Once the zone is migrated, Ascension will output a message telling you,
that it will refresh the zone after the time has elapsed. You can
resolve the names in the zone directly using GNS or if you want to use
it with your browser, check out the GNS manual section. Configuring the
GNU Name System. To resolve the records from another system you need the
respective zones PKEY. To get the zones public key, you can run the
following command:

::

   $ gnunet-identity -dqe sy

Where “sy” is the name of the zone you want to migrate.

You can share the PKEY of the zone with your friends. They can then
resolve records in the zone by doing a lookup replacing the zone label
with your PKEY:

::

   $ gnunet-gns -t SOA -u "$PKEY"

The program will continue to run as a daemon and update once the refresh
time specified in the zones SOA record has elapsed.

DNSCurve style records are supported in the latest release and they are
added as a PKEY record to be referred to the respective GNS public key.
Key distribution is still a problem but provided someone else has a
public key under a given label it can be looked up.

There is an unofficial Debian package called python3-ascension that adds
a system user ascension and runs a GNUnet peer in the background.

Ascension-bind is also an unofficial Debian package that on installation
checks for running DNS zones and whether or not they are transferable
using DNS zone transfer (AXFR). It asks the administrator which zones to
migrate into GNS and installs a systemd unit file to keep the zone up to
date. If you want to migrate different zones you might want to check the
unit file from the package as a guide.

