README_adhoc-mode.rst
Setup process for adhoc mode
============================
* requires 2 (two) Linux hosts (Gentoo or Ubuntu bionic/focal LTS)
* one "mobile" host and one "exit" host
+ "mobile" host can be any Linux desktop (pkgs for arm, arm64, x86, x86_64)
+ "exit" host can be any (Linux) hardware/VM with decent gigabit ethernet
Note about network configuration
--------------------------------
The requirement for two hosts (as well as the steps that follow) is based
on the smallest possible private subnet, with only two free IPv4 addresses.
In `CIDR notation`_ this is a ``/30`` subnet, but you are free to add more
of your own hosts and use a different config. But *don't worry*, this is
simple in python. Try this at a python prompt:
::
Python 3.6.10 (default, Dec 6 2019, 21:16:24)
[GCC 9.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import ipaddress
>>> netobj = ipaddress.ip_network('172.16.0.241/30', strict=False)
>>> netobj
IPv4Network('172.16.0.240/30')
>>> list(netobj)
[IPv4Address('172.16.0.240'), IPv4Address('172.16.0.241'), IPv4Address('172.16.0.242'),
IPv4Address('172.16.0.243')]
>>> list(netobj.hosts())
[IPv4Address('172.16.0.241'), IPv4Address('172.16.0.242')]
The above demonstrates how Python "calculates" IPv4 subnets for the
(very) private 2-host network configured below. Since every IPv4 subnet
needs both a network address and a broadcast address, this leaves only
two addresses for actual host addresses on the network. If you want more
hosts on your adhoc network, simply use a larger subnet (eg, a ``/28``).
Keep in mind each mobile node on your adhoc network will all use the
same exit node; also note that a ``/28`` allows 14 host addresses:
::
>>> netobj = ipaddress.ip_network('172.16.0.30/28', strict=False)
>>> list(netobj)
[IPv4Address('172.16.0.16'), IPv4Address('172.16.0.17'), IPv4Address('172.16.0.18'),
IPv4Address('172.16.0.19'), IPv4Address('172.16.0.20'), IPv4Address('172.16.0.21'),
IPv4Address('172.16.0.22'), IPv4Address('172.16.0.23'), IPv4Address('172.16.0.24'),
IPv4Address('172.16.0.25'), IPv4Address('172.16.0.26'), IPv4Address('172.16.0.27'),
IPv4Address('172.16.0.28'), IPv4Address('172.16.0.29'), IPv4Address('172.16.0.30'),
IPv4Address('172.16.0.31')]
>>> len(list(netobj.hosts()))
14
.. _CIDR notation: https://en.wikipedia.org/wiki/CIDR_notation
Configuration steps
-------------------
The following steps are for a "personal" network (single "mobile" node).
* install fpnd, set adhoc mode (both hosts)
+ gentoo: `add the overlay`_ and ``emerge fpnd`` (``USE="adhoc"`` should be enabled by default)
+ ubuntu: `add the PPA`_ and ``apt-get install fpnd``
- edit ``/etc/fpnd.ini`` and change ``mode = peer`` to ``mode = adhoc``
* stop ``fpnd`` and start/restart ``zerotier|zerotier-one`` (both hosts)
* get the zerotier node ID from each host
+ run ``sudo zerotier-cli info``
+ output should look something like:
- ``200 info <YOUR_ID> 1.4.6 ONLINE``
- where ``<YOUR_ID>`` is a 10-digit hex string
- it may show ``OFFLINE`` after the first startup, this is normal
+ have each id ready for the next step
* create/configure a network on `my.zerotier.com`_
+ login with Google or make an account
+ select the **Free** option (read the terms of service)
+ click on the *networks* menu item and create a network
+ click on the network you just created
+ go to the **Members** section
- in the field below *Manually Add Member*:
* paste the **exit** node ID and click Add New Member
* wait for the node ID to appear and give it a name/desc
* repeat the above steps with your **mobile** node ID
.. _add the PPA: https://github.com/freepn/fpnd/blob/master/README.rst#getting-started
.. _add the overlay: https://github.com/freepn/freepn-overlay/blob/master/README.rst
.. _my.zerotier.com: https://my.zerotier.com/
.. note:: The above network Members will continue to show **Never** in the
Last Seen column until after the final steps below are complete
and fpnd is running on each node.
* configure the network for maximum privacy
+ scroll up to the Settings section
+ confirm Access Control is set to PRIVATE
+ scroll down to the Advanced section
+ under Managed Routes
- delete the existing route by clicking the trashcan
- under Add Routes
* enter ``172.16.0.240/30`` in the Destination, click Submit
* wait, then enter ``0.0.0.0/0`` in the Destination. **and**
* enter ``172.16.0.241`` in (Via) and click submit
+ under IPv4 Auto-Assign
- disable auto-assign by **un-checking** the box
+ under IPv6 Auto-Assign
- make sure all three options are *disabled*
+ go back to the Members section under Managed IPs
- for the **exit** node, enter ``172.16.0.241`` in the address field and click
the **+** sign
- for the **source** node, enter ``172.16.0.242`` in the address field and click
the **+** sign
On each adhoc node:
* get the network ID of the network you just created (at the very top of the page)
* edit the ``helper_funcs.py`` source file
- near the top of the source file, look for the NODE_SETTINGS dictionary:
.. code:: python
NODE_SETTINGS = {
u'max_cache_age': 60, # maximum cache age in seconds
u'use_localhost': False, # messaging interface to use
u'node_role': None, # role this node will run as
u'ctlr_list': ['edf70dc89a'], # list of fpn controller nodes
u'moon_list': ['9790eaaea1'], # list of fpn moons to orbiit
u'home_dir': None,
u'debug': False,
u'node_runner': 'nodestate.py',
u'mode': 'peer',
u'use_exitnode': [], # edit to populate with ID: ['exitnode']
u'nwid': None # edit to populate with network ID
}
* find the above file using Ubuntu pkg tools:
::
$ dpkg -L python3-fpnd | grep helper_funcs
* find the above file using Gentoo pkg tools:
::
$ qlist fpnd | grep helper_funcs
Using a text editor (not a word processor) carefully edit the following
item:
* ``u'nwid': None`` => replace ``None`` with the network ID string in single quotes
The last two items in ``NODE_SETTINGS`` should look something like this:
.. code:: python
u'use_exitnode': [], # edit to populate with ID: ['exitnode']
u'nwid': 'b6079f73c63cea42' # edit to populate with network ID
.. note:: Your 16-digit network ID will be different than the example shown
above. Also note the comment does *not* apply to the current
0.7.2p6 release.
Once all of the above steps are complete, start the fpnd service on each
node.
On Gentoo with openrc:
::
# /etc/init.d/fpnd start
On Gentoo or Ubuntu with systemd:
::
# service fpnd start
Troubleshooting adhoc mode
==========================
Once configured as above, everything else is automated so as long as the
required commands are available the main thing you can do from the user
end is stop/start the service and check the log file (and since debug is
enabled there should be plenty of log output :)
.. note:: If you're already running a local firewall (eg, iptables or ufw)
you should make sure that port ``9993/UDP`` is allowed out.
For adhoc mode, you should *not* use the ``restart`` command; the fpnd
service does a (network) ``join`` command on startup and the corresponding
``leave`` command on shutdown and the network needs a few seconds to process
the latter for a clean startup.
The ``fpnd`` log file is written to ``/var/log/fpnd.log`` and will show
the status of the (internal) zerotier API calls and processing of network
scripts, etc.
Use the above init/service commands via sudo, and wait at least 5-10
seconds between ``stop`` and ``start``:
::
$ sudo service fpnd stop # pause 5+ sec
$ tail -f /var/log/fpnd.log
$ sudo service fpnd start
$ tail -f /var/log/fpnd.log
Verify the pre-shutdown commands after ``stop`` then after startup look
for ``Success`` for both the initial setup command and the gateway check.
You should see something like this after startup on both peers:
::
INFO [13086] Running job Job(interval=1, unit=seconds, do=run_net_cmd,
args=(['/usr/lib/fpnd/fpn1-setup.sh'],), kwargs={})
INFO [13086] net cmd fpn1-setup.sh result: Success
DEBUG [13086] JOB: Job(interval=1, unit=seconds, do=run_net_cmd,
args=(['/usr/lib/fpnd/fpn1-setup.sh'],), kwargs={})
claims success: (True, b'Success\n', 0)
Note the lines above are truncated/wrapped for readability ;)
Lastly, you can verify the command results using the ``iptables`` command.
Once you see the above log message on the "exit" node, run the following
command from a terminal prompt::
$ sudo iptables -L -t nat
and check the ``POSTROUTING`` chain; you should see one ``SNAT`` rule:
::
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
SNAT all -- 172.16.0.240/28 anywhere to:<exit IP>
Similarly on the "mobile" node, run the same command::
$ sudo iptables -L -t nat
and check the ``POSTROUTING`` chain; you should see two ``SNAT`` rules
for http/https:
::
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
SNAT tcp -- <your host> anywhere tcp dpt:https to:172.16.0.242
SNAT tcp -- <your host> anywhere tcp dpt:http to:172.16.0.242
What we test on
===============
* various x86_64 instances (both hardware and virtual machines)
some with resources as low as 1 GB of ram
* several embedded arm/arm64 devices, mainly chromebooks and
(better than rpi) clones, eg, nanopi-k2 and rockchip/allwinner devices
For chromebooks we use mainly Gentoo and Ubuntu on bootable media
built using `this chromebook build script`_ for developer mode.
.. _this chromebook build script: https://github.com/sarnold/chromebooks