Merge pull request #70 from ktsaou/vnetbuild

Add vnetbuild
This commit is contained in:
philwhineray 2015-04-26 19:24:23 +01:00
commit d0307dacb4
16 changed files with 1496 additions and 13 deletions

16
.gitignore vendored

@ -11,19 +11,14 @@ config.log
config.status
doc/db-valid
doc/services-generated
doc/*/tmp*
doc/*/man/man1/
doc/*/man/man5/
doc/*/*-manual.html
doc/*/*-manual.pdf
doc/firehol.ent
doc/firehol/tmp*
doc/firehol/man/man1/
doc/firehol/man/man5/
doc/firehol/firehol-manual.html
doc/firehol/firehol-manual.pdf
doc/firehol/firehol-services.html
doc/firehol/firehol-services.5.md
doc/fireqos/tmp*
doc/fireqos/man/man1/
doc/fireqos/man/man5/
doc/fireqos/fireqos-manual.html
doc/fireqos/fireqos-manual.pdf
doc/index-services.html
doc/index.html
doc/ch*.html
@ -36,6 +31,7 @@ doc/tools/pandoc-post
sbin/firehol
sbin/fireqos
sbin/link-balancer
sbin/vnetbuild
*.xz
*.gz
*.bz2

@ -7,6 +7,7 @@ AC_CONFIG_AUX_DIR([autotool])
AC_CONFIG_SRCDIR([sbin/firehol.in])
AC_CONFIG_SRCDIR([sbin/fireqos.in])
AC_CONFIG_SRCDIR([sbin/link-balancer.in])
AC_CONFIG_SRCDIR([sbin/vnetbuild.in])
AM_INIT_AUTOMAKE([gnu])
AM_MAINTAINER_MODE([disable])
@ -103,6 +104,7 @@ AC_CONFIG_FILES([
doc/Makefile
doc/firehol/Makefile
doc/fireqos/Makefile
doc/vnetbuild/Makefile
examples/Makefile
etc/Makefile
packaging/Makefile
@ -111,5 +113,6 @@ AC_CONFIG_FILES([
AC_CONFIG_FILES([sbin/firehol], [chmod +x sbin/firehol])
AC_CONFIG_FILES([sbin/fireqos], [chmod +x sbin/fireqos])
AC_CONFIG_FILES([sbin/link-balancer], [chmod +x sbin/link-balancer])
AC_CONFIG_FILES([sbin/vnetbuild], [chmod +x sbin/vnetbuild])
AC_OUTPUT

@ -1,6 +1,6 @@
# Process this file with automake to produce Makefile.in
SUBDIRS = . firehol fireqos
SUBDIRS = . firehol fireqos vnetbuild
all-local: service-links
@ -9,10 +9,13 @@ dochtmldir = $(htmldir)/html
MANUAL_LINKS = \
links-internal-firehol \
links-internal-fireqos \
links-internal-vnetbuild \
links-keywords-firehol \
links-keywords-fireqos \
links-keywords-vnetbuild \
links-website-firehol \
links-website-fireqos
links-website-fireqos \
links-website-vnetbuild
if ENABLE_DOC

@ -0,0 +1,11 @@
<!--
This file lists internal references within the manual
and associates them with anchors in the output.
Note that the blank line after this comment is required, to keep
pandoc(1) happy when formatting.
-->
[vnetbuild(1)]: vnetbuild.1.md#vnetbuild1
[vnetbuild.conf(5)]: vnetbuild-conf.5.md#vnetbuild.conf5

129
doc/vnetbuild/Makefile.am Normal file

@ -0,0 +1,129 @@
# Process this file with automake to produce Makefile.in
MANUAL_LINKS = \
${top_srcdir}/doc/links-internal-vnetbuild \
${top_srcdir}/doc/links-keywords-vnetbuild \
${top_srcdir}/doc/links-website-vnetbuild
dochtmldir = $(htmldir)/html
MANUALHTML_GENERATED = \
vnetbuild-manual.html
MANUALPDF_GENERATED = \
vnetbuild-manual.pdf
# Generate using:
# (ls vn*.md) | sed -ne 's;\(.*\).\([0-9]\).md;\tman/man\2/\1.\2 \\;p' |sort -u
MANUALMAN_GENERATED = \
man/man1/vnetbuild.1 \
man/man5/vnetbuild-conf.5
# Generate using:
# sed -ne 's;extra-manpage: \(.*\)\([0-9]\);\tman/man\2/\1\2 \\;p' *.md|sort -u
MANUALMAN_GENERATED_INDIRECT = \
man/man5/vnetbuild-bridgedev.5 \
man/man5/vnetbuild.conf.5 \
man/man5/vnetbuild-dev.5 \
man/man5/vnetbuild-exec.5 \
man/man5/vnetbuild-host.5 \
man/man5/vnetbuild-route.5 \
man/man5/vnetbuild-switch.5
if ENABLE_DOC
dochtml_DATA = \
$(MANUALHTML_GENERATED)
pdf_DATA = \
$(MANUALPDF_GENERATED)
endif
man_MANS = \
$(MANUALMAN_GENERATED) \
$(MANUALMAN_GENERATED_INDIRECT)
if MAINTAINER_MODE
MKSERVICELINKS = ${top_srcdir}/doc/tools/mkservicelinks
MKSERVICEMAN = ${top_srcdir}/doc/tools/mkserviceman
MANSYNOS = ${top_srcdir}/doc/tools/man-synos
COMBINEPANDOC = ${top_srcdir}/doc/tools/combine-pandoc
PANDOCPOST = ${top_srcdir}/doc/tools/pandoc-post
CHECKLINKS = ${top_srcdir}/doc/tools/check-links
FIREHOLIN = $(top_srcdir)/sbin/firehol.in
man/man1/%.1: %.1.md
$(MKDIR_P) man/man1
$(SED) -e '/^%/s/DATE/@PACKAGE_BUILT_DATE@/' -e '/^%/s/VERSION/@PACKAGE_VERSION@/' $< > tmp-manproc
$(SED) -e 's/: .*#/: #/' $(MANUAL_LINKS) > tmp-anchor-links
$(PANDOC) $(PANDOC_MAN_FLAGS) -o $@ tmp-manproc tmp-anchor-links
$(PANDOCPOST) $(PANDOC_VERSION) man $@
$(MANSYNOS) $< $@ man/
man/man5/%.5: %.5.md
$(MKDIR_P) man/man5
$(SED) -e '/^%/s/DATE/@PACKAGE_BUILT_DATE@/' -e '/^%/s/VERSION/@PACKAGE_VERSION@/' $< > tmp-manproc
$(SED) -e 's/: .*#/: #/' $(MANUAL_LINKS) > tmp-anchor-links
$(PANDOC) $(PANDOC_MAN_FLAGS) -o $@ tmp-manproc tmp-anchor-links
$(PANDOCPOST) $(PANDOC_VERSION) man $@
$(MANSYNOS) $< $@ man/
$(MANUALMAN_GENERATED): $(MANUAL_LINKS)
vnetbuild-manual.pdf: *.md $(MANUAL_LINKS)
$(SED) -e 's/: .*#/: #/' $(MANUAL_LINKS) > tmp-anchor-links
$(COMBINEPANDOC) pdf tmp-pdf-combined.md contents.md tmp-anchor-links
$(SED) -i -e '/^%/s/DATE/@PACKAGE_BUILT_DATE@/' -e '/^%/s/VERSION/@PACKAGE_VERSION@/' tmp-pdf-combined.md
$(PANDOC) $(PANDOC_PDF_FLAGS) -o $@ tmp-pdf-combined.md
rm tmp-pdf-combined.md
$(PANDOCPOST) $(PANDOC_VERSION) pdf $@
vnetbuild-manual.html: *.md $(MANUAL_LINKS)
$(SED) -e 's/: .*#/: #/' $(MANUAL_LINKS) > tmp-anchor-links
$(COMBINEPANDOC) html tmp-html-combined.md contents.md tmp-anchor-links
$(SED) -i -e '/^%/s/DATE/@PACKAGE_BUILT_DATE@/' -e '/^%/s/VERSION/@PACKAGE_VERSION@/' tmp-html-combined.md
$(PANDOC) $(PANDOC_HTML_FLAGS) -o tmp-manual.html tmp-html-combined.md
rm tmp-html-combined.md
$(CHECKLINKS) tmp-manual.html $(MANUAL_LINKS)
$(PANDOCPOST) $(PANDOC_VERSION) html tmp-manual.html
mv tmp-manual.html $@
endif
EXTRA_DIST = \
*.md \
$(MANUALHTML_GENERATED) \
$(MANUALPDF_GENERATED) \
$(MANUALMAN_GENERATED) \
$(MANUALMAN_GENERATED_INDIRECT)
CLEANFILES = \
tmp-anchor-links \
tmp-html-combined.md \
tmp-manproc \
tmp-manual.html \
tmp-pdf-combined.md
DISTCLEANFILES =
MAINTAINERCLEANFILES = \
service-links \
$(MANUALHTML_GENERATED) \
$(MANUALPDF_GENERATED) \
$(MANUALMAN_GENERATED) \
$(MANUALMAN_GENERATED_INDIRECT)
if MAINTAINER_MODE
DISTCLEANFILES += $(MAINTAINERCLEANFILES)
endif
uninstall-local:
@-rmdir --ignore-fail-on-non-empty $(DESTDIR)$(dochtmldir)
@-rmdir --ignore-fail-on-non-empty $(DESTDIR)$(pdfdir)

24
doc/vnetbuild/contents.md Normal file

@ -0,0 +1,24 @@
% VNetBuild Reference
% Copyright (c) Copyright (c) 2012-2015 Phil Whineray <phil@firehol.org>; 2015 Costa Tsaousis <costa@firehol.org>
% Version VERSION (Built DATE)
\newpage
<!--
This file is processed to include inline the individual pages
single-page HTML and PDF. It is used as-is as a contents page
for multi-page formats.
-->
The latest version of this manual is available online as a
[PDF](http://firehol.org/vnetbuild-manual.pdf), as
[single page HTML](http://firehol.org/vnetbuild-manual.html)
and also as
[multiple pages within the website](http://firehol.org/vnetbuild-manual/).
# VNetBuild Reference
## Running and Configuring VNetBuild
* [vnetbuild(1)](vnetbuild.1.md)
* [vnetbuild.conf(5)](vnetbuild-conf.5.md)

@ -0,0 +1,80 @@
Introduction
============
Who should read this manual
---------------------------
This is a reference guide with specific detailed information on
commands and configuration syntax for the VNetBuild tool.
The reference is unlikely to be suitable for newcomers to the tools,
except as a means to look up more information on a particular command.
For tutorials and guides to using FireHOL and VNetBuild, please visit the
[website](http://firehol.org/).
Where to get help
-----------------
The [FireHOL website](http://firehol.org/).
The [mailing lists and
archives](http://lists.firehol.org/mailman/listinfo).
The package comes with a complete set of manpages, a README and a brief
INSTALL guide.
Installation
------------
You can download tar-file releases by visiting the [FireHOL website
download area](http://firehol.org/download/).
Unpack and change directory with:
tar xfz firehol-version.tar.gz
cd firehol-version
Options for the configure program can be seen in the INSTALL file and by
running:
./configure --help
To build and install taking the default options:
./configure && make && sudo make install
Alternatively, just copy the `sbin/vnetbuild.in` file to where you want it.
All of the common SysVInit command line arguments are recognised which
makes it easy to deploy the script as a startup service.
Packages are available for most distributions and you can use your
distribution's standard commands (e.g. aptitude, yum, etc.) to install
these.
> **Note**
>
> Distributions do not always offer the latest version. You can see what
> the latest release is on the [FireHOL website](http://firehol.org/).
Licence
-------
This manual is licensed under the same terms as the FireHOL package, the
GNU GPL v2 or later.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
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.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

@ -0,0 +1,270 @@
% vnetbuild.conf(5) VNetBuild Reference | VERSION
% FireHOL Team
% Built DATE
# NAME
vnetbuild.conf - VNetBuild configuration file
<!--
extra-manpage: vnetbuild.conf.5
extra-manpage: vnetbuild-host.5
extra-manpage: vnetbuild-switch.5
extra-manpage: vnetbuild-dev.5
extra-manpage: vnetbuild-bridgedev.5
extra-manpage: vnetbuild-route.5
extra-manpage: vnetbuild-exec.5
-->
# SYNOPSIS
````
host *ID*
dev *DEVICE* [ *ID*/*PAIRDEV* ] [ *IP*/*MASK*... ]
...
bridgedev *BRIDGE* [ *DEVICE*... ] [ *IP*/*MASK*... ]
...
route *ROUTECMD*
...
exec *CUSTOMCMD*
...
...
switch *ID*
dev *DEVICE* [ *ID*/*PAIRDEV* ]
...
exec *CUSTOMCMD*
...
...
````
# DESCRIPTION
There is no default configuration file for [vnetbuild(1)][]; one must
always be specified on the command line.
The configuration file defines a set of namespaces that will be operated
on.
VNetBuild defines two types of namespace, a `host` and a `switch`. Any
number of each may be specified, with any number of configuration
statements in each.
Note
: The Linux kernel does not see any difference between a `host` and
a `switch` namespace. VNetBuild provides the distinction to make it
easy build full virtual networks.
# NAMESPACE DEFINITIONS
Namespace definitions come in two types, `host` and `switch`. Simply
provide a simple unique alphanumeric *ID*. Any subsequent statements
apply to this namespace until the next `host` or `switch` statement.
A `host` definition is designed to work like a physical machine.
It allows you to specify any number of `dev` entries for network
interfaces, with their IP addresses. You can also define any
number of Linux bridges with `bridgedev` to add your defined
interfaces to.
A `host` also allows any number of custom `exec` commands for
extensibility and provides a `route` statement to deal with the
common case of wanting to add network routes to the host.
A `switch` definition is designed to work like a physical network
switch. It allows you to add any number of `dev` entries (and also
custom `exec` commands for extensibility) but nothing else.
In addition, `dev` entries in a `switch` may only specify device names,
they cannot have an IP address associated. A `switch` has a bridge
automatically created in it and all `dev` entries are automatically
added to it.
# CONFIGURATION STATEMENTS
dev *DEVICE* ...
: Define a virtual ethernet device, *DEVICE* in a `host` or `switch`.
Devices must exist in pairs. A `dev` must first be defined unpaired
in a namespace, then some subsequent `dev` must define the pair:
````
host a
dev veth0
host b
dev vppp0 a/veth0
````
Any *DEVICE* name which is acceptable to the Linux kernel
may be used. We recommend sticking to e.g. `veth0`, `vppp0` etc.
to make it clear that they are virtual and also how you are
thinking of the device in terms of your setup. Devices will
be created as type `veth`, irrespective of what you call them.
Hosts may optionally specify one or more *IP*/*MASK* values which
will be applied (along with the calculated broadcast address)
automatically, e.g.:
````
host a
dev veth0 10.0.0.1/8 192.168.1.2/24
host b
dev vppp0 a/veth0 10.0.0.2/8 192.168.1.3/24
````
A `dev` may not specify an IP address if it is in a `switch`. Switches
exist just to tie together multiple devices in hosts, just like a
physical network switch.
bridgedev *BRIDGE* ...
: Define an ethernet bridge, *BRIDGE* in a `host`. These are setup
automatically using brctl(8).
A bridge can specify network devices from its own namespace to
be automatically added, as well as its own IP address(es).
````
host a
dev veth0
dev veth1 otherns/vdev0
bridgedev vbr0 veth0 veth1 10.0.0.3/8
````
Devices included in a bridge generally do not need their own IP
address (although that is permitted).
Bridges cannot have a pair themselves, but any devices added to
a bridge need a pair as usual.
route *ROUTECMD*
: Specify an additional network route for a `host`.
Most commonly to add a default route from hosts on a "LAN" to
the machine that acts as a gateway, e.g.:
````
route default via 10.0.0.254
````
The syntax of *ROUTECMD* is anything that can fit this pattern:
````
ip route add ROUTECMD
````
See ip(8) and ip-route(8) for help adding routes. If you want to do
anything more complex than simply adding routes, use the `exec`
configuration statement.
exec *CUSTOMCMD*
: Execute a custom command in a `host` or `switch` once the rest
of the namespace setup is complete.
Once all the namespaces are created, the final step in setting
each one up is to have its `exec` statements combined and executed.
It is roughly the equivalent to writing your own script and executing
it after `vnetbuild start` has finished:
````
sudo iptables netns exec myns ./myscript.sh
````
See below for some common uses for custom `exec` commands.
# COMMON CUSTOM COMMANDS
Forwarding is not enabled by the Linux kernel when a namespace is first
created. This can be easily done for any hosts that need to forward
traffic:
~~~~
host mygateway
...
exec echo 1 > /proc/sys/net/ipv4/ip_forward
~~~~
The `exec` operates in the `mygateway` namespace so your host is not
affected.
Logs from network namespaces are not included in the normal system
logs. To enable iptables logging you must start an instance of
ulogd(8) in the namespace and use *ULOG* or *NFLOG* logging. For
FireHOL, that means set `FIREHOL_LOG_MODE=ULOG` or
`FIREHOL_LOG_MODE=NFLOG`. Note that *NFLOG* only works with ulogd
version 2.
The default configuration for ulogd(8) is `/etc/ulogd.conf`. Assuming
the default place it will write iptables logs to is
`/var/log/ulog/syslogemu.log` (otherwise change the `sed` command
as required), it is simple to set up per-namespace logging:
~~~~
host mygateway
...
exec sed 's:/var/log/ulog/syslogemu.log:/var/log/ulog/mygateway.log:' /etc/ulogd.conf > $NSTMP/ulogd.conf
exec /usr/sbin/ulogd -d -c $NSTMP/ulogd.conf
~~~~
The `-d` flag to ulogd(8) makes it become a daemon; when `vnetbuild stop`
executes it will automatically kill any programs running in the namespaces
is is stopping, which includes the logging daemon.
The configuration file will get cleaned as soon as `vnetbuild start`
is finished. To be able to access such files you need to write them to
a location not under `$NSTMP` or create them up outside the `vnetbuild`
configuration altogether.
# EXAMPLE
A simple LAN arrangement with two hosts, one of which is a gateway
to third host:
````
host host01
dev veth0 10.0.0.1/8
dev vppp0 192.168.0.1/24
exec echo 1 > /proc/sys/net/ipv4/ip_forward
route default via 192.168.0.1
host host02
dev veth0 10.0.0.2/8
route default via 10.0.0.1
switch lan
dev d01 host01/veth0
dev d02 host02/veth0
host extern01
dev veth0 host01/vppp0 192.168.0.254/24
route default via 192.168.0.1
exec echo 1 > /proc/sys/net/ipv4/ip_forward
````
# LIMITATIONS
When created, the namespaces setup by `vnetbuild` are completely
disconnected from any real network. There is no way of defining
such a connection in the `vnetbuild` configuration as allowing it
would lead to conflicts with the normal network setup tools and
configuration files in most distributions.
It is possible to arrange your network so you can connect real
devices into one or more network namespaces. For the general
approach see this [mailing list post][ml].
[ml]: http://lists.firehol.org/pipermail/firehol-support/2015-April/003043.html
# SEE ALSO
* [vnetbuild(1)][] - VNetBuild program
* [FireHOL Website](http://firehol.org/)
* [VNetBuild Online PDF Manual](http://firehol.org/vnetbuild-manual.pdf)
* [VNetBuild Online Documentation](http://firehol.org/documentation/)
* [ip(8)](http://manpages.ubuntu.com/manpages/trusty/man8/ip.8.html) - show/manipulate network devices
* [ip-route(8)](http://manpages.ubuntu.com/manpages/trusty/man8/ip-route.8.html) - routing table management
* [brctl(8)](http://manpages.ubuntu.com/manpages/trusty/man8/brctl.8.html) - routing table management
* [ulogd(8)](http://manpages.ubuntu.com/manpages/trusty/man8/ulogd.8.html) - netfilter/iptables logging daemon

@ -0,0 +1,102 @@
% vnetbuild(1) VNetBuild Reference | VERSION
% FireHOL Team
% Built DATE
# NAME
vnetbuild - an easy to use but powerful namespace setup tool
# SYNOPSIS
sudo vnetbuild *CONFIGFILE* { start | stop | status }
vnetbuild *CONFIGFILE* graphviz *OUTFILE*.{gv|png|pdf|ps}
# DESCRIPTION
VNetBuild is a program that helps you set up groups of interconnected
network namespaces, to simulate networks of any complexity without
resorting to using real or virtual machines.
This is ideal for testing complex multi-host configurations with a minimal
amount of resources on a single machine:
* Each namespace can have its own network setup, including firewall
and QOS configuration.
* Commands can be run in the namespace and will have that specific
view of the network, including running standard network tools and
daemons.
Run without any arguments, `vnetbuild` will present some help on usage.
# COMMANDS
start
: Sets up a series of network namespaces as defined in *CONFIGFILE*.
`vnetbuild` creates interconnected network devices as specified
in the configuration, sets up routing and runs any custom
commands that are given within the namespace.
stop
: Removes any devices from the namespaces defined in *CONFIGFILE*
and kills any processes running with the namespaces, then
removes the namespaces themselves.
status
: For each namespace defined in *CONFIGFILE*, shows if it is active
and if so its network devices and their configuration.
graphviz *OUTFILE*
: Generates a graph of the network defined in *CONFIGFILE*. This
does not need root access, nor does it require the namespaces
to have been started.
*OUTFILE* can be `png` `pdf` or `ps`. If the extension `gv` is
given the output is a graphviz(7) file which you can process
separately.
# RUNNING COMMANDS IN A NAMESPACE
Once you have created a set of network namespaces, you can easily
run any commands you want within them. If for instance you defined
three hosts (`host_a` with IP `10.0.0.1`, `host_b`
with IP `10.0.0.2` and `host_c` with IP `10.0.0.3`)
connected via a common switch `sw0`:
~~~~
# ping host_b and host_c from host_a
sudo ip netns exec host_a ping 10.0.0.2
sudo ip netns exec host_a ping 10.0.0.3
# use netcat to listen on host_a and send data from host_b
# (use two terminals to run the commands simultaneously)
sudo ip netns exec host_a nc -l -p 23
sudo ip netns exec host_b nc -q 0 10.0.0.1 23 < /etc/hosts
# capture traffic passing through the switch, then view it
sudo ip netns exec sw0 tcpdump -i switch -w capfile
wireshark capfile
# Use 'firehol panic' in host_b to block all traffic
# (you could equally load a full config etc.)
sudo ip netns exec host_b firehol panic
# this is now blocked
sudo ip netns exec host_a ping 10.0.0.2
# not blocked (host_b not involved)
sudo ip netns exec host_a ping 10.0.0.3
# obtain a shell for your regular user, only "in" host_c
sudo ip netns exec host_c sudo -i -u $USER
ip a | grep 10.0.0.3
~~~~
# SEE ALSO
* [vnetbuild.conf(5)][] - VNetBuild configuration file
* firehol(1) - FireHOL program
* fireqos(1) - FireQOS program
* [FireHOL Website](http://firehol.org/)
* [VNetBuild Online PDF Manual](http://firehol.org/vnetbuild-manual.pdf)
* [VNetBuild Online Documentation](http://firehol.org/documentation/)

@ -11,6 +11,8 @@ examples_DATA = \
lan-gateway.conf \
office.conf \
icmpv6.conf \
vnetbuild.conf \
vnetbuild-simple.conf \
fireqos.conf
EXTRA_DIST = \

@ -0,0 +1,48 @@
#
# Simple vnetbuild config with one namespace representing the firewall,
# one representing the ISP and the whole internet behind it and a few
# more representing hosts on a LAN.
#
# Start namespace:
# sudo vnetbuild vnetbuild-simple.conf start
#
# Ping from a host on the LAN to an internet address (served by ISP)
# sudo ip netns exec host01 ping 192.0.2.1
# Ping from an internet address (served by ISP) to a host on the LAN:
# sudo ip netns exec isp ping -I 192.0.2.1 10.0.0.2
# Block all traffic through firewall by invoking firehol in the namespace:
# sudo ip netns exec firewall firehol panic
# Clear the firewall with firehol to re-enable the traffic:
# sudo ip netns exec firewall firehol stop
#
host firewall
dev ppp0 192.168.1.1/30
dev veth0 10.0.0.254/8
route default via 192.168.1.2
exec echo 1 > /proc/sys/net/ipv4/ip_forward
exec sed 's:/var/log/ulog/syslogemu.log:/var/log/ulog/firewall.log:' /etc/ulogd.conf > $NSTMP/ulogd.conf
exec /usr/sbin/ulogd -d -c $NSTMP/ulogd.conf
host isp
dev ppp0-wan firewall/ppp0 192.168.1.2/30 192.0.2.1/24 198.51.100.1/24 203.0.113.1/24
route default via 192.168.1.1
exec echo 1 > /proc/sys/net/ipv4/ip_forward
host host01
dev veth0 10.0.0.1/8
route default via 10.0.0.254
host host02
dev veth0 10.0.0.2/8
route default via 10.0.0.254
host host03
dev veth0 10.0.0.2/8
route default via 10.0.0.254
switch lan
dev d01 firewall/veth0
dev d02 host01/veth0
dev d03 host02/veth0
dev d04 host03/veth0

165
examples/vnetbuild.conf Normal file

@ -0,0 +1,165 @@
# This definition sets up a network according to the diagram below which
# covers a multitude of possible scenarios.
#
# Install graphviz to produce a nice graph:
# vnetbuild vnetbuild-complex.conf graphviz vnetbuild-complex.png
#
# To get iptables logs for "fw", ulogd must be installed. A sed command
# is configured which will create a custom logfile from the system standard
# /etc/ulogd.conf - this may need editing to match your system.
#
# Run:
# sudo vnetbuild vnetbuild.conf start
#
# A network namespace is created for each host and switch to keep everything
# isolated. You can apply different networking setups including routing,
# firewalling and QOS in every namespace. Add more "exec" commands to
# automate this at start time.
#
# Note that there are no virtual machines in use, all processing is done
# on the host but with separate views of what the network looks like.
#
# The name of a host or switch in the configuration is the name used for
# the namespace making it easy to use "ip netns exec" to specify where
# commands should run. Examples:
#
# Tcpdump traffic passing through a switch
# sudo ip netns exec sw0 tcpdump -i switch -w capfile
#
# Tcpdump traffic seen by a device on a host
# sudo ip netns exec host12 tcpdump -i veth0 -w capfile
#
# Ping "from" host01 (10.0.0.1) to host12 via switch sw0 and hosts fw and gw:
# sudo ip netns exec host01 ping 192.168.2.12
#
# Start netcat on port 23 of host52 to receive telnet:
# sudo ip netns exec host52 nc -l -p 23
#
# In a different terminal, telnet "from" host21 (10.0.0.1) to host52
# via fw, switches and bridges:
# sudo ip netns exec host21 telnet 10.45.45.52
#
# Start firehol in fw host namespace:
# sudo ip netns exec fw firehol some-firehol.conf start
#
# Panic firehol in fw host namespace (now previous commands are blocked):
# sudo ip netns exec fw firehol panic
#
# Key:
# hostname
# [device] (hosts have just a [veth0] unless otherwise noted)
# (switch)
#
# host21 +- host01 host41
# | | |
# | host22 +- host02 | host42
# | | | (sw0) | |
# | | . . . . . . . . | . . . . . . . . . | |
# | | . [veth0] . | |
# +-----+----[vbr0eth2] | [vbr1eth4]----+-----+
# (sw2) . | | fw | . (sw4)
# . + [vbr0]--+---[vbr1] + .
# (sw3) . | | | . (sw5)
# +-----+----[vbr0eth3] | [vbr1eth5]----+-----+
# | | . [veth1] . | |
# | | . . . . . . . . | . . . . . . . . . | |
# | | | (<direct>) | |
# | host31 [veth0] | host52
# | gw |
# host32 [veth1] [veth2] host51
# (<direct>) / \ (<direct>)
# host11 host12
host fw
dev veth0 10.0.0.254/24
dev veth1 10.1.1.254/24
dev vbr0eth2
dev vbr0eth3
dev vbr1eth4
dev vbr1eth5
bridgedev vbr0 vbr0eth2 vbr0eth3 10.23.23.254/24
bridgedev vbr1 vbr1eth4 vbr1eth5 10.45.45.254/24
route default via 10.1.1.253
exec echo 1 > /proc/sys/net/ipv4/ip_forward
exec sed 's:/var/log/ulog/syslogemu.log:/var/log/ulog/fw.log:' /etc/ulogd.conf > $NSTMP/ulogd.conf
exec /usr/sbin/ulogd -d -c $NSTMP/ulogd.conf
host gw
dev veth0 fw/veth1 10.1.1.253/24
dev veth1 192.168.1.254/24
dev veth2 192.168.2.254/24
route default via 10.1.1.254
exec echo 1 > /proc/sys/net/ipv4/ip_forward
host host01
dev veth0 10.0.0.1/24
route default via 10.0.0.254
host host02
dev veth0 10.0.0.2/24
route default via 10.0.0.254
host host11
dev veth0 gw/veth1 192.168.1.11/24
route default via 192.168.1.254
host host12
dev veth0 gw/veth2 192.168.2.12/24
route default via 192.168.2.254
host host21
dev veth0 10.23.23.21/24
route default via 10.23.23.254
host host22
dev veth0 10.23.23.22/24
route default via 10.23.23.254
host host31
dev veth0 10.23.23.31/24
route default via 10.23.23.254
host host32
dev veth0 10.23.23.32/24
route default via 10.23.23.254
host host41
dev veth0 10.45.45.41/24
route default via 10.45.45.254
host host42
dev veth0 10.45.45.42/24
route default via 10.45.45.254
host host51
dev veth0 10.45.45.51/24
route default via 10.45.45.254
host host52
dev veth0 10.45.45.52/24
route default via 10.45.45.254
switch sw0
dev d01 fw/veth0
dev d02 host01/veth0
dev d03 host02/veth0
switch sw2
dev d01 fw/vbr0eth2
dev d02 host21/veth0
dev d03 host22/veth0
switch sw3
dev d01 fw/vbr0eth3
dev d02 host31/veth0
dev d03 host32/veth0
switch sw4
dev d01 fw/vbr1eth4
dev d02 host41/veth0
dev d03 host42/veth0
switch sw5
dev d01 fw/vbr1eth5
dev d02 host51/veth0
dev d03 host52/veth0

@ -1,3 +1,3 @@
# Process this file with automake to produce Makefile.in
sbin_SCRIPTS = firehol fireqos link-balancer
sbin_SCRIPTS = firehol fireqos link-balancer vnetbuild

650
sbin/vnetbuild.in Executable file

@ -0,0 +1,650 @@
#!/bin/bash
#
# vnetbuild - linked network namespace setup for humans...
#
# Copyright
#
# Copyright (C) 2015 Phil Whineray <phil@sanewall.org>
# Copyright (C) 2015 Costa Tsaousis <costa@tsaousis.gr>
#
# License
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# 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.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# See the file COPYING for details.
#
# make sure sbin is included in the path
# it seems that pppd ip-up.d script need this
export PATH="$PATH:/sbin:/usr/sbin:/usr/local/sbin"
get_version() {
GIT_REF='$Format:%d,commit-%h$'
local IFS=":(), "
set -- "$GIT_REF"
ver='$Id$'
for i in $@
do
case "$i" in
*[0-9].[0.9]*)
echo "$i" | sed -e 's/^v//'
return 0
;;
commit-[0-9a-zA-Z]*)
ver="$i"
;;
esac
done
echo "$ver"
return 0
}
VERSION=$(get_version)
emit_version() {
cat <<EOF
FireHOL vnetbuild $VERSION
(C) Copyright 2015 Phil Whineray <phil@firehol.org>
(C) Copyright 2015 Costa Tsaousis <costa@tsaousis.gr>
FireHOL is distributed under the GPL v2+.
Home Page: http://firehol.org
-------------------------------------------------------------------------
Get notified of new FireHOL releases by subscribing to the mailing list:
http://lists.firehol.org/mailman/listinfo/firehol-support/
-------------------------------------------------------------------------
EOF
}
needroot=Y
haderror=""
#gvprog=dot
#gvprog=sfdp
gvprog=neato
setup="$1"
mode="$2"
outfile="$3"
case "$mode" in
""|-h|help|-v|version)
mode=
needroot=
haderror="Y"
;;
start|stop|status)
:
;;
graphviz)
needroot=
case "$outfile" in
*.gv|"")
graphviz=cat
;;
*.ps)
format=ps
graphviz="$gvprog -T$format"
;;
*.pdf)
format=pdf
graphviz="$gvprog -T$format"
;;
*.png)
format=png
graphviz="$gvprog -T$format"
;;
*)
1>&2 echo "Unrecognised file extension: $mode"
haderror="Y"
;;
esac
;;
*)
1>&2 echo "Unrecognised mode: $mode"
haderror="Y"
needroot=
;;
esac
if [ "$mode" = "" ]
then
emit_version
fi
if [ "$needroot" -a "`id -r -u`" != "0" ]
then
echo "Error: must be root to use '$mode'"
haderror="Y"
fi
if [ "$haderror" -o $# -lt 2 ]
then
echo ""
echo "Usage: sudo vnetbuild CONFIGFILE stop|start|status"
echo " or: vnetbuild CONFIGFILE graphviz OUTFILE.{gv,png,pdf,ps}"
exit 1
else
shift
shift
fi
setupbase="$(basename $setup)"
errline=""
error=""
if ! MYTMP="`mktemp -d -t vnetbuild-XXXXXX`"
then
echo >&2
echo >&2
echo >&2 "Cannot create temporary directory."
echo >&2
exit 1
fi
myexit() {
status=$?
if [ "$error" != "" ]
then
echo "$setupbase: line $errline: $error"
fi
rm -rf $MYTMP
exit $status
}
trap myexit INT
trap myexit HUP
trap myexit 0
CURDIR=`pwd`/
export CURDIR
set -e
mkdir $MYTMP/setup
sed = "$setup" > $MYTMP/withnum
(echo "cd $CURDIR"; sed -e 'N;s/\n/\t/' -e 's/^/lineno=/' -e '/exec/s/[<>|&]/\\&/g' $MYTMP/withnum) > $MYTMP/setup/$setupbase
mkdir $MYTMP/ns
mkdir $MYTMP/runtime-lines
current_name=
create_namespace() {
errline=$lineno
local type="$1"
current_name="$2"
NSTMP=$MYTMP/ns/$current_name
if [ -d $NSTMP ]
then
error="$current_name: $(cat $NSTMP/type) already defined"
return 1
fi
mkdir $NSTMP
mkdir $NSTMP/devices
mkdir $NSTMP/devicepairs
echo $type > $NSTMP/type
echo 0 > $NSTMP/forward
> $NSTMP/routes
> $NSTMP/devlist
> $NSTMP/pairlist
> $NSTMP/bridgelist
echo $current_name >> $MYTMP/nslist
echo $errline > $MYTMP/runtime-lines/$current_name
}
host() {
errline=$lineno
create_namespace host "$1"
}
switch() {
errline=$lineno
create_namespace switch "$1"
}
dev() {
errline=$lineno
device="$1"
shift
if [ ! "$current_name" ]
then
error="cannot define dev outside of a host or switch"
return 1
fi
if [ -f $NSTMP/devices/$device ]
then
error="$current_name/$device: already defined"
return 1
fi
local otherns=
local otherdev=
case $1 in
*/[a-zA-Z]*)
otherns=$(echo $1 | cut -f1 -d/)
otherdev=$(echo $1 | cut -f2 -d/)
shift
if [ -f $MYTMP/ns/$otherns/devicepairs/$otherdev ]
then
error="$otherns/$otherdev: already has paired device"
return 1
fi
;;
esac
local type="$(cat $NSTMP/type)"
if [ "$*" != "" -a "$type" = "switch" ]
then
error="device in switch may not specify an IP address"
return 1
fi
f=$NSTMP/devices/$device
> $f
for ip in "$@"
do
case $ip in
*/*)
echo "$ip" >> $f
;;
*)
error="IP address should be expressed as ip/mask"
return 1
;;
esac
done
if [ "$otherdev" ]
then
if [ ! -d $MYTMP/ns/$otherns ]
then
error="$otherns undefined"
return 1
fi
echo "$current_name $device" > $MYTMP/ns/$otherns/devicepairs/$otherdev
echo "n/a n/a" > $NSTMP/devicepairs/$device
echo "$otherns $otherdev" >> $NSTMP/pairlist
echo $errline > $MYTMP/runtime-lines/$otherns-pair-$otherdev
fi
echo $device >> $NSTMP/devlist
echo $errline > $MYTMP/runtime-lines/$current_name-dev-$device
return 0
}
route() {
errline=$lineno
if [ ! "$current_name" ]
then
error="can only specify route in a host"
return 1
fi
local type="$(cat $NSTMP/type)"
if [ "$type" = "switch" ]
then
error="can only specify route in a host"
return 1
fi
echo "$*" >> $NSTMP/routes
echo $errline >> $MYTMP/runtime-lines/$current_name-routes
return 0
}
bridgedev() {
errline=$lineno
device="$1"
shift
if [ ! "$current_name" ]
then
error="can only specify bridgedev in a host"
return 1
fi
local type="$(cat $NSTMP/type)"
if [ "$type" = "switch" ]
then
error="can only specify bridgedev in a host"
return 1
fi
if [ -f $NSTMP/devices/$device ]
then
error="$current_name/$device: already defined"
return 1
fi
ipf=$NSTMP/devices/$device
devf=$ipf-bridged
> $ipf
> $devf
for ipordev in "$@"
do
case $ipordev in
*/*)
echo "$ipordev" >> $ipf
;;
*)
echo "$ipordev" >> $devf
;;
esac
done
echo $device >> $NSTMP/bridgelist
echo $errline > $MYTMP/runtime-lines/$current_name-dev-$device
return 0
}
exec() {
errline=$lineno
if [ ! "$current_name" ]
then
error="can only specify exec in a host or switch"
return 1
fi
echo "$*" >> $NSTMP/exec
echo $errline >> $MYTMP/runtime-lines/$current_name-exec
return 0
}
cd $MYTMP/setup
. $setupbase
errline=""
cd $CURDIR
exists_ns() {
if [ "$(ip netns list | grep "^$1\$")" ]
then
return 0
else
return 1
fi
}
dev_in_ns() {
ip netns exec $1 ip link list | grep "^[0-9]" | cut -d: -f2 | tr -d ' '
}
get_pids() {
# Not in all versions:
# ip netns pids $1
find -L /proc/[0-9]*/ns -maxdepth 1 -samefile /var/run/netns/$1 2>/dev/null | cut -f3 -d/
}
shutdown_ns() {
for i in $(dev_in_ns $1)
do
ip netns exec $1 ip link set $i down
done
pids=$(get_pids $1)
if [ "$pids" ]; then kill $pids; sleep 1; fi
pids=$(get_pids $1)
if [ "$pids" ]; then kill -9 $pids; fi
}
startup_ns() {
for i in $(dev_in_ns $1)
do
ip netns exec $1 ip link set $i up
done
}
while read ns
do
while read dev
do
read errline < $MYTMP/runtime-lines/$ns-dev-$dev
if [ ! -f $MYTMP/ns/$ns/devicepairs/$dev ]
then
error="$ns/$dev has no paired device"
exit 1
fi
done < $MYTMP/ns/$ns/devlist
while read otherns otherdev
do
read errline < $MYTMP/runtime-lines/$otherns-pair-$otherdev
if [ ! -f $MYTMP/ns/$otherns/devices/$otherdev ]
then
error="$otherns/$otherdev not defined to be paired with"
exit 1
fi
done < $MYTMP/ns/$ns/pairlist
done < $MYTMP/nslist
if [ "$mode" = "stop" -o "$mode" = "start" ]
then
while read ns
do
read errline < $MYTMP/runtime-lines/$ns
error="shutting down namespace"
exists_ns $ns && shutdown_ns $ns
done < $MYTMP/nslist
while read ns
do
read errline < $MYTMP/runtime-lines/$ns
error="deleting namespace"
exists_ns $ns && ip netns del $ns
done < $MYTMP/nslist
error=""
fi
if [ "$mode" = "stop" ]
then
exit 0
fi
if [ "$mode" = "start" ]
then
while read ns
do
read errline < $MYTMP/runtime-lines/$ns
error="adding namespace"
type="$(cat $MYTMP/ns/$ns/type)"
ip netns add $ns
if [ "$type" = "switch" ]
then
error="adding bridge to switch namespace"
ip netns exec $ns brctl addbr switch
fi
done < $MYTMP/nslist
while read ns
do
type="$(cat $MYTMP/ns/$ns/type)"
while read dev
do
read errline < $MYTMP/runtime-lines/$ns-dev-$dev
read ons odev < $MYTMP/ns/$ns/devicepairs/$dev
if [ "$ons" != "n/a" ]
then
error="adding virtual ethernet to $type namespace"
ip link add $dev netns $ns type veth peer netns $ons name $odev
else
: # gets set up from the other end
fi
if [ "$type" = "switch" ]
then
error="adding virtual ethernet to bridge"
ip netns exec $ns brctl addif switch $dev
fi
while read ip
do
error="adding ip address to virtual ethernet"
ip netns exec $ns ip addr add $ip broadcast + dev $dev
done < $MYTMP/ns/$ns/devices/$dev
done < $MYTMP/ns/$ns/devlist
while read bridge
do
read errline < $MYTMP/runtime-lines/$ns-dev-$bridge
error="adding bridge to host namespace"
ip netns exec $ns brctl addbr $bridge
while read dev
do
error="adding virtual interface to bridge"
ip netns exec $ns brctl addif $bridge $dev
done < $MYTMP/ns/$ns/devices/$bridge-bridged
while read ip
do
error="adding ip to virtual interface"
ip netns exec $ns ip addr add $ip broadcast + dev $bridge
done < $MYTMP/ns/$ns/devices/$bridge
done < $MYTMP/ns/$ns/bridgelist
done < $MYTMP/nslist
while read ns
do
echo "Starting namespace $ns"
read errline < $MYTMP/runtime-lines/$ns
error="starting namespace"
startup_ns $ns
while read route
do
errline=$(tr "\n" "/" < $MYTMP/runtime-lines/$ns-routes | sed -e s:/$::)
error="adding route to $ns"
ip netns exec $ns ip route add $route
done < $MYTMP/ns/$ns/routes
if [ -f $MYTMP/ns/$ns/exec ]
then
errline=$(tr "\n" "/" < $MYTMP/runtime-lines/$ns-exec | sed -e s:/$::)
error="running exec for $ns"
ip netns exec $ns sh -e $MYTMP/ns/$ns/exec
fi
done < $MYTMP/nslist
error=""
fi
if [ "$mode" = "status" ]
then
while read ns
do
echo "---------------------- $ns --------------------"
if exists_ns $ns
then
ip netns exec $ns ip addr show
ip netns exec $ns ip route show
ip netns exec $ns brctl show
else
echo "Namespace not running"
fi
echo ""
done < $MYTMP/nslist
fi
if [ "$mode" = "graphviz" ]
then
gv=$MYTMP/gv
echo "/* process e.g.: $gvprog -Tps filename.gv -o filename.ps */" >$gv
echo "graph NET {" >>$gv
if [ "$format" != "png" ]
then
echo "size=7; /* Max size 7 inches */" >>$gv
fi
echo "overlap=prism;" >>$gv
echo "edge [color=blue,style=dashed];" >>$gv
while read ns
do
type="$(cat $MYTMP/ns/$ns/type)"
if [ "$type" = "switch" ]
then
echo "switch_$ns [shape=polygon,sides=4,skew=.4,label=\"$ns\"];" >>$gv
else
echo -n "host_$ns [shape=record,label=\"$ns" >>$gv
while read route
do
echo -n "\\n$route" >>$gv
done < $MYTMP/ns/$ns/routes
while read bridge
do
echo -n "|{<$bridge> $bridge" >>$gv
while read ip
do
echo -n "\\n$ip" >>$gv
done < $MYTMP/ns/$ns/devices/$bridge
while read dev
do
echo -n "|{" >>$gv
echo -n "<$dev> $dev" >>$gv
while read ip
do
echo -n "\n$ip" >>$gv
done < $MYTMP/ns/$ns/devices/$dev
echo -n "}" >>$gv
echo "$bridge" > $MYTMP/ns/$ns/suppress-$dev
done < $MYTMP/ns/$ns/devices/$bridge-bridged
echo -n "}" >>$gv
done < $MYTMP/ns/$ns/bridgelist
while read dev
do
if [ ! -f $MYTMP/ns/$ns/suppress-$dev ]
then
echo -n "|<$dev> $dev" >>$gv
while read ip
do
echo -n "\\n$ip" >>$gv
done < $MYTMP/ns/$ns/devices/$dev
fi
done < $MYTMP/ns/$ns/devlist
echo "\"];" >>$gv
fi
done < $MYTMP/nslist
while read ns
do
type="$(cat $MYTMP/ns/$ns/type)"
while read dev
do
read ons odev < $MYTMP/ns/$ns/devicepairs/$dev
if [ "$ons" != "n/a" ]
then
otype="$(cat $MYTMP/ns/$ons/type)"
if [ "$type" = "switch" ]
then
from="switch_$ns"
else
from="host_$ns:$dev"
fi
if [ "$otype" = "switch" ]
then
to="switch_$ons"
else
to="host_$ons:$odev"
fi
echo "$from -- $to;" >>$gv
else
: # gets set up from the other end
fi
done < $MYTMP/ns/$ns/devlist
done < $MYTMP/nslist
echo "}" >>$gv
if [ "$outfile" = "" ]
then
$graphviz $gv
else
$graphviz $gv > "$outfile"
fi
fi
exit 0