Open Visual Traceroute, Opensuse Leap 42.1 and sudo – howto – I

IP GeoLocation is useful – not only in the context of professional penetration testing, but also for answering very legitimate questions of both system administrators and normal users. E.g.: Where does my web hosting provider really host my website or all my cloud data? In Germany with relatively strict laws regarding personal data protection, the EU or somewhere else where privacy may not be respected to the full extent I expect?

The German provider 1&1, for example, is very active on the French market, too, but at least very many, if not all French websites seem to be hosted on servers in German computation centers. Good to know for a French customer, both legally and also in case of technical problems.

Also sometimes admins may need to clarify why and where there are latency problems, when a user tries to connect to e.g. web or database servers over the Internet. Another field where IP GeoLocation is very helpful is the analysis of the origin of spam mails from the IP information in mail headers. And, and …

Of course, there are GeoLocation services available on the Internet – but the documentation of result data very often is pretty inconvenient. Now, you could write e.g. a python program for GeoLocation on your own – which is a nice exercise, but you will soon find out that you must have a profound knowledge about networking protocol details. So, from the point of view of a standard Linux user or admin it would be nice to have an easy to use, graphical and open-source solution for IP GeoLocation available on the desktop. Such a program is “Open Visual Traceroute” [OVT] of Leo Lewis.

OVT is Java based; for IP GeoLocation it uses the CityLight-database of the company Mindmax. OVT has a nice graphical interface for the geographical display of the results of tracerouting. It has some simple but helpful log and documentation functionality – and even allows for some “sniffing” inspection into data traffic on network interfaces.

Note that using the latter capability has legal implications – so, always (!) get the explicit allowance from your company owners, if you intend to use this functionality of OVT – e.g. in the course of penetration test. In general: Consider possible legal restrictions of the use of OVT (especially in Germany) – and do it carefully.

This having said: Can we technically use OVT on an Opensuse Leap 42.1 system? The answer is yes, but …. The “BUT” in this case does not refer to functionality, but to general security considerations, which we shall discuss in a later article.

However, let us first have a look at some elementary obstacles which prevent the successful execution of the program on an Opensuse Leap desktop. Starting the application as a normal user leads to a variety of different error messages from the Java side, problems with X11 access and right problems regarding the essential package capturing functionality.

One reason for this behavior is a general problematic aspect of the program: It requires root rights for network analysis capabilities. You think of “sudo” ? Yeah, but …. Actually one can learn a bit about “sudo” when dealing with OVT.

In this article I shall describe 3 simple ways of using OVT on Opensuse Leap 42.1. Note that these approaches are only reasonable for single user machines! Actually, due to its special sniffing capabilities OVT is a program to which only selected users should get access to on a multiuser system. In addition running Java and network package analysis as root leaves us with an uneasy feeling …. But let us first get OVT running at all.

In a second article we restrict the usage of OVT to selected users – and improve the startup of OVT for these users a bit. During the discussion I touch some general “sudo” issues, which may be useful in other contexts. A third article then
argues for using the program in a chroot jail or virtual environment to improve security.

I have posted some of my approaches also in the discussion forum of OVT on Sourceforge (https://sourceforge.net/p/openvisualtrace/discussion/1799338/thread/76f2b798/).

Download / Installation

Installation of OVT is quite simple and basically means to place a folder into some reasonable branch of the file system. A shell script is used to start the program.

The web site http://visualtraceroute.net/ offers the download of different installation packages for different operating systems. For our Opensuse system the most reasonable choice is “Download Universal”. The zip-file behind it expands on our SuSE machine into a folder “OpenVisualTraceRoute1.6.3” with a shell script “ovtr.sh” at the highest level and some required subfolders below. The additional “README.txt” file informs about the present and older versions of OVT – in my case I used version 1.6.3.

On my system I have placed the contents of the mentioned folder into a directory “/opt/ovt/”. But you may take another choice. We abbreviate the full path to this installation directory during the rest of this article by “/PATH/TO/OVT/” and call it “OVT-directory”. The OVT-directory contains a “lib” subdirectory which supplies the required “jar” archives.

In principle the OVT program could be started from the OVT-directory by executing the “ovtr.sh” script there. However, this does not work on OS Leap 42.1 – and results in a variety of error messages.

Requirements for running OVT with full functionality

All steps to overcome the cascade of different errors can better be understood by the regarding the four requirements that must be fulfilled to get access to OVT’s capabilities:

  1. The program must find the “libpcap” library. Actually, in the present version OVT assumes that this library can be found in form of a file “libpcap.so.0.8” in some directory of the PATH environment variable. However, such a file does not exist on Opensuse Leap 42.1!
  2. The program needs to run with root rights (or certain network privileges on a system that support file capabilities). The reason is that it uses libpcap, i.e. network packet capturing on detected network interfaces.
  3. OVT must find and read the shell environment variable DISPLAY – which under some circumstances is not completely trivial.
  4. OVT must get the right to access the X11 display of the non-privileged user who started the X11 desktop.

This list is the result of some trial and error testing plus a closer look at some discussions at Sourceforge.

Make OVT start at all – as a non-privileged user – but with reduced functionality

To get the program running at all for a non-privileged user we must modify the startup script on Opensuse. So, please, change the content of “ovtr.sh” to

#!/bin/bash
#sudo java -Xmx512m -jar org.leo.traceroute.jar
java -Xmx512m -jar org.leo.traceroute.jar

I.e., omit the “sudo” command. The reason for this will become clearer later on. In addition you must the assign execution right to “ovtr.sh”. You then get OVT running in the following form:

me@mytux:/opt/ovt> ./ovtr.sh
13:01:33.276 [main] INFO  org.leo.traceroute.Main - Open Visual Traceroute 1.6.3 
13:01:33.284 [main] INFO  org.leo.traceroute.install.Env - Java run-time version: 1.8.0_91
13:01:33.285 [main] INFO  org.leo.traceroute.
install.Env - NASA World Wind Java 2.0 2.0.0
13:01:33.285 [main] INFO  org.leo.traceroute.install.Env - /usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
13:01:33.285 [main] INFO  org.leo.traceroute.install.Env - OS:Linux / arch:amd64
Locale en_GB
13:01:36.063 [SwingWorker-pool-1-thread-1] INFO  o.leo.traceroute.core.geo.GeoService - Use geoip db /home/rmo/ovtr/GeoLiteCity.dat which is 8 day(s) old
13:01:36.772 [SwingWorker-pool-1-thread-1] WARN  o.leo.traceroute.core.ServiceFactory - Cannot find a suitable network device for tracing.
java.lang.UnsatisfiedLinkError: /opt/ovt/native/linux/x64/libjpcap.so: libpcap.so.0.8: Kann die Shared-Object-Datei nicht öffnen: Datei oder Verzeichnis nicht gefunden
        at java.lang.ClassLoader$NativeLibrary.load(Native Method) ~[na:1.8.0_91]
        at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1941) ~[na:1.8.0_91]
        at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1857) ~[na:1.8.0_91]
        at java.lang.Runtime.loadLibrary0(Runtime.java:870) ~[na:1.8.0_91]
        at java.lang.System.loadLibrary(System.java:1122) ~[na:1.8.0_91]
        at jpcap.JpcapCaptor.<clinit>(JpcapCaptor.java:251) ~[jpcap.jar:na]
        at org.leo.traceroute.core.network.JPcapNetworkService.init(JPcapNetworkService.java:90) ~[org.leo.traceroute.jar:na]
        at org.leo.traceroute.core.ServiceFactory.init(ServiceFactory.java:110) [org.leo.traceroute.jar:na]
        at org.leo.traceroute.Main$4.doInBackground(Main.java:115) [org.leo.traceroute.jar:na]
        at org.leo.traceroute.Main$4.doInBackground(Main.java:111) [org.leo.traceroute.jar:na]
        at javax.swing.SwingWorker$1.call(SwingWorker.java:295) [na:1.8.0_91]
        at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_91]
        at javax.swing.SwingWorker.run(SwingWorker.java:334) [na:1.8.0_91]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_91]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_91]
        at java.lang.Thread.run(Thread.java:745) [na:1.8.0_91]
13:01:36.776 [SwingWorker-pool-1-thread-1] WARN  o.l.t.c.n.JNetCapNetworkService - Cannot find a suitable network device for tracing.
java.lang.UnsatisfiedLinkError: /opt/ovt/native/linux/x64/libjnetpcap.so: libpcap.so.0.8: Kann die Shared-Object-Datei nicht öffnen: Datei oder Verzeichnis nicht gefunden
        at java.lang.ClassLoader$NativeLibrary.load(Native Method) ~[na:1.8.0_91]
        at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1941) ~[na:1.8.0_91]
        at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1857) ~[na:1.8.0_91]
        at java.lang.Runtime.loadLibrary0(Runtime.java:870) ~[na:1.8.0_91]
        at java.lang.System.loadLibrary(System.java:1122) ~[na:1.8.0_91]
        at org.jnetpcap.Pcap.<clinit>(Unknown Source) ~[jnetpcap.jar:1.3.0]
        at org.leo.traceroute.core.network.JNetCapNetworkService.init(JNetCapNetworkService.java:71) ~[org.leo.traceroute.jar:na]
        at org.leo.traceroute.core.ServiceFactory.init(ServiceFactory.java:111) [org.leo.traceroute.jar:na]
        at org.leo.traceroute.Main$4.doInBackground(Main.java:115) [org.leo.traceroute.jar:na]
        at org.leo.traceroute.Main$4.doInBackground(Main.java:111) [org.leo.traceroute.jar:na]
        at javax.swing.SwingWorker$1.call(SwingWorker.java:295) [na:1.8.0_91]
        at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_91]
        at javax.swing.SwingWorker.run(SwingWorker.java:334) [na:1.8.0_91]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_91]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_91]
        at java.lang.Thread.run(Thread.java:745) [na:1.8.0_91]
13:01:37.272 [AWT-EventQueue-0] INFO  org.leo.traceroute.Main - Startup completed in 4001ms

 

Despite the many warnings the application opens and displays the following graphical elements, which are quite self-explanatory.
ovt1

However, trying to traceroute some web-address by pressing the orange button results in the displayed error. The reason is that “/usr/sbin” is not included in the PATH variable. Actually, at http://visualtraceroute.net/installation it is recommend to also include

export PATH=”$PATH:/usr/sbin/”; java -Xmx512m -jar -Djava.awt.headless=false org.leo.traceroute.jar

in “ovtr.sh”. Lets do it

#!/bin/bash
export PATH="$PATH:/usr/sbin/"; java -Xmx512m -jar org.leo.traceroute.jar

 
Afterwards, we can run “traceroute” ….
ovt3

However, if we compare our screenshot with illustrations on the site http://visualtraceroute.net/ we detect that our interface lacks a button, e.g. for sniffing. We come back to this a bit later.

Why did we need the “/usr/sbin” in our PATH? Because OVT actually uses the “OS’s traceroute” command as a fallback – if it cannot analyze network packages itself another way. We can conclude this fact from OVT’s “settings”-options (tools button on the right):

ovt2

The option “Use OS traceroute” is set to “Yes” in the combobox – and, under the given conditions, this option cannot be changed.

Give OVT the required libpcap !

Actually, the native Linux traceroute command is a bit limited in its capabilities. Therefore, its results are sometimes not convincing – in very many examples the traceroute analysis is stopped by restrictions in intermediate computation centers. A look at the discussions on OVT at Sourceforge and the version history reveals that OVT, therefore, has its own traceroute program, which is based on capturing and analyzing network protocol packets:

The access to “libpcap” is not only required for sniffing, but also for tracerouting!

The feedback on our terminal from the program start shows 2 times that “libpcap.so.0.8” is missing. In my opinion, for Linux systems, it would have been more reasonable to search for “libpcap.so.1”. But things are easy to remedy. As root we search for “libpcap.so*”, find it under “/usr/lib64” and simply add a new soft link there:

mytux:/usr/lib64 # ln -s /usr/lib64/libpcap.so.1 libpcap.so.0.8

Actually, “libpcap.so.1” itself is linked to the real version presently used on Opensuse Leap 42.1 systems, namely “libpcap.so.1.5.3”:

mytux:/usr/lib64 # ls -lisa | grep libpcap
 793187     0 lrwxrwxrwx   1 root root       23 Aug 12 15:00 libpcap.so.0.8 -> /usr/lib64/libpcap.so.1
 797513     0 lrwxrwxrwx   1 root root       16 Oct 29  2015 libpcap.so.1 -> libpcap.so.1.5.3
 793262   276 -rwxr-xr-x   1 root root   279312 Oct 25  2015 libpcap.so.1.5.3  

 

A new OVT start now results in clean messages without any errors or warnings

me@mytux:/opt/ovt> ./ovtr.sh
15:03:33.154 [main] INFO  org.leo.traceroute.Main 
- Open Visual Traceroute 1.6.3 
15:03:33.166 [main] INFO  org.leo.traceroute.install.Env - Java run-time version: 1.8.0_91
15:03:33.167 [main] INFO  org.leo.traceroute.install.Env - NASA World Wind Java 2.0 2.0.0
15:03:33.167 [main] INFO  org.leo.traceroute.install.Env - /usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
15:03:33.168 [main] INFO  org.leo.traceroute.install.Env - OS:Linux / arch:amd64
Locale en_GB
15:03:35.468 [SwingWorker-pool-1-thread-1] INFO  o.leo.traceroute.core.geo.GeoService - Use geoip db /home/rmo/ovtr/GeoLiteCity.dat which is 8 day(s) old
15:03:36.906 [AWT-EventQueue-0] INFO  org.leo.traceroute.Main - Startup completed in 3757ms

 
However, still no sniffing button and no change in the OVT settings – OVT still uses “/usr/sbin/traceroute”.

Does OVT work for user root?

The reason why OVT still does not work as expected is that packet capturing requires root rights or – on systems supporting file capabilities – the setting of some special rights for certain files (we come back to this in the last article of this mini series). Ever tried “wireshark” or “tcpdump”? For these programs – or parts of them – special rights are required, too. To get a step further we now again take the original, unmodified “ovtr.sh” with the sudo command

#!/bin/bash
sudo java -Xmx512m -jar org.leo.traceroute.jar

and try to run it as user “root”. The “sudo” included in the script should do no harm now as we already are root. Or, at least we think so …

So, as an unprivileged user we open a root terminal on our desktop, type in the root password to get shell access or use “su -” in a standard terminal. But, unfortunately, we get a new error:

  
mytux:/opt/ovt # ./ovtr.sh
15:26:39.153 [main] INFO  org.leo.traceroute.Main - Open Visual Traceroute 1.6.3 
15:26:39.161 [main] INFO  org.leo.traceroute.install.Env - Java run-time version: 1.8.0_91
15:26:39.161 [main] INFO  org.leo.traceroute.install.Env - NASA World Wind Java 2.0 2.0.0
15:26:39.162 [main] INFO  org.leo.traceroute.install.Env - /usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
15:26:39.162 [main] INFO  org.leo.traceroute.install.Env - OS:Linux / arch:amd64
Locale en_GB
15:26:39.636 [main] ERROR org.leo.traceroute.Main - Uncaught error
java.awt.HeadlessException: 
No X11 DISPLAY variable was set, but this program performed an operation which requires it.
        at java.awt.GraphicsEnvironment.checkHeadless(GraphicsEnvironment.java:204) ~[na:1.8.0_91]
        at java.awt.Window.<init>(Window.java:536) ~[na:1.8.0_91]
        at java.awt.Frame.<init>(Frame.java:420) ~[na:1.8.0_91]
        at javax.swing.JFrame.<init>(JFrame.java:232) ~[na:1.8.0_91]
        at org.leo.traceroute.ui.TraceRouteFrame.<init>(TraceRouteFrame.java:52) ~[org.leo.traceroute.jar:na]
        at org.leo.traceroute.Main.main(Main.java:87) ~[org.leo.traceroute.jar:na]

 
What is the reason for this failure? No X11 DISPLAY variable? An “env” command shows:

mysystem:/opt/ovt # env | grep DISPL
DISPLAY=:0

It took me a bit to see it: The origin of the error actually is the sudo-command in “ovtr.sh” ! Why? The important thing to be aware of is:

“sudo” does not invoke any kind of shell. So, even if the user root had defined special startup scripts for login or execution shells, which specified the export of DISPLAY, such scripts would not be invoked by “sudo” and as a result the DISPLAY variable would be missing. Therefore, Java complains about the X11 DISPLAY variable!

But, as we know, on Opensuse systems a graphical program started from a root terminal/shell
under KDE does know the DISPLAY variable and does start on the unprivileged user’s X11 desktop.
[ Off topic: On OS LEAP 42.1 KDE programs are actually started from the root terminal with ignoring basic KDE settings (font sizes, etc.) of the unprivileged and the root user – which is a mess in general, but it is unimportant here as Java’s AWT is responsible for the graphics, fonts, etc of the OVT interface.]

So, again: What about turning off the “sudo”?

Solution 1: Run OVT as user root – but without “sudo” in the start script ovtr.sh

Actually, any normal user on a standard (!) unmodified Opensuse system would have to know the root password in case he/she wanted to perform a command with “sudo”. The reason for this is a standard entry in the file “/etc/sudoers”:

Defaults        targetpw 

 
Note: On other systems (as Kali) this entry may not be active after installation. But with this entry you may as well start OVT directly from a root shell. “sudo” would ask you for the root password anyway. So, our first working solution will be to start OVT as user root from a root shell, but without the “sudo” in the start script “ovtr.sh”:

#!/bin/bash
java -Xmx512m -jar org.leo.traceroute.jar

And really:

  
mysystem:/opt/ovt # ./ovtr.sh
19:17:23.021 [main] INFO  org.leo.traceroute.Main - Open Visual Traceroute 1.6.3 
19:17:23.029 [main] INFO  org.leo.traceroute.install.Env - Java run-time version: 1.8.0_91
19:17:23.030 [main] INFO  org.leo.traceroute.install.Env - NASA World Wind Java 2.0 2.0.0
19:17:23.030 [main] INFO  org.leo.traceroute.install.Env - /usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
19:17:23.030 [main] INFO  org.leo.traceroute.install.Env - OS:Linux / arch:amd64
Locale en_GB
19:17:25.377 [SwingWorker-pool-1-thread-1] INFO  o.leo.traceroute.core.geo.GeoService - Use geoip db /root/ovtr/GeoLiteCity.dat which is 0 day(s) old
19:17:27.110 [pool-2-thread-1] INFO  o.leo.traceroute.core.ServiceFactory - Try using device eth0 null
19:17:27.275 [pool-2-thread-2] INFO  o.leo.traceroute.core.ServiceFactory - Try using device br0 null
19:17:27.446 [pool-2-thread-3] INFO  o.leo.traceroute.core.ServiceFactory - Try using device virbr_vmw null
19:17:28.509 [pool-2-thread-8] INFO  o.leo.traceroute.core.ServiceFactory - Try using device virbr1 null
19:17:29.659 [pool-2-thread-9] INFO  o.leo.traceroute.core.ServiceFactory - Try using device vmnet1 null            
19:17:30.682 [pool-2-thread-10] INFO  o.leo.traceroute.core.ServiceFactory - Try using device virbr2 null           
19:17:31.665 [pool-2-thread-11] INFO  o.leo.traceroute.core.ServiceFactory - Try using device virbr3 null           
19:17:32.666 [pool-2-thread-12] INFO  o.leo.traceroute.core.ServiceFactory - Try using device vmnet3 null           
19:17:33.683 [pool-2-thread-13] INFO  o.leo.traceroute.core.ServiceFactory - Try using device virbr4 null           
19:17:34.703 [pool-2-thread-14] INFO  o.leo.traceroute.core.ServiceFactory - Try using device virbr5 null
19:17:35.688 [pool-2-thread-15] INFO  o.leo.traceroute.core.ServiceFactory - Try using device virbr6 null
19:17:36.718 [pool-2-thread-17] INFO  o.leo.traceroute.core.ServiceFactory - Try using device lo null
19:17:38.806 [AWT-EventQueue-0] INFO  org.leo.traceroute.Main - Startup completed in 15790ms 

 
Obviously, OVT now detects some network devices on the system. Do not worry, you probably will not see as many network devices as I do. I have a lot of virtual machines installed and attached to a virtual Linux bridge of my test system… 🙂

And, hey, we now see the button for
sniffing – and therefore know that packet capturing is active.

ovt4

And: By some clever intelligence of OVT’s packet analysis we now arrive at the real hosting place of the web address we tracerouted (compare the above image with the first picture where the Linux traceroute was used). Good!

I have experienced the better and more thorough analysis of OVT’s own traceroute routine in other examples, too.

Solution 2: Run OVT with “sudo”-command – but modify it!

The next challenge for me was to make the sudo-command in the standard script work. The required trick is pretty simple: as sudo itself does not invoke a shell by itself, we must explicitly force sudo to do it:

#!/bin/bash
sudo /bin/bash -c ‘export DISPLAY=:0; java -Djava.awt.headless=false -Xmx512m -jar org.leo.traceroute.jar’

Take care of the positions of single quotation marks! When we now start “ovtr.sh” as an unprivileged user, we are prepared to enter the root password. And then – what do you guess?

me@mysystem:/opt/ovt> ./ovtr.sh 
14:55:43.581 [main] INFO  org.leo.traceroute.Main - Open Visual Traceroute 1.6.3 
14:55:43.589 [main] INFO  org.leo.traceroute.install.Env - Java run-time version: 1.8.0_91
14:55:43.590 [main] INFO  org.leo.traceroute.install.Env - NASA World Wind Java 2.0 2.0.0
14:55:43.590 [main] INFO  org.leo.traceroute.install.Env - /usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
14:55:43.590 [main] INFO  org.leo.traceroute.install.Env - OS:Linux / arch:amd64
Locale en_GB
Invalid MIT-MAGIC-COOKIE-1 key14:55:43.875 [main] ERROR org.leo.traceroute.Main - Uncaught error
java.lang.NoClassDefFoundError: Could not initialize class sun.awt.X11.XToolkit
        at java.lang.Class.forName0(Native Method) ~[na:1.8.0_91]
        at java.lang.Class.forName(Class.java:264) ~[na:1.8.0_91]
        at java.awt.Toolkit$2.run(Toolkit.java:860) ~[na:1.8.0_91]
        at java.awt.Toolkit$2.run(Toolkit.java:855) ~[na:1.8.0_91]
        at java.security.AccessController.doPrivileged(Native Method) ~[na:1.8.0_91]
        at java.awt.Toolkit.getDefaultToolkit(Toolkit.java:854) ~[na:1.8.0_91]
        at java.awt.KeyboardFocusManager.initPeer(KeyboardFocusManager.java:446) ~[na:1.8.0_91]
        at java.awt.KeyboardFocusManager.<init>(KeyboardFocusManager.java:442) ~[na:1.8.0_91]
        at java.awt.DefaultKeyboardFocusManager.<init>(DefaultKeyboardFocusManager.java:65) ~[na:1.8.0_91]
        at java.awt.KeyboardFocusManager.getCurrentKeyboardFocusManager(KeyboardFocusManager.java:225) ~[na:1.8.0_91]
        at java.awt.KeyboardFocusManager.getCurrentKeyboardFocusManager(KeyboardFocusManager.java:216) ~[na:1.8.0_91]
        at javax.swing.plaf.synth.SynthLookAndFeel.initialize(SynthLookAndFeel.java:616) ~[na:1.8.0_91]
        at javax.swing.plaf.nimbus.NimbusLookAndFeel.initialize(NimbusLookAndFeel.java:105) ~[na:1.8.0_91]
        at javax.swing.UIManager.setLookAndFeel(UIManager.java:538) ~[na:1.8.0_91]
        at javax.swing.UIManager.setLookAndFeel(UIManager.java:583) ~[na:1.8.0_91]
        at org.leo.traceroute.Main.main(Main.java:75) ~[org.leo.traceroute.jar:na]
me@mysystem:/opt/ovt> 

 
What the hack!? However, this problem is simple one. We started Java from a subshell as root. But why should root get access to our X11 display from such an environment? Actually, even root cannot do this without special precautions!

In the case of starting a KDE root terminal as in “solution 1” KDE and pam take care of the X11 access. Also, in case of a ”
su -” command at the prompt this is handled by pam. See the “/etc/pam.d/su” file and look for a line

session optional pam_xauth.so

Let us quickly test our theory about a missing X11 access right by using the “xhost”-command in addition:

me@mysystem:/opt/ovt> xhost +SI:localuser:root
localuser:root being added to access control list
me@mysystem:/opt/ovt> ./ovtr.sh
root's password:
15:40:20.920 [main] INFO  org.leo.traceroute.Main - Open Visual Traceroute 1.6.3 
15:40:20.928 [main] INFO  org.leo.traceroute.install.Env - Java run-time version: 1.8.0_91
15:40:20.929 [main] INFO  org.leo.traceroute.install.Env - NASA World Wind Java 2.0 2.0.0
15:40:20.929 [main] INFO  org.leo.traceroute.install.Env - /usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
15:40:20.929 [main] INFO  org.leo.traceroute.install.Env - OS:Linux / arch:amd64
Locale en_GB
15:40:23.313 [SwingWorker-pool-1-thread-1] INFO  o.leo.traceroute.core.geo.GeoService - Use geoip db /root/ovtr/GeoLiteCity.dat which is 0 day(s) old
15:40:24.913 [pool-2-thread-1] INFO  o.leo.traceroute.core.ServiceFactory - Try using device eth0 null
15:40:25.090 [pool-2-thread-2] INFO  o.leo.traceroute.core.ServiceFactory - Try using device br0 null
15:40:25.279 [pool-2-thread-3] INFO  o.leo.traceroute.core.ServiceFactory - Try using device virbr_vmw null
15:40:26.317 [pool-2-thread-8] INFO  o.leo.traceroute.core.ServiceFactory - Try using device vmnet1 null
15:40:27.339 [pool-2-thread-9] INFO  o.leo.traceroute.core.ServiceFactory - Try using device virbr1 null
15:40:28.394 [pool-2-thread-10] INFO  o.leo.traceroute.core.ServiceFactory - Try using device virbr2 null
15:40:29.417 [pool-2-thread-11] INFO  o.leo.traceroute.core.ServiceFactory - Try using device vmnet3 null
15:40:30.445 [pool-2-thread-12] INFO  o.leo.traceroute.core.ServiceFactory - Try using device virbr3 null
15:40:31.469 [pool-2-thread-13] INFO  o.leo.traceroute.core.ServiceFactory - Try using device virbr4 null
15:40:32.492 [pool-2-thread-14] INFO  o.leo.traceroute.core.ServiceFactory - Try using device virbr5 null
15:40:33.512 [pool-2-thread-15] INFO  o.leo.traceroute.core.ServiceFactory - Try using device virbr6 null
15:40:34.534 [pool-2-thread-17] INFO  o.leo.traceroute.core.ServiceFactory - Try using device lo null
15:40:36.711 [AWT-EventQueue-0] INFO  org.leo.traceroute.Main - Startup completed in 15796ms
...
15:40:47.831 [Shutdown] INFO  org.leo.traceroute.install.Env - Preferences saved.
15:40:47.833 [Shutdown] INFO  o.leo.traceroute.ui.TraceRouteFrame - Application exited.
me@mysystem:/opt/ovt> xhost -SI:localuser:root
localuser:root being removed from access control list
me@mysystem:/opt/ovt>

 
Success! But, do not forget to retrieve the access right after having used OVT.

Solution 3: Run OVT with sudo and preserved XAUTHORITY variable

How can we automatize the X11 access a bit? A look at the settings in the simple standard “/etc/sudoers”-file of Opensuse reveals that it should be possible to run the “sudo”-command in our “ovtr.sh” also with the option “-E” (= –preserve-env):

#!/bin/bash
export PATH="$PATH:/usr/sbin/"
env | grep XAUTHO
sudo -E /bin/bash -c 'export DISPLAY=:0; env | grep XAUTHO;  java -Djava.awt.headless=false  -Xmx512m -jar org.leo.traceroute.jar'

 
And really:

 
me@mysystem:/opt/ovt> ./ovtr.sh 
XAUTHORITY=/tmp/xauth-1011-_0
root's password:
SUDO_COMMAND=/bin/bash -c export DISPLAY=:0; env | 
grep XAUTHO;  java -Djava.awt.headless=false  -Xmx512m -jar org.leo.traceroute.jar
XAUTHORITY=/tmp/xauth-1011-_0
19:31:41.610 [main] INFO  org.leo.traceroute.Main - Open Visual Traceroute 1.6.3 
...
....
19:31:45.617 [pool-2-thread-1] INFO  o.leo.traceroute.core.ServiceFactory - Try using device eth0 null
...

 
It works ! I do not recommended to invoke the environment of a standard user this way, but this test just gave us the right idea. The following has the same effect – and is safer as we only use the contents of one variable (XAUTHORITY) of the unprivileged environment:

#!/bin/bash
sudo XAUTHORITY=$XAUTHORITY /bin/bash -c 'export DISPLAY=:0; java -Djava.awt.headless=false  -Xmx512m -jar org.leo.traceroute.jar'

 

Summary

My objective in this post was to present some elementary steps to get OVT running on an Opensuse Leap 42.1 system. We have seen that we need to make the right “libpcap.so” library available and that the “sudo” command in the start script has to be adapted to guarantee both the recognition of the DISPLAY variable and the access to the X11 display. In a first test we have futhermore seen that OVT’s internal traceroute is a bit better than the standard Linux traceroute.

On a multi-user system, however, we need to restrict the access to OVT to a group of trustworthy users. This will be the topic of the next article.

Have some fun with testing out OVT in the meantime!

Nützliche Webseiten zur Analyse von DNS-Problemen mit gehosteten Web-Domainen

Gestern rief meine Frau an, die sich z.Z. bei Bekannten in Norwegen aufhält; Firefox würde eine von ihr betreute norwegische Homepage eines Kunden nicht mehr anzeigen – weder auf dem Windows-Desktop noch auf ihrem Mobil-Telefon. Bei einem Kollegen ginge es aber anstandslos. Andere Webseiten konnte sie problemlos aufrufen; nur eben nicht die Seiten der von ihr betreuten norwegischen Web-Domaine.

Das sind so Themen, die einen durchaus eine Weile beschäftigen können, da in einer solchen Situation potentiell mehrere Provider ins Spiel kommen. Da ist einerseits mal der Internet-Provider der Verwandtschaft in Norwegen; über den erhält der dortige Router in der Standardkonfiguration automatisch DNS-Server-Adressen zugewiesen. Der Kunde hingegen hatte seinen Web-Space bei einem sog. “norwegischen Web-Hotel” – also bei einem kleineren norwegischen Web-Server-Provider – gehostet. (Der Vertrag ist außerhalb von unserer Verantwortung und Beratung geschlossen worden).

Natürlich war hinter der ganzen Angelegenheit ein DNS-Problem zu vermuten. Allerdings war auch klar, dass das ein etwas ungewöhnliches Problem sein musste, da es nur domain-spezifisch auftrat. Ich beschreibe nachfolgend kurz das Vorgehen zur Analyse mit Hilfe von im Internet verfügbaren Diensten und einiger nützlicher Webseiten. Das Ergebnis war für mich zudem etwas überraschend; man lernt ja nie aus.

Zunächst ließ ich checken, welche DNS-Server dem Router in Norwegen zugeordnet waren; dann, ob diese Server überhaupt ihren Dienst taten. Letzteren Schritt konnte ich nicht von Deutschland aus mit einem der üblichen Linux-Kommandos “dig”, “host” oder dem alten “nslookup” erledigen. Grund: Der Provider verweigert den Zugriff auf seinen DNS-Server aus dem Ausland.
Also musste meine Frau die Windows-Variante von “nslookup” in der MS Windows Eingabe-Aufforderung benutzen. (Die Syntax – s. “nslookup /?” – ist sehr linux-ähnlich). Ergebnis: Die DNS-Server des Providers funktionierten zwar, konnten den Namen der Problem-Domaine aber tatsächlich nicht in eine IP-Adresse auflösen – andere Domainnamen hingegen schon.

Ein Gegentest mit verschiedenen anderen, öffentlich zugänglich DNS-Servern in Norwegen (http://public-dns.info/nameserver/no.html) ergab dann, dass einige dieser DNS-Server die Namensauflösung vornahmen, einige wenige aber nicht.

Für andere Länder findet man öffentlich zugängliche DNS-Server übrigens mit

http://public-dns.info/nameserver/LANDESKUERZEL.html

Ein ähnliches Ergebnis lieferte dann eine Stichprobe für deutsche DNS-Server: die allermeisten DNS-Server führten die Namensauflösung für die betroffene norwegische Web-Domaine durch, einige aber auch hierzulande nicht. Dadurch misstrauisch geworden, überprüfte ich als nächstes, was denn die Datenkrake Google zu der ganzen Sache meinte.

So kann man beispielsweise mal

host xyz.no 8.8.8.8 oder host xyz.no 8.8.4.4

ausführen (xyz ist natürlich durch den korrekten Domainnamen zu ersetzen). die IP-Adressen entsprechen öffentlichen DNS-Servern von Google.

Und siehe da – auch Google verweigerte die Namensauflösung mit der Meldung “SERVFAIL”; das Ergebnis erhielt ich natürlich auch über https://dns.google.com.

Interessant – aber ein Seitenaspekt – ist in einer solchen Situation auch, wie eigentlich eine Domaine nach außen im Internet erscheint, wer darauf verlinkt und ob die zugeordnete IP von mehreren anderen Web-Domainen geteilt wird. Hierzu kann man mal einen Blick auf den Web-Dienst

http://domainstats.io/

werfen und dort seinen Domainnamen eingeben (oder gleich http://domainstats.io/domainname). Man erhält dann in der Mitte der Seite mit vielen Analyse-Ergebnissen auch eine Info zur IP – und wie oft die geteilt wird.
Ein Klick auf die Zahl oder aber die Eingabe von

http://domainstats.io/IP-ADRESSE

in der HTTP-Adresszeile des Browsers liefert dann mehr und übersichtliche Informationen über die Web-Domainen zur gleichen IP-Adresse.

Für uns interessant war das Ergebnis trotz keiner direkten DNS-bezogenen Auskunft trotzdem. Denn auf diesem Wege erfuhren wir, dass die betreute Domaine (inzwischen?) auf einem US-amerikanischen Server gehostet und dass die Web-Server-IP mit 48 anderen Domainen (meist norwegische Domainen) geteilt wird. Davon wusste weder unser Kunde etwas, noch bislang wir.

Im Klartext: Der Web-Hoster in Norwegen kooperiert offenbar mit einem amerikanischen Provider – und nutzt dessen Hosting-Dienste – wohl um selbst Kosten zu sparen. Inkl. der an die Domaine angeschlossene Mail-Dienste. Ohne allerdings den Kunden über dieses Faktum zu informieren …

Off Topic: Dass in den USA ein anderer Datenschutz gehandhabt wird als in der EU ist wohl auch Norwegern inzwischen bekannt … Aber, was solls, Norwegen ist ja selbst auch nicht in der EU und sein Geheimdienst betreibt angeblich auch Supercomputeranlagen zur Dechiffrierung kryptierter Information
http://www.golem.de/news/spionage-supercomputer-soll-norwegen-beim-entschluesseln-helfen-1404-106115.html
http://www.spiegel.de/netzwelt/web/steelwinter-supercomputer-norwegens-geheimdienst-kooperiert-mit-nsa-a-966541.html
https://netzpolitik.org/2014/steelwinter-nsa-verkauft-supercomputer-an-norwegischen-geheimdienst/
Unabhängig davon gilt wohl: Augen auf bei der Provider-Wahl für Web-Hosting in Norwegen …. Man sollte sich als Betroffener vorab informieren, wo die eigenen Daten letztlich wirklich gehostet werden – und dann entscheiden, ob man das für gut hält …

Nun war es endgültig an der Zeit, sich darüber zu informieren, aus welchen Gründen es z.B. bei Google Probleme mit der Namensauflösung geben kann. Weiter half dabei die Seite
https://developers.google.com/speed/public-dns/docs/troubleshooting
Sie liefert einige nützliche Informationen und verweist auf weitere Seiten, die eine übersichtliche Analyse der DNS-Situation für eine Web-Domaine liefern können; für eine solche Analyse müsste man auch als Linuxer einigen Aufwand betreiben und sich viele Optionen der Kommandos nslookup, dig, host zu eigen machen :

http://intodns.com/

Das dortige Toolset analysiert zwar nur Haupt- und keine Sub-Domainen; das reicht ja aber in der Regel. Ich kann jedem nur raten, sich das ausführliche Ergebnis mal für die eigene Domainen anzusehen und über evtl. monierte Punkte nachzudenken und diesbzgl. auch ggf. seinen Provider zu kontaktieren.

Interessant war auch im Fall des norwegischen Hosters wieder eine Abweichung von deutschen Gepflogenheiten festzustellen – hierzulande werden zumindest bei den großen Providern die autoritativen DNS-Nameserver zu einer .de-Domaine in getrennten Netz-Segmenten und unabhängig von den Web-Servern betrieben. Eine Zusammenstellung der Anforderungen (im Jahr 2012) findet man z.B. hier
http://www.inmotionhosting.com/support/community-support/dns-nameserver-changes/nameserver-requirements-to-de-domain-name,
http://manage.resellerclub.com/kb/
answer/1132
,
https://de.godaddy.com/help/about-de-domains-5825.
Der TÜV stellt im Rahmen von Firmenzertifizierungen noch weitergehende Anforderungen wie z.B. echte unabhängige Internet-Uplinks etc.. Im Falle des norwegischen (besser amerikanischen Hosters war ein Nameserver mit dem Webserver identisch. Ein zweiter lag im selben C-Segment.

In Norwegen ist übrigens die Organisation NORID für die übergeordneten Domain-Services zuständig. Allerdings erfährt man aus den “whois”-Einträgen anders als bei der DENIC nicht direkt die IP-Adressen der autoritativen Name-Server für eine Domaine. Hier helfen auf die Schnell die Informationen von intodns.com. Oder:

host -C domain-name

Es lohnt sich generell, mal die man-Seiten zu nslookup, host und dig bzgl. der möglichen Optionen zu scannen.

Im Falle unserer norwegischen Problem-Domaine spuckte intodns.com zwar einige kleinere Warnhinweise aus – nichts davon erschien mir aber die fehlende Namensauflösung erklären zu können. Aber Google weist ja freundlicherweise auch auf

http://dnsviz.net/

hin. Die dortigen DNS-Tools untersuchen die Einhaltung von DNSSEC-Standards. Es geht dabei um die Signierung von DNS-Informationen mit Hilfe kryptografischer Schlüssel und Zertifikate. Siehe für eine Kurzdarstellung:
https://de.wikipedia.org/wiki/Domain_Name_System_Security_Extensions

Eine wesentlich ausführlichere und gute Einführung liefert folgender Artikel von U. Wisse, der unter den Webseiten von Heise publiziert wurde :
http://www.heise.de/netze/artikel/Domain-Name-System-absichern-mit-DNSSEC-903318.html

Nachvollziehbare Kritik zum DNSSEC-Verfahren findet man z.B. hier:
http://www.golem.de/news/imho-dnssec-ist-gescheitert-1506-114940.html

Interessant finde ich, dass das ganze DNSSEC-System allein von US-amerikanischen Root-Zonen-Servern und der dortigen DNSSEC-Schlüssel-, genauer Zertifikats-Verwaltung abhängig ist. Als neutrale Verfikationsinstanz für die Zertifikatsechtheit fungiert wiederum ein amerikanisches Unternehmen. Das aber nur nebenbei …

Der Einführung von Hrn. Wisser entnimmt man, dass schon kleine Fehler beim Aufsetzen der DNSSEC-Informationen auf DNS-Servern, die DNSSEC unterstützen, zur Nicht-Erreichbarkeit einer Web-Domaine führen können. Das Gleiche gilt, wenn Umzüge von Domainen zu Providern stattfinden, die z.B. DNSSEC nicht unterstützen – der originale Provider aber auf seinen Servern noch DNSSEC-Einträge vorhält. Darauf weist auch die oben genannte Google-Seite hin.

Tja, was soll ich noch mehr sagen: “http://dnsviz.net/” lieferte gestern substanzielle Fehler bzgl. der verfügbaren DNSSEC Information zu unserer Problem-Domaine. Kein Wunder, dass Google und andere DNSSEC-fähige DNS-Server die Namensauflösung verweigerten. Viele andere DNS-Server prüfen DNSSEC-Information übrigens nicht – was einen Teil des obigen Befunds erklärt.

Der norwegische Hosting-Provider unseres Kunden hat inzwischen auf seinen Webseiten zugegeben, dass für einige “Konten” Fehler beim Update von DNSSEC-Informationen aufgetreten seien. Die würden behoben. Tatsächlich liefert dnsviz heute keine Fehler mehr. Der irritierte Kunde ist jetzt auch wieder glücklich – ich habe nebenbei etwas über DNSSEC gelernt – und auch darüber, wie sehr der Betrieb von DNSSEC von Amerika abhängig ist. Gelernt habe ich ferner, dass DNS-Probleme durch DNSSEC-Fehlern von Hosting-Providern verursacht sein können.

Dass Provider wiederum Provider nutzen, ist dagegen keine neue Erkenntnis. Dass Hosting-
Provider in Nicht-EU-Ländern gehostete Websites aber auf Server in ein anderes Land – hier: die USA – verschieben, ohne dass der Kunde etwas davon erfährt, war ein anderes interessantes Lehrstück. Ich hoffe, derlei ist in Deutschland unmöglich.

Ansonsten: Viel Spaß beim Anwenden der oben angegebenen Analyseseiten auf die von euch betreuten Web-Domainen.

P.S.: DNS-Analysen im Rahmen von Penetrationstests
Wer sich mehr für DNS-Analysen z.B. im Rahmen von Penetrationstests interessiert, sollte auch mal einen Blick auf folgende Seite werfen: http://resources.infosecinstitute.com/dns-hacking/
Auch “dnsrecon” und “dnsenum” sind interessante Tools, die in Penetrationstests aber mit Bedacht eingesetzt werden muss (s. https://w3dt.net/tools/dnsrecon). Brute Force-Einsätze sind zu unterlassen, wenn keine entsprechenden Einwilligungen des Netzbetreibers vorliegen.

nPA, eID und Open eCard unter Linux/Opensuse

Vor kurzem musste ich mich mit der Frage auseinandersetzen, wie ich die eID des neuen Personalausweises [nPA] unter Linux nutzen kann. Da ich in Bayern wohne, war ich u.a. daran interessiert, Zugang zur sog. BayernID und einem damit verbundenen “Bürgerkonto” zu bekommen, das von der Landesregierung über ein Infrastruktur der AKDB zentral bereitgestellt wird. Dieses Konto kann in allen sog. “Bürgerservice”-Portalen der in Bayern an die AKDB angeschlossenen Kommunen verwendet werden kann. Der im Alltag spürbare Nutzen ist aufgrund des noch sehr begrenzten Angebots an transaktionalen Online-Diensten, in denen der eID-Einsatz die Schriftformerfordernis abdeckt, allerdings noch relativ bescheiden. Aber das ist eine andere Diskussion …

Welche Erfahrung macht man nun, wenn man sich als Linux-Nutzer registrieren will? Leider wird man umgehend frustriert und enttäuscht:

Linux-User werden von Hauptseiten der Portal- und Dienstebetreiber schlichtweg ignoriert; sie tauchen in den Anleitungen zum Einsatz der eID flächendeckend nicht auf. Grundsätzlich wird die AusweisApp2 als Voraussetzung der eID-Nutzung genannt. Diese Anwendung steht jedoch nur für MS Windows und Apple OS X zur Verfügung. Der übliche Verweis auf die Website “https://www.ausweisapp.bund.de/startseite/” für weitere Informationen lässt den Linux-User dann jedoch im Regen stehen. Nach mühsamer Suche erfährt man unter FAQs bzw. in einem Forum lapidar, dass Governikus angeblich auf die am häufigsten eingesetzten Betriebssysteme gezielt habe.

Aufregen nutzt hier nichts – die eigentlich relevante Frage, wie hoch der Prozentsatz der E-Government-Willigen pro Betriebssystem ist und was das dann in absoluten Zahlen bedeutet, wurde wohl nicht als relevant angesehen. Im Ergebnis ist festzuhalten, dass die Möglichkeit zur Plattformneutralität trotz Opensource-Politik von Governikus nicht genutzt hat. Zudem wurde leider die Chance vertan, gerade bei denjenigen Staatsbürgern Pluspunkte und Vertrauen zu gewinnen, die E-Government befürworten und dabei den deutschen Datenschutz womöglich ernster nehmen als ein bestimmter Betriebssystemhersteller, der für seine Nutzungsbedingungen und den umfassenden Zugriff auf personenbezogene Daten im Rahmen von Standardinstallation kürzlich von einer deutschen Verbraucherzentrale heftig kritisiert wurde.
http://www.sueddeutsche.de/digital/klage-windows-verbraucherzentrale-geht-gegen-microsoft-vor-1.2886619

Open eCard

Welche Alternative hat man nun als Linux-User, der E-Government-Anwendungen in Kombination mit der eID nutzen will? Governikus verweist auf das “persoapp”-Projekt. Das ist jedoch nicht fertig – unter Opensuse Leap mit Java OpenJDK 1.8 und KDE 5 lief die Test-Anwendung jedenfalls (noch) nicht. Auch ein Java-Webstart von des Testseite führte nicht zum Erfolg.

Nach ein wenig Recherche wird man aber dank anderer engagierter Zeitgenossen fündig: Es gibt auch das Open eCard-Projekt – siehe:
https://www.openecard.org/startseite/
Dort kann man sich eine Java Web Start Applikation und bei Interesse den zugehörigen Code herunterladen. Angemerkt sei, dass die Open eCard-Anwendung Anfang 2016 vom BSI in puncto Sicherheit zertifiziert wurde. Siehe hierzu:
http://www.pro-linux.de/news/1/23138/bsi-zertifiziert-offenen-eid-client.html

Voraussetzung der Anwendung ist eine JAVA Run Time Umgebung JRE >= Version 1.7. Hat man ferner einen NFC-fähigen Kartenleser, für den der Hersteller Linux-Treiber bereitstellt (etwa von ReinerSCT), so nimmt die Open eCard-Anwendung den Kartenleser anstandslos wahr und zeigt ggf. an, dass (k)eine RFID-Karte oder eben der
neue Personalausweis eingelegt ist.

eID_opeecard_0
eID_opeecard_01

Unter KDE platziert sich die Anwendung in der Systemkontrollleiste – und wartet im Hintergrund. Ein Klick öffnet unter KDE 4 ein Anwendungsfenster. Das funktioniert unter KDE5 (noch) nicht – das tut aber der späteren Funktionalität in Kombination mit E-Government Web-Anwendungen im Browser keinen Abbruch.

Die Anwendung kommt extrem schlicht daher; es gibt kaum Infos und Einstellmöglichkeiten; das Layout ist maximal schmucklos.

eID_opeecard_02

Wirklich zu werkeln beginnt die Anwendung dann, wenn eine E-Government-Web-Anwendung im Browser – z.B. das AKDB-Konto beim Login – die eID auslesen will. Man wird dann vom Kartenleser wie der Open eCard-Anwendung vorab über die Berechtigung der zugreifenden Instanz informiert und – soweit noch nicht getan – zum Ein-/Auflegen des nPA in das Lesegerät aufgefordert.

eID_opeecard_1

Zudem wird rudimentär und für den Unkundigen etwas kryptisch der Typus der Daten angezeigt, die ausgelesen werden.

eID_opeecard_2

Unter “pseudonym” kann sich nicht jeder was vorstellen. Weiter helfen dem Interessierten Bürger hier Informationen dieser Links:
http://www.die-pseudonym-funktion.de/?navigation=login-per-pseudonym-funktion-des-personalausweises
http://www.personalausweisportal.de/DE/Wirtschaft/Diensteanbieter-werden/Einsatzmoeglichkeiten/Pseudonymer-Zugang/pseudonym_node.html
http://www.die-eid-funktion.de/

Im Falle komplexerer Transaktionen als einem Login werden hier deutlich mehr personenbezogene Daten angezeigt. Z.B. bei der Abfrage der gespeicherten nPA-Daten über eine Website des BMI https://www.buergerserviceportal.de/bund/ausweisapp/bspx_selbstauskunft/index.jsp

eID_opeecard_4

Interessanterweise findet Firefox die genannte Seite des BMI nicht vollständig sicher; das letztlich referenzierte Zertifikat der AKDB) ist aber OK.

eID_opeecard_5

eID_opeecard_6

Ja, ja, … Querverweis zur Anwendung nicht ganz glücklich implementiert. Unter dem Bayernportal läuft die gleiche Auskunftsanwendung dagegen ohne Sicherheitswarnung. Man versuche es selbst unter https://www.buergerserviceportal.de/bayern/freistaat/bspx_selbstauskunft

Nach PIN-Eingabe und dem Auslesevorgang wird die Kontrolle dann wieder an die Web-Anwendung abgegeben. Dankenswerterweise fordert einen “Open eCard” dann auf, den Personalausweis wieder aus dem Kartenleser zu entfernen.

eID_opeecard_3

Ich habe inzwischen mehrere kommunale Verwaltungsportale besucht und immer dann, wenn die Bedienungsanleitungen die AusweisApp2 verlangten, unter Linux auf die Open eCard zurückgegriffen. Konnte bislang kein Problem erkennen.

Fazit

Also – wenn auch nicht mit der AusweisApp2 und ohne Unterstützung von Governikus:

Dank der Leute, die zu Open eCard beigetragen haben, kann auch der Linuxer E-Government Dienste in Deutschland nutzen, die die eID erfordern. Mit BSI Sicherheitszertifizierung. Ich jedenfalls danke dem Open eCard Team für seine Anstrengungen und Verdienste um die Zertifizierung recht herzlich.

Linux bridges – can iptables be used against MiM attacks based on ARP spoofing ? – III

This small series of blog contributions was written to understand a little better how to use iptables in the context of Linux bridges as a countermeasure against some of the effects of a man-in-the-middle [MiM] attack based on ARP spoofing. The attacking system as well as the attacked systems are in our scenarios attached to Linux bridge ports. My objective was to block redirected TCP/IP packets from and to the attacking system.

In the first post
Linux bridges – can iptables be used against MiM attacks based on ARP spoofing ? – I
we had discussed how we have to set up iptables rules for ports of a single Linux bridge and their associated IP-addresses to get the desired blocking. We found that a certain order of DENY and ACCEPT rules is required.

In the second post
Linux bridges – can iptables be used against MiM attacks based on ARP spoofing ? – II
we investigated how iptables reacts to the existence of multiple and linked Linux bridges on one and the same host.

We defined “border ports” as ports that connect a Linux bridge to other bridges, to external network segments or to the virtualization host itself – but not to guests directly attached to the bridge via tap or veth-devices. “Border ports” may be passed by packets traveling to their destination across multiple bridges. We then extended our previous considerations on iptables rules to such “border ports” and found a general recipe for the order of the required DENY and ACCEPT rules for the ports of the multiple bridges.

In the present post we shall test the required rules for the bridge setup presented in the 2nd post. We consider some examples of attack variants with respect to the 2 bridges and ICMP packets. However, the tests would also work for any TCP based service. The reason is that the central DENY rules are very general and compiled without reference to any specific service type.

I assume that you have had a look at the screenshots of the logical rules displayed in a FWbuilder interface in the 2nd article (II).

Setup and iptables rules created by FWbuilder

See the following drawing for the setup of our test scenario:

bridge3

The general DENY rules and the ICMP-related ACCEPT rules displayed in the last article are compiled by FWbuilder to create the following script commands:

    # Rule 2 (vk63)
    # 
    echo "Rule 2 (vk63)"
    # 
    # virbr6 guest port
    $IPTABLES -N Out_RULE_2
    $IPTABLES -A FORWARD -m physdev --physdev-is-bridged --physdev-out vk63 !  -d 192.168.50.13   -j Out_RULE_2  
    $IPTABLES -A Out_RULE_2  -j LOG  --log-level info --log-prefix "RULE 2 -- DENY "
    $IPTABLES -A Out_RULE_2  -j DROP
    # 
    # Rule 3 (vk64)
    # 
    echo "Rule 3 (vk64)"
    # 
    # virbr6 guest port
    $IPTABLES -N Out_RULE_3
    $IPTABLES -A FORWARD -m physdev --physdev-is-bridged --physdev-out vk64 !  -d 192.168.50.14   -j Out_RULE_3 
    $IPTABLES -A Out_RULE_3  -j LOG  --log-level info --log-prefix "RULE 3 -- DENY "  
    $IPTABLES -A Out_RULE_3  -j DROP
    # 
    # Rule 4 (vk65)
    # 
    echo "Rule 4 (vk65)"
    # 
    # virbr6 guest port
    $IPTABLES -N Out_RULE_4
    $IPTABLES -A FORWARD -m physdev --physdev-is-bridged --physdev-out vk65 !  -d 192.168.50.15   -j Out_RULE_4  
    $IPTABLES -A Out_RULE_4  -j LOG  --log-level info --log-prefix "RULE 4 -- DENY "    
    $IPTABLES -A Out_RULE_4  -j DROP
    # 
    # Rule 5 (vk42)
    # 
    echo "Rule 5 (vk42)"
    # 
    # virbr4 guest port
    $IPTABLES -N Out_RULE_5
    $IPTABLES -A FORWARD -m physdev --physdev-is-bridged --physdev-out vk42 !  -d 192.168.50.12   -j Out_RULE_5  
    $IPTABLES -A Out_RULE_5  -j LOG  --log-level info --log-prefix "RULE 5 -- DENY "
    $IPTABLES -A Out_RULE_5  -j DROP
    # 
    # Rule 6 (vk63)
    # 
    echo "Rule 6 (vk63)"
    # 
    # virbr6 guest port
    $IPTABLES -N Out_RULE_6
    $IPTABLES -A FORWARD -m physdev --physdev-is-bridged --physdev-out vk63  -s 192.168.50.13   -j Out_RULE_6  
    $IPTABLES -A Out_RULE_6  -j LOG  --log-level info --log-prefix "RULE 6 -- DENY "
    $IPTABLES -A Out_RULE_6  -j DROP
    # 
    # Rule 7 (vk64)
    # 
    echo "Rule 7 (vk64)"
    # 
    # virbr6 guest port
    $IPTABLES -N Out_RULE_7
    $IPTABLES -A FORWARD -m physdev --physdev-is-bridged --physdev-out vk64  -s 192.168.50.14   -j Out_RULE_7  
    $IPTABLES -A Out_RULE_7  -j LOG  --log-level info --log-prefix "RULE 7 -- DENY "
    $IPTABLES -A Out_RULE_7  -j DROP
    # 
    # Rule 8 (vk65)
    # 
    echo "Rule 8 (vk65)"
    # 
    # virbr6 guest port
    $IPTABLES -N Out_RULE_8
    $IPTABLES -A FORWARD -m physdev --physdev-is-bridged --physdev-out vk65  -s 192.168.50.15   -j Out_RULE_8  
    $IPTABLES -A Out_RULE_8  -j LOG  --log-level info --log-prefix "RULE 8 -- DENY "
    $IPTABLES -A Out_RULE_8  -j DROP
    # 
    # Rule 9 (vk42)
    # 
    echo "Rule 9 (vk42)"
    # 
    # virbr4 guest port
    $IPTABLES -N Out_RULE_9
    $IPTABLES -A FORWARD -m physdev --physdev-is-bridged --physdev-out vk42  -s 192.168.50.12   -j Out_RULE_9  
    $IPTABLES -A Out_RULE_9  -j LOG  --log-level info --log-prefix "RULE 9 -- DENY "
    $IPTABLES -A Out_RULE_9  -j DROP
    # 
    # Rule 10 (vk63)
    # 
    echo "Rule 10 (vk63)"
    # 
    # virbr6 guest port
    $IPTABLES -N In_RULE_10
    $IPTABLES -A INPUT -m physdev --physdev-in vk63 !  -s 192.168.50.13   -j In_RULE_10
    $IPTABLES -A FORWARD -m physdev --physdev-in vk63 !  -s 192.168.50.13   -j In_RULE_10  
    $IPTABLES -A In_RULE_10  -j LOG  --log-level info --log-prefix "RULE 10 -- DENY "
    $IPTABLES -A In_RULE_10  -j DROP
    # 
    # Rule 11 (vk64)
    # 
    echo "Rule 11 (vk64)"
    # 
    # virbr6 guest port
    $IPTABLES -N In_RULE_11
    $IPTABLES -A INPUT -m physdev --physdev-in vk64 !  -s 192.168.50.14   -j In_RULE_11
    $IPTABLES -A FORWARD -m physdev --physdev-in vk64 !  -s 192.168.50.14   -j In_RULE_11  
    $IPTABLES -A In_RULE_11  -j LOG  --log-level info --log-prefix "RULE 11 -- DENY "
    $IPTABLES -A In_RULE_11  -j DROP
    # 
    # Rule 12 (vk65)
    # 
    echo "Rule 12 (vk65)"
    # 
    # virbr6 guest port
    $IPTABLES -N In_RULE_12
    $IPTABLES -A INPUT -m physdev --physdev-in vk65 !  -s 192.168.50.15   -j In_RULE_12
    $IPTABLES -A FORWARD -m physdev --physdev-in vk65 !  -s 192.168.50.15   -j In_RULE_12  
    $IPTABLES -A In_RULE_12  -j LOG  --log-level info --log-prefix "RULE 12 -- DENY "
    $IPTABLES -A In_RULE_12  -j DROP
    # 
    # Rule 13 (vk42)
    # 
    echo "Rule 13 (vk42)"
    # 
    # virbr4 guest port
    $IPTABLES -N In_RULE_13
    $IPTABLES -A INPUT -m physdev --physdev-in vk42 !  -s 192.168.50.12   -j In_RULE_13
    $IPTABLES -A FORWARD -m physdev --physdev-in vk42 !  -s 192.168.50.12   -j In_RULE_13   
    $IPTABLES -A In_RULE_13  -j LOG  --log-level info --log-prefix "RULE 13 -- DENY "
    $IPTABLES -A In_RULE_13  -j DROP
    # 
    # Rule 15 (vethb2)
    # 
    echo "Rule 15 (vethb2)"
    # 
    # br6 border out
    $IPTABLES -N Cid7404X2034.0
    $IPTABLES -A FORWARD -m physdev --physdev-is-bridged --physdev-out vethb2  -j Cid7404X2034.0
    $IPTABLES -A Cid7404X2034.0  -s 192.168.50.13   -j RETURN
    $IPTABLES -A Cid7404X2034.0  -s 192.168.50.14   -j RETURN
    $IPTABLES -A Cid7404X2034.0  -s 192.168.50.15   -j RETURN
    $IPTABLES -N Out_RULE_15_3
    $IPTABLES -A Cid7404X2034.0  -j Out_RULE_15_3
    $IPTABLES -A Out_RULE_15_3  -j LOG  --log-level info --log-prefix "RULE 15 -- DENY "  
    $IPTABLES -A Out_RULE_15_3  -j DROP
    # 
    # Rule 16 (vethb2)
    # 
    echo "Rule 16 (vethb2)"
    # 
    # br6 border out
    $IPTABLES -N Cid7478X2034.0
    $IPTABLES -A FORWARD -m physdev --physdev-is-bridged --physdev-out vethb2  -j Cid7478X2034.0  
    $IPTABLES -A Cid7478X2034.0  -d 192.168.50.1   -j RETURN
    $IPTABLES -A Cid7478X2034.0  -d 192.168.0.37   -j RETURN
    $IPTABLES -A Cid7478X2034.0  -d 192.168.50.12   -j RETURN
    $IPTABLES -N Out_RULE_16_3
    $IPTABLES -A Cid7478X2034.0  -j Out_RULE_16_3
    $IPTABLES -A Out_RULE_16_3  -j LOG  --log-level info --log-prefix "RULE 16 -- DENY "
    $IPTABLES -A Out_RULE_16_3  -j DROP
    # 
    # Rule 17 (vethb1)
    # 
    echo "Rule 17 (vethb1)"
    # 
    # br4 border out
    $IPTABLES -N Cid8637X2034.0
    $IPTABLES -A FORWARD -m physdev --physdev-is-bridged --physdev-out vethb1  -j Cid8637X2034.0  
    $IPTABLES -A Cid8637X2034.0  -s 192.168.50.1   -j RETURN
    $IPTABLES -A Cid8637X2034.0  -s 192.168.0.37   -j RETURN
    $IPTABLES -A Cid8637X2034.0  -s 192.168.50.12   -j RETURN
    $IPTABLES -N Out_RULE_17_3
    $IPTABLES -A Cid8637X2034.0  -j Out_RULE_17_3
    $IPTABLES -A Out_RULE_17_3  -j LOG  --log-level info --log-prefix "RULE 17 -- DENY "
    $IPTABLES -A Out_RULE_17_3  -j DROP
    # 
    # Rule 18 (vethb1)
    # 
    echo "Rule 18 (vethb1)"
    # 
    # br4 border out
    $IPTABLES -N Cid8753X2034.0
    $IPTABLES -A FORWARD -m physdev --physdev-is-bridged --physdev-out vethb1  -j Cid8753X2034.0  
    $IPTABLES -A Cid8753X2034.0  -d 192.168.50.13   -j RETURN
    $IPTABLES -A Cid8753X2034.0  -d 192.168.50.14   -j RETURN
    $IPTABLES -A Cid8753X2034.0  -d 192.168.50.15   -j RETURN
    $IPTABLES -N Out_RULE_18_3
    $IPTABLES -A Cid8753X2034.0  -j Out_RULE_18_3
    $IPTABLES -A Out_RULE_18_3  -j LOG  --log-level info --log-prefix "RULE 18 -- DENY "
    $IPTABLES -A Out_RULE_18_3  -j DROP
    # 
    # Rule 19 (vmh1)
    # 
    echo "Rule 19 (vmh1)"
    # 
    # br4 border out
    $IPTABLES -N Cid8374X2034.0
    $IPTABLES -A FORWARD -m physdev --physdev-is-bridged --physdev-out vmh1  -j Cid8374X2034.0  
    $IPTABLES -A Cid8374X2034.0  -s 192.168.50.12   -j RETURN
    $IPTABLES -A Cid8374X2034.0  -s 192.168.50.13   -j RETURN
    $IPTABLES -A Cid8374X2034.0  -s 192.168.50.14   -j RETURN
    $IPTABLES -A Cid8374X2034.0  -s 192.168.50.15   -j RETURN
    $IPTABLES -N Out_RULE_19_3
    $IPTABLES -A Cid8374X2034.0  -j Out_RULE_19_3
    $IPTABLES -A Out_RULE_19_3  -j LOG  --log-level info --log-prefix "RULE 19 -- DENY "
    $IPTABLES -A Out_RULE_19_3  -j DROP
    # 
    # Rule 20 (vmh1)
    # 
    echo "Rule 20 (vmh1)"
    # 
    # br4 border out
    $IPTABLES -N Cid8530X2034.0
    $IPTABLES -A FORWARD -m physdev --physdev-is-bridged --physdev-out vmh1  -j Cid8530X2034.0  
    $IPTABLES -A Cid8530X2034.0  -d 192.168.50.1   -j RETURN
    $IPTABLES -A Cid8530X2034.0  -d 192.168.0.37   -j RETURN
    $IPTABLES -N Out_RULE_20_3
    $IPTABLES -A Cid8530X2034.0  -j Out_RULE_20_3
    $IPTABLES -A Out_RULE_20_3  -j LOG  --log-level info --log-prefix "RULE 20 -- DENY "
    $IPTABLES -A Out_RULE_20_3  -j DROP
    # 
    # Rule 22 (vethb2)
    # 
    echo "Rule 22 (vethb2)"
    # 
    # br6 border IN
    $IPTABLES -N Cid7917X2034.0
    $IPTABLES -A INPUT -m physdev --physdev-in vethb2  -j Cid7917X2034.0
    $IPTABLES -A FORWARD -m physdev --physdev-in vethb2  -j Cid7917X2034.0
    $IPTABLES -A Cid7917X2034.0  -d 192.168.50.13   -j RETURN
    $IPTABLES -A Cid7917X2034.0  -d 192.168.50.14   -j RETURN
    $IPTABLES -A Cid7917X2034.0  -d 192.168.50.15   -j RETURN
    $IPTABLES -N In_RULE_22_3
    $IPTABLES -A Cid7917X2034.0  -j In_RULE_22_3
    $IPTABLES -A In_RULE_22_3  -j LOG  --log-level info --log-prefix "RULE 22 -- DENY "
    $IPTABLES -A In_RULE_22_3  -j DROP
    # 
    # Rule 23 (vethb2)
    # 
    echo "Rule 23 (vethb2)"
    # 
    # br6 border IN
    $IPTABLES -N Cid8013X2034.0
    $IPTABLES -A INPUT -m physdev --physdev-in vethb2  -j Cid8013X2034.0
    $IPTABLES -A FORWARD -m physdev --physdev-in vethb2  -j Cid8013X2034.0
    $IPTABLES -A Cid8013X2034.0  -s 192.168.50.1   -j RETURN
    $IPTABLES -A Cid8013X2034.0  -s 192.168.0.37   -j RETURN
    $IPTABLES -A Cid8013X2034.0  -s 192.168.50.12   -j RETURN
    $IPTABLES -N In_RULE_23_3
    $IPTABLES -A Cid8013X2034.0  -j In_RULE_23_3
    $IPTABLES -A In_RULE_23_3  -j LOG  --log-level info --log-prefix "RULE 23 -- DENY "
    $IPTABLES -A In_RULE_23_3  -j DROP
    # 
    # Rule 24 (vethb1)
    # 
    echo "Rule 24 (vethb1)"
    # 
    # br4 border IN
    $IPTABLES -N Cid7639X2034.0
    $IPTABLES -A INPUT -m physdev --physdev-in vethb1  -j Cid7639X2034.0
    $IPTABLES -A FORWARD -m physdev --physdev-in vethb1  -j Cid7639X2034.0
    $IPTABLES -A Cid7639X2034.0  -s 192.168.50.13   -j RETURN
    $IPTABLES -A Cid7639X2034.0  -s 192.168.50.14   -j RETURN
    $IPTABLES -A Cid7639X2034.0  -s 192.168.50.15   -j RETURN
    $IPTABLES -N In_RULE_24_3
    $IPTABLES -A Cid7639X2034.0  -j In_RULE_24_3
    $IPTABLES -A In_RULE_24_3  -j LOG  --log-level info --log-prefix "RULE 24 -- DENY "  
    $IPTABLES -A In_RULE_24_3  -j DROP
    # 
    # Rule 25 (vethb1)
    # 
    echo "Rule 25 (vethb1)"
    # 
    # br4 border IN
    $IPTABLES -N Cid7736X2034.0
    $IPTABLES -A INPUT -m physdev --physdev-in vethb1  -j Cid7736X2034.0
    $IPTABLES -A FORWARD -m physdev --physdev-in vethb1  -j Cid7736X2034.0
    $IPTABLES -A Cid7736X2034.0  -d 192.168.50.1   -j RETURN
    $IPTABLES -A Cid7736X2034.0  -d 192.168.0.37   -j RETURN
    $IPTABLES -A Cid7736X2034.0  -d 192.168.50.12   -j RETURN
    $IPTABLES -N In_RULE_25_3
    $IPTABLES -A Cid7736X2034.0  -j In_RULE_25_3
    $IPTABLES -A In_RULE_25_3  -j LOG  --log-level info --log-prefix "RULE 25 -- DENY "  
    $IPTABLES -A In_RULE_25_3  -j DROP
    # 
    # Rule 26 (vmh1)
    # 
    echo "Rule 26 (vmh1)"
    # 
    # br4 border IN
    $IPTABLES -N Cid8881X2034.0
    $IPTABLES -A INPUT -m physdev --physdev-in vmh1  -j Cid8881X2034.0
    $IPTABLES -A FORWARD -m physdev --physdev-in vmh1  -j Cid8881X2034.0
    $IPTABLES -A Cid8881X2034.0  -s 192.168.50.1   -j RETURN
    $IPTABLES -A Cid8881X2034.0  -s 192.168.0.37   -j RETURN
    $IPTABLES -N In_RULE_26_3
    $IPTABLES -A Cid8881X2034.0  -j In_RULE_26_3
    $IPTABLES -A In_RULE_26_3  -j LOG  --log-level info --log-prefix "RULE 26 -- DENY "  
    $IPTABLES -A In_RULE_26_3  -j DROP
    # 
    # Rule 27 (vmh1)
    # 
    echo "Rule 27 (vmh1)"
    # 
    # br4 border IN
    $IPTABLES -N Cid9010X2034.0
    $IPTABLES -A INPUT -m physdev --physdev-in vmh1  -j Cid9010X2034.0
    $IPTABLES -A FORWARD -m physdev --physdev-in vmh1  -j Cid9010X2034.0
    $IPTABLES -A Cid9010X2034.0  -d 192.168.50.12   -j RETURN
    $IPTABLES -A Cid9010X2034.0  -d 192.168.50.13   -j RETURN
    $IPTABLES -A Cid9010X2034.0  -d 192.168.50.14   -j RETURN
    $IPTABLES -A Cid9010X2034.0  -d 192.168.50.15   -j RETURN
    $IPTABLES -N In_RULE_27_3
    $IPTABLES -A Cid9010X2034.0  -j In_RULE_27_3
    $IPTABLES -A In_RULE_27_3  -j LOG  --log-level info --log-prefix "RULE 27 -- DENY "  
    $IPTABLES -A In_RULE_27_3  -j DROP
    # 
    # Rule 29 (vmh2)
    # 
    echo "Rule 29 (vmh2)"
    # 
    # host OUT
    $IPTABLES -N Cid10297X2034.0
    $IPTABLES -A OUTPUT -o vmh2   -s 192.168.0.19   -j Cid10297X2034.0
    $IPTABLES -A OUTPUT -o vmh2   -s 192.168.50.1   -j Cid10297X2034.0
    $IPTABLES -A Cid10297X2034.0  -d 192.168.50.12   -j RETURN
    $IPTABLES -A Cid10297X2034.0  -d 192.168.50.13   -j RETURN
    $IPTABLES -A Cid10297X2034.0  -d 192.168.50.14   -j RETURN
    $IPTABLES -A Cid10297X2034.0  -d 192.168.50.15   -j RETURN
    $IPTABLES -N Out_RULE_29_3
    $IPTABLES -A Cid10297X2034.0  -j Out_RULE_29_3
    $IPTABLES -A Out_RULE_29_3  -j LOG  --log-level info --log-prefix "RULE 29 -- DENY "  
    $IPTABLES -A Out_RULE_29_3  -j DROP
    # 
    # Rule 30 (vmh2)
    # 
    echo "Rule 30 (vmh2)"
    # 
    # host IN
    $IPTABLES -N Cid10437X2034.0
    $IPTABLES -A INPUT -i vmh2   -d 192.168.0.19   -j Cid10437X2034.0
    $IPTABLES -A INPUT -i vmh2   -d 192.168.50.1   -j Cid10437X2034.0
    $IPTABLES -A FORWARD -i vmh2   -d 192.168.0.37   -j Cid10437X2034.0
    $IPTABLES -A Cid10437X2034.0  -s 192.168.50.12   -j RETURN
    $IPTABLES -A Cid10437X2034.0  -s 192.168.50.13   -j RETURN
    $IPTABLES -A Cid10437X2034.0  -s 192.168.50.14   -j RETURN
    $IPTABLES -A Cid10437X2034.0  -s 192.168.50.15   -j RETURN
    $IPTABLES -N In_RULE_30_3
    $IPTABLES -A Cid10437X2034.0  -j In_RULE_30_3
    $IPTABLES -A In_RULE_30_3  -j LOG  --log-level info --log-prefix "RULE 30 -- DENY "  
    $IPTABLES -A In_RULE_30_3  -j DROP
    # 
    # Rule 32 (vk63)
    # 
    echo "Rule 32 (vk63)"
    # 
    # br6 IN
    $IPTABLES -N In_RULE_32
    $IPTABLES -A INPUT -m physdev --physdev-in vk63 -p icmp  -m icmp  -s 192.168.50.13   --icmp-type any  -m state --state NEW  -j In_RULE_32  
    $IPTABLES -A FORWARD -m physdev --physdev-in vk63 -p icmp  -m icmp  -s 192.168.50.13   --icmp-type any  -m state --state NEW  -j In_RULE_32  
    $IPTABLES -A In_RULE_32  -j LOG  --log-level info --log-prefix "RULE 32 -- ACCEPT "
    $IPTABLES -A In_RULE_32  -j ACCEPT
    # 
    # Rule 33 (vk64)
    # 
    echo "Rule 33 (vk64)"
    # 
    # br6 IN
    $IPTABLES -N In_RULE_33
    $IPTABLES -A INPUT -m physdev --physdev-in vk64 -p icmp  -m icmp  -s 192.168.50.14   --icmp-type any  -m state --state NEW  -j In_RULE_33  
    $IPTABLES -A FORWARD -m physdev --physdev-in vk64 -p icmp  -m icmp  -s 192.168.50.14   --icmp-type any  -m state --state NEW  -j In_RULE_33  
    $IPTABLES -A In_RULE_33  -j LOG  --log-level info --log-prefix "RULE 33 -- ACCEPT "
    $IPTABLES -A In_RULE_33  -j ACCEPT
    # 
    # Rule 34 (vk64)
    # 
    echo "Rule 34 (vk64)"
    # 
    # br6 IN HTTP
    $IPTABLES -N In_RULE_34
    $IPTABLES -A FORWARD -m physdev --physdev-in vk64 -p tcp -m tcp  -m multiport  -s 192.168.50.14   -d 192.168.0.37   --dports 80,443  -m state --state NEW  -j In_RULE_34   
    $IPTABLES -A In_RULE_34  -j LOG  --log-level info --log-prefix "RULE 34 -- ACCEPT "
    $IPTABLES -A In_RULE_34  -j ACCEPT
    # 
    # Rule 35 (vk65)
    # 
    echo "Rule 35 (vk65)"
    # 
    # br6 IN
    $IPTABLES -N In_RULE_35
    $IPTABLES -A INPUT -m physdev --physdev-in vk65 -p icmp  -m icmp  -s 192.168.50.15   --icmp-type any  -m state --state NEW  -j In_RULE_35
    $IPTABLES -A FORWARD -m physdev --physdev-in vk65 -p icmp  -m icmp  -s 192.168.50.15   --icmp-type any  -m state --state NEW  -j In_RULE_35
    $IPTABLES -A In_RULE_35  -j LOG  --log-level info --log-prefix "RULE 35 -- ACCEPT "
    $IPTABLES -A In_RULE_35  -j ACCEPT
    # 
    # Rule 36 (vethb2)
    # 
    echo "Rule 36 (vethb2)"
    # 
    # br6 border IN
    $IPTABLES -N Cid9698X2034.0
    $IPTABLES -A FORWARD -m physdev --physdev-in vethb2 -p icmp  -m icmp  -s 192.168.50.1   --icmp-type any  -m state --state NEW  -j Cid9698X2034.0  
    $IPTABLES -N In_RULE_36
    $IPTABLES -A Cid9698X2034.0  -d 192.168.50.13   -j In_RULE_36
    $IPTABLES -A Cid9698X2034.0  -d 192.168.50.14   -j In_RULE_36
    $IPTABLES -A Cid9698X2034.0  -d 192.168.50.15   -j In_RULE_36
    $IPTABLES -N Cid9698X2034.1
    $IPTABLES -A FORWARD -m physdev --physdev-in vethb2 -p icmp  -m icmp  -s 192.168.50.1   --icmp-type any  -m state --state NEW  -j Cid9698X2034.1  
    $IPTABLES -A Cid9698X2034.1  -d 192.168.50.13   -j In_RULE_36
    $IPTABLES -A Cid9698X2034.1  -d 192.168.50.14   -j In_RULE_36
    $IPTABLES -A Cid9698X2034.1  -d 192.168.50.15   -j In_RULE_36
    $IPTABLES -N Cid9698X2034.2
    $IPTABLES -A FORWARD -m physdev --physdev-in vethb2 -p icmp  -m icmp  --icmp-type any  -m state --state NEW  -j Cid9698X2034.  2
    $IPTABLES -N Cid9698X2034.3
    $IPTABLES -A Cid9698X2034.2  -s 192.168.0.37   -j Cid9698X2034.3
    $IPTABLES -A Cid9698X2034.2  -s 192.168.50.12   -j Cid9698X2034.3
    $IPTABLES -A Cid9698X2034.3  -d 192.168.50.13   -j In_RULE_36
    $IPTABLES -A Cid9698X2034.3  -d 192.168.50.14   -j In_RULE_36
    $IPTABLES -A Cid9698X2034.3  -d 192.168.50.15   -j In_RULE_36
    $IPTABLES -A In_RULE_36  -j LOG  --log-level info --log-prefix "RULE 36 -- ACCEPT "
    $IPTABLES -A In_RULE_36  -j ACCEPT
    # 
    # Rule 38 (vk42)
    # 
    echo "Rule 38 (vk42)"
    # 
    # br4 IN
    $IPTABLES -N In_RULE_38
    $IPTABLES -A INPUT -m physdev --physdev-in vk42 -p icmp  -m icmp  -s 192.168.50.12   --icmp-type any  -m state --state NEW  -j In_RULE_38
    $IPTABLES -A FORWARD -m physdev --physdev-in vk42 -p icmp  -m icmp  -s 192.168.50.12   --icmp-type any  -m state --state NEW  -j In_RULE_38  
    $IPTABLES -A In_RULE_38  -j LOG  --log-level info --log-prefix "RULE 38 -- ACCEPT "
    $IPTABLES -A In_RULE_38  -j ACCEPT
    # 
    # Rule 39 (vethb1)
    # 
    echo "Rule 39 (vethb1)"
    # 
    # br4 border IN
    $IPTABLES -N Cid15566X9203.0
    $IPTABLES -A FORWARD -m physdev --physdev-in vethb1 -p icmp  -m icmp  -d 192.168.50.1   --icmp-type any  -m state --state NEW  -j Cid15566X9203.0  
    $IPTABLES -N In_RULE_39
    $IPTABLES -A Cid15566X9203.0  -s 192.168.50.13   -j In_RULE_39
    $IPTABLES -A Cid15566X9203.0  -s 192.168.50.14   -j In_RULE_39
    $IPTABLES -A Cid15566X9203.0  -s 192.168.50.15   -j In_RULE_39
    $IPTABLES -N Cid15566X9203.1
    $IPTABLES -A INPUT -m physdev --physdev-in vethb1 -p icmp  -m icmp  -d 192.168.50.1   --icmp-type any  -m state --state NEW  -j Cid15566X9203.1  
    $IPTABLES -A Cid15566X9203.1  -s 192.168.50.13   -j In_RULE_39
    $IPTABLES -A Cid15566X9203.1  -s 192.168.50.14   -j In_RULE_39
    $IPTABLES -A Cid15566X9203.1  -s 192.168.50.15   -j In_RULE_39
    $IPTABLES -N Cid15566X9203.2
    $IPTABLES -A FORWARD -m physdev --physdev-in vethb1 -p icmp  -m icmp  --icmp-type any  -m state --state NEW  -j Cid15566X9203.2  
    $IPTABLES -N Cid15566X9203.3
    $IPTABLES -A Cid15566X9203.2  -d 192.168.0.37   -j Cid15566X9203.3
    $IPTABLES -A Cid15566X9203.2  -d 192.168.50.12   -j Cid15566X9203.3
    $IPTABLES -A Cid15566X9203.3  -s 192.168.50.13   -j In_RULE_39
    $IPTABLES -A Cid15566X9203.3  -s 192.168.50.14   -j In_RULE_39
    $IPTABLES -A Cid15566X9203.3  -s 192.168.50.15   -j In_RULE_39
    $IPTABLES -A In_RULE_39  -j LOG  --log-level info --log-prefix "RULE 39 -- ACCEPT "
    $IPTABLES -A In_RULE_39  -j ACCEPT
    # 
    # Rule 40 (vmh1)
    # 
    echo "Rule 40 (vmh1)"
    # 
    # br4 border IN
    $IPTABLES -N Cid16232X9203.0
    $IPTABLES -A FORWARD -m physdev --physdev-in vmh1 -p icmp  -m icmp  -s 192.168.50.1   --icmp-type any  -m state --state NEW  -j Cid16232X9203.0  
    $IPTABLES -N In_RULE_40
    $IPTABLES -A Cid16232X9203.0  -d 192.168.50.12   -j In_RULE_40
    $IPTABLES -A Cid16232X9203.0  -d 192.168.50.13   -j In_RULE_40
    $IPTABLES -A Cid16232X9203.0  -d 192.168.50.14   -j In_RULE_40
    $IPTABLES -A Cid16232X9203.0  -d 192.168.50.15   -j In_RULE_40
    $IPTABLES -N Cid16232X9203.1
    $IPTABLES -A FORWARD -m physdev --physdev-in vmh1 -p icmp  -m icmp  -s 192.168.50.1   --icmp-type any  -m state --state NEW  -j Cid16232X9203.1   
    $IPTABLES -A Cid16232X9203.1  -d 192.168.50.12   -j In_RULE_40
    $IPTABLES -A Cid16232X9203.1  -d 192.168.50.13   -j In_RULE_40
    $IPTABLES -A Cid16232X9203.1  -d 192.168.50.14   -j In_RULE_40
    $IPTABLES -A Cid16232X9203.1  -d 192.168.50.15   -j In_RULE_40
    $IPTABLES -N Cid16232X9203.2
    $IPTABLES -A FORWARD -m physdev --physdev-in vmh1 -p icmp  -m icmp  -s 192.168.0.37   --icmp-type any  -m state --state NEW  -j Cid16232X9203.2  
    $IPTABLES -A Cid16232X9203.2  -d 192.168.50.12   -j In_RULE_40
    $IPTABLES -A Cid16232X9203.2  -d 192.168.50.13   -j In_RULE_40
    $IPTABLES -A Cid16232X9203.2  -d 192.168.50.14   -j In_RULE_40
    $IPTABLES -A Cid16232X9203.2  -d 192.168.50.15   -j In_RULE_40
    $IPTABLES -A In_RULE_40  -j LOG  --log-level info --log-prefix "RULE 40 -- ACCEPT "
    $IPTABLES -A In_RULE_40  -j ACCEPT
    # 
    # Rule 42 (vmh2)
    # 
    echo "Rule 42 (vmh2)"
    # 
    # external are IN
    $IPTABLES -N Cid16691X6788.0
    $IPTABLES -A INPUT -i vmh2  -p icmp  -m icmp  -d 192.168.50.1   --icmp-type any  -m state --state NEW  -j Cid16691X6788.0  
    $IPTABLES -N In_RULE_42
    $IPTABLES -A Cid16691X6788.0  -s 192.168.50.12   -j In_RULE_42
    $IPTABLES -A Cid16691X6788.0  -s 192.168.50.13   -j In_RULE_42
    $IPTABLES -A Cid16691X6788.0  -s 192.168.50.14   -j In_RULE_42
    $IPTABLES -A Cid16691X6788.0  -s 192.168.50.15   -j In_RULE_42
    $IPTABLES -N Cid16691X6788.1
    $IPTABLES -A FORWARD -i vmh2  -p icmp  -m icmp  -d 192.168.0.37   --icmp-type any  -m state --state NEW  -j Cid16691X6788.1  
    $IPTABLES -A Cid16691X6788.1  -s 192.168.50.12   -j In_RULE_42
    $IPTABLES -A Cid16691X6788.1  -s 192.168.50.13   -j In_RULE_42
    $IPTABLES -A Cid16691X6788.1  -s 192.168.50.14   -j In_RULE_42
    $IPTABLES -A Cid16691X6788.1  -s 192.168.50.15   -j In_RULE_42
    $IPTABLES -A In_RULE_42  -j LOG  --log-level info --log-prefix "RULE 42 -- ACCEPT "
    $IPTABLES -A In_RULE_42  -j ACCEPT
    # 
    # Rule 43 (vmh2)
    # 
    echo "Rule 43 (vmh2)"
    # 
    # host border OUT
    $IPTABLES -N Cid16236X6788.0
    $IPTABLES -A OUTPUT -o vmh2  -p icmp  -m icmp  -s 192.168.50.1   --icmp-type any  -m state --state NEW  -j Cid16236X6788.0  
    $IPTABLES -N Out_RULE_43
    $IPTABLES -A Cid16236X6788.0  -d 192.168.50.12   -j Out_RULE_43
    $IPTABLES -A Cid16236X6788.0  -d 192.168.50.13   -j Out_RULE_43
    $IPTABLES -A Cid16236X6788.0  -d 192.168.50.14   -j Out_RULE_43
    $IPTABLES -A Cid16236X6788.0  -d 192.168.50.15   -j Out_RULE_43
    $IPTABLES -N Cid16236X6788.1
    $IPTABLES -A FORWARD -o vmh2  -p icmp  -m icmp  -s 192.168.0.37   --icmp-type any  -m state --state NEW  -j Cid16236X6788.1  
    $IPTABLES -A Cid16236X6788.1  -d 192.168.50.12   -j Out_RULE_43
    $IPTABLES -A Cid16236X6788.1  -d 192.168.50.13   -j Out_RULE_43
    $IPTABLES -A Cid16236X6788.1  -d 192.168.50.14   -j Out_RULE_43
    $IPTABLES -A Cid16236X6788.1  -d 192.168.50.15   -j Out_RULE_43
    $IPTABLES -A Out_RULE_43  -j LOG  --log-level info --log-prefix "RULE 43 -- ACCEPT "
    $IPTABLES -A Out_RULE_43  -j ACCEPT
    # 
    # Rule 45 (br0)
    # 
    echo "Rule 45 (br0)"
    # 
    # external
    $IPTABLES -A OUTPUT -o br0   -m state --state NEW  -j ACCEPT
    # 
    # Rule 46 (br0)
    # 
    echo "Rule 46 (br0)"
    # 
    # external
    $IPTABLES -A FORWARD -i br0   -s 192.168.0.10   -d 192.168.0.255   -m state --state NEW  -j ACCEPT
    $IPTABLES -A INPUT -i br0   -s 192.168.0.10   -d 192.168.0.255   -m state --state NEW  -j ACCEPT
    $IPTABLES -A INPUT -i br0   -s 192.168.0.10   -m state --state NEW  -j ACCEPT
    # 
    # Rule 47 (global)
    # 
    echo "Rule 47 (global)"
    # 
    $IPTABLES -N RULE_47
    $IPTABLES -A OUTPUT  -j RULE_47
    $IPTABLES -A INPUT  -j RULE_47
    $IPTABLES -A FORWARD  -j RULE_47
    $IPTABLES -A RULE_47  -j LOG  --log-level info --log-prefix "RULE 47 -- DENY "
    $IPTABLES -A RULE_47  -j DROP

The variable “$IPTABLES” identifies the local iptables command. As already discussed in the last articles we arranged our (virtual) guest systems, the virtualization host and external systems in 3 defined host groups in FWbuilder (see the last post):

  • br6_grp: kali3, kali4, kali5,
  • br4_grp: kali2,
  • ext_grp: the host and some external web server “lamp”.

Remember that rules for bridge-ports are investigated separately and independently as a packet moves from one bridge to another. Note that the host and further systems attached to “virbr4” via a veth device “vmh2” are recognized as members of a distinct logical host area for which iptables rules again are reinvestigated separatly by the kernel during packet transport. Therefore we need ACCEPT rules to allow for incoming and outgoing packets at the host’s interface “vmh2”.

Examples of spoofing scenarios

With 2 bridges in place we can define already a variety of ARP spoofing scenarios with a subsequent MiM-attack. We only test some selected, but typical scenarios. Note again that we cannot prevent the act of spoofing itself with iptables – however, we can prevent that redirected packets arrive at the MiM system.

Example 1: kali2 of virbr4 attacks the communication between kali3 and kali5 within virbr6

Which rule do we expect to prevent this? Actually as kali2 tries to redirect the intended communication from bridge virbr6 into bridge virbr4 we would already expect a DENY rule at the border port “vethb2” to stop redirected packets. In our rules list this would be rule 16.

So let us see. We start ARP spoofing on kali2:

root@kali2: ~# echo 1 > /proc/sys/net/ipv4/ip_forward
root@kali2: ~# iptables -A OUTPUT -p icmp --icmp-type redirect -j REJECT
root@kali2: ~# arpspoof -i eth3 -t 192.168.50.13 192.168.50.14 & 2> /dev/null  
root@kali2: ~# arpspoof -i eth3 -t 192.168.50.14 192.168.50.13 & 2> /dev/null  

eth3 is the relevant Ethernet interface to net 192.168.50.0/24 on guest kali2.
After some time we get the following ARP information on e.g. kali3:

bridges_1

Consequently, after a “journalctl -f” on the virtualization host we find: :

Mar 17 13:21:53 mytux kernel: RULE 16 -- DENY IN=virbr6 OUT=virbr6 PHYSIN=vk63 PHYSOUT=vethb2 MAC=52:54:00:f2:a4:8d:52:54:00:b1:5d:1f:08:00 SRC=192.168.50.13 DST=192.168.50.14 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=16140 DF PROTO=ICMP TYPE=8 CODE=0 ID=1756 SEQ=1   
Mar 17 13:21:54 mytux kernel: RULE 16 -- DENY IN=virbr6 OUT=virbr6 PHYSIN=vk63 PHYSOUT=vethb2 MAC=52:54:00:f2:a4:8d:52:54:00:b1:5d:1f:08:00 SRC=192.168.50.13 DST=192.168.50.14 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=16252 DF PROTO=ICMP TYPE=8 CODE=0 ID=1756 SEQ=2  
 

Our test example shows that rules for border ports help to isolate bridges against misguided packets.

Rule 16 deserves a closer look as it contains a logical negation of 2 separately defined groups of hosts. We see that FWbuilder compiles the negation internally correctly: The related subchain definition contains all required hosts.

As described in the previous articles we stop the attack by the command “killall arpspoof” on kali2. Remember that due to time limits for ARP and port caching information on the guests and the bridge, respectively, it may take some time until normal operation is possible again. See the first article of this series for more information on this topic.

Example 2: kali2 of virbr4 attacks the communication between kali3 and the virtualization host

In this scenario a regular (!) packet would propagate from virbr6 through virbr4 and then to the host. Therefore, neither border port rules for virbr6 nor for virbr4 can block the traffic. We must, instead, rely on the analysis of redirected packets following an OUT direction to port vk42 – this is rule 5.

Therefore, this example is just a repetition of what we learned in the first article of this series
Linux bridges – can iptables be used against MiM attacks based on ARP spoofing ? – I

Actually, after another spoofing attack by kali2

root@kali2: ~# arpspoof -i eth3 -t 192.168.50.1 192.168.50.13 & 2> /dev/null  
root@kali2: ~# arpspoof -i eth3 -t 192.168.50.13 192.168.50.1 & 2> /dev/null  

and sending pings from kali3 to the host we get:

Mar 17 18:44:51 mytux kernel: RULE 32 -- ACCEPT IN=virbr6 OUT=virbr6 PHYSIN=vk63 PHYSOUT=vethb2 MAC=54:00:f2:a4:8d:52:54:00:b1:5d:1f:08:00 SRC=192.168.50.13 DST=192.168.50.1 LEN=84 TOS=0x00 PREC=0x00 =64 ID=48428 DF PROTO=ICMP TYPE=8 CODE=0 ID=2872 SEQ=2   
Mar 17 18:44:51 mytux kernel: RULE 5 -- DENY IN=virbr4 OUT=virbr4 PHYSIN=vethb1 PHYSOUT=vk42 MAC=52:50:f2:a4:8d:52:54:00:b1:5d:1f:08:00 SRC=192.168.50.13 DST=192.168.50.1 LEN=84 TOS=0x00 PREC=0x00 TTL ID=48428 DF PROTO=ICMP TYPE=8 CODE=0 ID=2872 SEQ=2 
   

We see that the transition from bridge virbr6 to virbr4 works as planned – however the packets redirected to the MiM kali2 are stopped at vk42. Good!

Example 3: kali3 of virbr6 attacks the communication between kali4 of virbr4 and the virtualization host

We look at pings issued from the host to kali4 after an attack of kali3. In this case the border port rules again must not block. Instead, we rely on local port rules at port vk63, .i.e. rule 2. Indeed:

Mar 17 19:00:39 mytux kernel: RULE 43 -- ACCEPT IN= OUT=vmh2 SRC=192.168.50.1 DST=192.168.50.14 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=53576 DF PROTO=ICMP TYPE=8 CODE=0 ID=2981 SEQ=1 
Mar 17 19:00:39 mytux kernel: RULE 40 -- ACCEPT IN=virbr4 OUT=virbr4 PHYSIN=vmh1 PHYSOUT=vethb1 MAC=52:54:00:b1:5d:1f:7a:ff:fc:bd:68:b6:08:00 SRC=192.168.50.1 DST=192.168.50.14 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=53576 DF PROTO=ICMP TYPE=8 CODE=0 ID=2981 SEQ=1       
Mar 17 19:00:39 mytux kernel: RULE 2 -- DENY IN=virbr6 OUT=virbr6 PHYSIN=vethb2 PHYSOUT=vk63 MAC=52:54:00:b1:5d:1f:7a:ff:fc:bd:68:b6:08:00 SRC=192.168.50.1 DST=192.168.50.14 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=53576 DF PROTO=ICMP TYPE=8 CODE=0 ID=2981 SEQ=1     
  

Example 4: kali3 of virbr6 attacks the communication between kali2 and the virtualization host

In this case border rules should stop redirected packets. For our test case this would in particular be rule 18.

And – after the initialization of the attack by kali3 and the trial to send pings from kali2 to the host, we get:

Mar 18 16:47:30 mytux kernel: RULE 18 -- DENY IN=virbr4 OUT=virbr4 PHYSIN=vk42 PHYSOUT=vethb1 MAC=52:54:00:b1:5d:1f:52:54:00:f2:a4:8d:08:00 SRC=192.168.50.12 DST=192.168.50.1 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=4405 DF PROTO=ICMP TYPE=8 CODE=0 ID=2420 SEQ=1    
  

And vice versa :

Mar 18 16:48:42 mytux kernel: RULE 43 -- ACCEPT IN= OUT=vmh2 SRC=192.168.50.1 DST=192.168.50.12 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=63251 DF PROTO=ICMP TYPE=8 CODE=0 ID=21778 SEQ=1  
Mar 18 16:48:42 mytux kernel: RULE 18 -- DENY IN=virbr4 OUT=virbr4 PHYSIN=vmh1 PHYSOUT=vethb1 MAC=52:54:00:b1:5d:1f:f2:be:a1:5a:cd:6e:08:00 SRC=192.168.50.1 DST=192.168.50.12 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=63251 DF PROTO=ICMP TYPE=8 CODE=0 ID=21778 SEQ=1   
   

As expected!

Example 5: The host attacks communication between guests attached to an inner bridge

One may think such an example is just academic. Actually, in my opinion it is not. Although the administrator of a virtualization host has in principle a variety of means available to follow any communication across a bridge, ARP spoofing should NOT be such a measure under normal operation conditions. In addition, there may be legal aspects in a professional hosting situation.

But more important: From the perspective of the involved bridges, in our setup the host is attached to bridge virbr4 as an external guest over a border port. Rules for the virtualization host are, therefore, only an example for similar rules applied to other external hosts which may have the allowance to communicate with bridge guests – via forwarding and a respective route defined on the virtualization host.

We expect rule 20 to stop packages redirected by the MiM:

Mar 18 17:38:38 rux kernel: RULE 32 -- ACCEPT IN=virbr6 OUT=virbr6 PHYSIN=vk63 PHYSOUT=vethb2 MAC=f2:be:a1:5a:cd:6e:52:54:00:b1:5d:1f:08:00 SRC=192.168.50.13 DST=192.168.50.12 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=36173 DF PROTO=ICMP TYPE=8 CODE=0 ID=2218 SEQ=1   
Mar 18 17:38:38 rux kernel: RULE 20 -- DENY IN=virbr4 OUT=virbr4 PHYSIN=vethb1 PHYSOUT=vmh1 MAC=f2:be:a1:5a:cd:6e:52:54:00:b1:5d:1f:08:00 SRC=192.168.50.13 DST=192.168.50.12 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=36173 DF PROTO=ICMP TYPE=8 CODE=0 ID=2218 SEQ=1   
 

And vice versa

Mar 18 17:39:39 rux kernel: RULE 20 -- DENY IN=virbr4 OUT=virbr4 PHYSIN=vk42 PHYSOUT=vmh1 MAC=f2:be:a1:5a:cd:6e:52:54:00:f2:a4:8d:08:00 SRC=192.168.50.12 DST=192.168.50.13 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=10910 DF PROTO=ICMP TYPE=8 CODE=0 ID=2730 SEQ=1    
Mar 18 17:39:40 rux kernel: RULE 20 -- DENY IN=virbr4 OUT=virbr4 PHYSIN=vk42 PHYSOUT=vmh1 MAC=f2:be:a1:5a:cd:6e:52:54:00:f2:a4:8d:08:00 SRC=192.168.50.12 DST=192.168.50.13 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=11113 DF PROTO=ICMP TYPE=8 CODE=0 ID=2730 SEQ=2    
 

Summary

So, all in all, for our few examples we could verify that our recipe for setting up iptables rules in case of several linked Linux bridges with guests on one [KVM] virtualization host guided us correctly. After associating unique IP addresses with bridge ports we can define rules that block the transport of packets redirected to a MiM system – even when multiple bridges are present on the virtualization host. Additional and special rules for the bridges’ border ports help to prevent irregular traffic between defined groups of guests and/or external hosts.

Note that we only demonstrated this for specific allowance rules for the ICMP protocol. Yet, it is easy to understand that the very same principles should work for any protocol on level 4.

 

Linux bridges – can iptables be used against MiM attacks based on ARP spoofing ? – II

In the last post
Linux bridges – can iptables be used against MiM attacks based on ARP spoofing ? – I
of this series we saw that iptables rules with options like

-m physdev –physdev-in/out device

may help in addition to other netfilter tools (for lower layers) to block redirected traffic to a “man in the middle system” on a Linux bridge.

Tools like FWbuilder support the creation of such “physdev”-related rules as soon as bridge devices are marked as bridged in the interface definition process for the firewall host. However, we have also seen that we need to bind IP addresses to certain bridge ports. This in turn requires knowledge about a predictable IP-to-port-configuration.

Such a requirement may be an obstacle for using iptables in scenarios with many virtual guests on one or several Linux bridges of a virtualization host as it reduces flexibility for automated IP address assignment.

Before we discuss administrative aspects in a further post, let us expand our iptables rules to a more complex situation:

In this post we discuss a scenario with 2 linked Linux bridges “virbr4” and “virbr6” plus the host attached to “virbr4”. This provides us with a virtual infrastructure for which we need to construct a more complex, but more general set of rules in comparison to what we discussed in the last article. We will look at the required rules and their order. Testing of the rules will be done in a forthcoming post.

Two coupled bridges and the host attached via veth devices

You see my virtual bridge setup in the following drawing.

(Note for those who read the article before: I have exchanged the picture a bit to make it consistent with a forthcoming post. The port for kali2 has been renamed to “vk42”).

bridge3

The small blue rectangles inside the bridges symbolize standard Linux tap devices – whereas the RJ45 like rectangles symbolize veth devices. veth pairs deliver a convenient way on a Linux system to link bridges and to attach the host to them in a controllable way. As a side effect one can avoid to assign the bridge itself an IP address. See:
Fun with veth devices, Linux virtual bridges, KVM, VMware – attach the host and connect bridges via veth

In the drawing you recognize our bridge “virbr6” and its guests from the 1st post of this series. The new bridge “virbr4” is only equipped with one guest (kali2); this is sufficient for our test case purposes. Of course, you could have many more guests there in more realistic scenarios. Note that attaching certain groups of guests to distinct bridges also occurs in physical reality for a variety of reasons.

Two types of ports

For the rest of this post we call ports as vethb2 on virbr6 as well as vethb1 and vmh1 on virbr4 “border ports” of their respective bridges. Such border ports

  • connect a bridge to another bridge,
  • connect a bridge to the virtualization host
  • or connect the bridge to hosts on external, physically real Ethernet segments.

We remind the reader that it always is the perspective of the bridge that decides about the INcoming or OUTgoing direction of an Ethernet packet via a specific port when we define respective IN/OUT iptables rules.

Therefore, packets crossing a border port in the IN direction always come from outside the bridge. Packets leaving the port OUTwards may however come from guests of the bridge itself AND from guests outside other border ports of the very same bridge.

In contrast to border ports we shall call a port of a bridge with just one defined guest behind it a “guest port”. [In our test case the bridge connection of guests is realized with tap devices because this is convenient with KVM. In the case of LXC and docker containers we would rather see veth-pairs.]

Multiple bridges on one host – how are the iptables rules probed by the kernel?

Just from looking at the sketch above we see a logical conundrum, which has a significant impact on the setup of iptables rules on a host with multiple bridges in place:

A packet created at one of the ports may leave the bridge where it has been created and travel into a neighboring bridge via border ports. But when and how are port-related iptables-rules tested by the kernel as the packet travels – lets e.g. say from kali5 to the guest at “vnet0” or to the host at “vmh2”?

  • Bridge for bridge – IN-Port-rules, then OUT-port-rules on the same first bridge => afterwards IN-port-rules/OUT-port-rules again – but this time for the ports of the next entered bridge?
  • Or: iptables rules are checked only once, but globally and for all bridges – with some knowledge of port-MAC-relations of the different bridges included?

If the latter were true just one passed ACCEPT rule on a single bridge port would lead to an overall acceptance of a packet despite the fact that the packet possibly will cross further bridges afterward. Such a behavior would be unreasonable – but who knows …

So the basic question is:

After having been checked on a first bridge, having been accepted for leaving one border port of this first bridge and then having entered a second linked bridge via a corresponding border port – will the packet be checked again against all denial and acceptance rules of the second bridge? Will the packet with its transportation attributes be injected again into the whole set of iptables rules?

It is obvious that the answer would have an impact of how we need to define our rules. Especially during port flooding, which we already observed in the tests described in our first article.

Tests of the order of iptables rules probing for ports of multiple bridges on a packet’s path

As a first test we do something very simple: we define some iptables rules for ICMP pings formally in the following logical order: We first deny a passage through vethb1 on virbr4 before we allow the packet to pass vethb2 on virbr6:

bridge vibr4 rule 15:  src 192.168.50.14, dest 192.168.50.1 - ICMP IN vethb1 => DENY   
bridge vibr6 rule 16:  src 192.168.50.14, dest 192.168.50.1 - ICMP OUT vethb2 => ALLOW    

and then we test the order of how these rules are passed by logging them.

To avoid any wrong or missing ARP information on the involved guest/host systems and missing MAC-port-relations in the “forward databases” [FWB] of the bridges we first clear any iptables rules and try some pings. Then we activate the rules and get the following results for ping packets sent from kali4 to the host:

2016-02-27T12:09:33.295145+01:00 mytux kernel: [ 
5127.067043] RULE 16 -- ACCEPT IN=virbr6 OUT=virbr6 PHYSIN=vk64 PHYSOUT=vethb2 MAC=96:b0:a9:7c:73:7d:52:54:00:74:60:4a:08:00 SRC=192.168.50.14 DST=192.168.50.1 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=22031 DF PROTO=ICMP TYPE=8 CODE=0 ID=1711 SEQ=1     
2016-02-27T12:09:33.295158+01:00 mytux kernel: [ 5127.067062] RULE 15 -- DENY IN=virbr4 OUT=virbr4 PHYSIN=vethb1 PHYSOUT=vmh1 MAC=96:b0:a9:7c:73:7d:52:54:00:74:60:4a:08:00 SRC=192.168.50.14 DST=192.168.50.1 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=22031 DF PROTO=ICMP TYPE=8 CODE=0 ID=1711 SEQ=1    
2016-02-27T12:09:34.302140+01:00 mytux kernel: [ 5128.075040] RULE 16 -- ACCEPT IN=virbr6 OUT=virbr6 PHYSIN=vk64 PHYSOUT=vethb2 MAC=96:b0:a9:7c:73:7d:52:54:00:74:60:4a:08:00 SRC=192.168.50.14 DST=192.168.50.1 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=22131 DF PROTO=ICMP TYPE=8 CODE=0 ID=1711 SEQ=2 
2016-02-27T12:09:34.302153+01:00 mytux kernel: [ 5128.075056] RULE 15 -- DENY IN=virbr4 OUT=virbr4 PHYSIN=vethb1 PHYSOUT=vmh1 MAC=96:b0:a9:7c:73:7d:52:54:00:74:60:4a:08:00 SRC=192.168.50.14 DST=192.168.50.1 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=22131 DF PROTO=ICMP TYPE=8 CODE=0 ID=1711 SEQ=2   
 

Now we do a reverse test: We allow the incoming direction over port vk64 of virbr6 before we deny the incoming package over vethb1 on virbr4:

bridge vibr6 rule :  src 192.168.50.14, dest 192.168.50.1 - IN vk64 => ALLOW   
bridge vibr4 rule :  src 192.168.50.14, dest 192.168.50.1 - IN vethb1 => DENY     
 

We get

2016-02-27T14:02:32.821286+01:00 mytux kernel: [11913.962828] RULE 15 -- ACCEPT IN=virbr6 OUT=virbr6 PHYSIN=vk64 PHYSOUT=vethb2 MAC=96:b0:a9:7c:73:7d:52:54:00:74:60:4a:08:00 SRC=192.168.50.14 DST=192.168.50.1 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=21400 DF PROTO=ICMP TYPE=8 CODE=0 ID=2104 SEQ=1     
2016-02-27T14:02:32.821307+01:00 mytux kernel: [11913.962869] RULE 16 -- DENY IN=virbr4 OUT=virbr4 PHYSIN=vethb1 PHYSOUT=vmh1 MAC=96:b0:a9:7c:73:7d:52:54:00:74:60:4a:08:00 SRC=192.168.50.14 DST=192.168.50.1 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=21400 DF PROTO=ICMP TYPE=8 CODE=0 ID=2104 SEQ=1 
2016-02-27T14:02:33.820257+01:00 mytux kernel: [11914.962965] RULE 15 -- ACCEPT IN=virbr6 OUT=virbr6 PHYSIN=vk64 PHYSOUT=vethb2 MAC=96:b0:a9:7c:73:7d:52:54:00:74:60:4a:08:00 SRC=192.168.50.14 DST=192.168.50.1 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=21494 DF PROTO=ICMP TYPE=8 CODE=0 ID=2104 SEQ=2    
2016-02-27T14:02:33.820275+01:00 mytux kernel: [11914.962987] RULE 16 -- DENY IN=virbr4 OUT=virbr4 PHYSIN=vethb1 PHYSOUT=vmh1 MAC=96:b0:a9:7c:73:7d:52:54:00:74:60:4a:08:00 SRC=192.168.50.14 DST=192.168.50.1 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=21494 DF PROTO=ICMP TYPE=8 CODE=0 ID=2104 SEQ=2   
  

So to our last test:

bridge vibr6 rule :  src 192.168.50.14, dest 192.168.50.1 - IN vk64 => ALLOW    
bridge vibr6 rule :  src 192.168.50.14, dest 192.168.50.1 - IN vethb2 => DENY   
bridge vibr4 rule :  src 192.168.50.14, dest 192.168.50.1 - IN vethb1 => DENY  
  

We get:

2016-02-27T14:26:08.964616+01:00 mytux kernel: [13331.634200] RULE 15 -- ACCEPT IN=virbr6 OUT=virbr6 PHYSIN=vk64 PHYSOUT=vethb2 MAC=96:b0:a9:7c:73:7d:52:54:00:74:60:4a:08:00 SRC=192.168.50.14 DST=192.168.50.1 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=27122 DF PROTO=ICMP TYPE=8 CODE=0 ID=2218 SEQ=1   
2016-02-27T14:26:08.964633+01:00 mytux kernel: [13331.634232] RULE 17 -- DENY IN=virbr4 OUT=virbr4 PHYSIN=vethb1 PHYSOUT=vmh1 MAC=96:b0:a9:7c:73:7d:52:54:00:74:60:4a:08:00 SRC=192.168.50.14 DST=192.168.50.1 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=27122 DF PROTO=ICMP TYPE=8 CODE=0 ID=2218 SEQ=1  
2016-02-27T14:26:09.972621+01:00 mytux kernel: [13332.643587] RULE 15 -- ACCEPT IN=virbr6 OUT=virbr6 PHYSIN=vk64 PHYSOUT=vethb2 MAC=96:b0:a9:7c:73:7d:52:54:00:74:60:4a:08:00 SRC=192.168.50.14 DST=192.168.50.1 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=27347 DF PROTO=ICMP TYPE=8 CODE=0 ID=2218 SEQ=2 
2016-02-27T14:26:09.972637+01:00 mytux kernel: [13332.643605] RULE 17 -- DENY IN=virbr4 OUT=virbr4 PHYSIN=vethb1 PHYSOUT=vmh1 MAC=96:b0:a9:7c:73:7d:52:54:00:74:60:4a:08:00 SRC=192.168.50.14 DST=192.168.50.1 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=27347 DF PROTO=ICMP TYPE=8 CODE=0 ID=2218 SEQ=2   
 

Intermediate conclusions

We can conclude the following points:

  • A packet is probed per bridge – in the order of how multiple bridges of the host are passed by the packet.
  • An ALLOW rule for a port on one bridge does not overrule a DENY rule for a port on a second bridge which the package may pass on its way.
  • A packet is tested both for IN/OUT conditions of a FORWARD rule for each bridge it passes.
  • If we split IN and OUT rules on a bridge (as we need to do within some tools as FWbuilder) than we must probe the OUT rules first to guarantee the prevention of illegal packet transport.

For the rest of the post we shall follow the same rule we already used as a guide line in the previous post:
Our general iptables policy is that a packet will be denied if it is not explicitly accepted by one of the tested rule.

Blocking of border ports in port flooding situations

During our tests in the last post we have seen that port flooding situations may occur – depending among other things on the “setaging” parameter of the bridge and the resulting deletion of stale entries in the “Forward Database” [FWD] of a bridge. Flooding of veth based border ports may be critical for packet transmission and may have to be blocked in some cases.

E.g., it would be unreasonable to transfer packets logically meant for hosts beyond port vmh1 of virbr4 over vethb1/2 to virbr6. We would stop such packets already via OUT DENY rules for vethb1:

bridge vibr4 rule :  src "guest of virbr4", dest "no guest of virbr6" - OUT vethb1 => DENY  

Rules regarding packets just crossing and passing a bridge

Think about a bridge “virbrx” linked on its both sides to two other bridges “virbr_left” and “virbr_right”. In such a scenario packets could arrive at virbrx from bridge virbr_right, enter the intermediate bridge virbrx and leave it at once again for the third bridge virbr_left – because it never was destined to any guest of bridge virbrx.

For such packets we need at least one ACCEPT rule om virbrx – either on the IN direction of the border port of virbrx against virbr_right or on the OUT direction at the border port to virbr_left.

Again, we cling to our policy of the last article:
We define DENY rules for outgoing packets at all ports – also for border ports – and put these DENY rules to the top of the iptables list; then we define DENY rules for ports which are passed in IN direction; only after that we define ACCEPT rules for incoming packets for all ports of a bridge – including border ports – and set these rules below/after the DENIAL rules. This should provide us with a consistent handling also of packets crossing and passing bridges.

Grouping of guests/hosts

From looking at the drawing above we also understand the following point:
In order to handle packets at border ports connecting two bridges we have the choice to block packets at either border port – i.e. before the OUTgoing port passage on the first bridge OR before the INcoming port passage on the second. We shall do the blocking at the port in the packets OUTgoing direction. Actually, there would be no harm in setting up reasonable DENY rules for both ports. Then we would safely cover all types of situations.

Anyway – we also find that the rules for border ports require a certain grouping of the guests and hosts:

  • Group 1: Guests attached to the bridge that has a border port.
  • Group 2: Guests on the IN side of the border port of a bridge – i.e. the internal side of the bridge. This group includes Group 1 plus external guests of further bridges beyond other border ports of the very same bridge.
  • Group 3:Guests on the outgoing side of a border port – i.e. the side to the next connected bridge. This group contains hosts of Group 1 for the next connected bridge and/or groups of external hosts on the OUT side of all other border ports of the connected bridge.

These groups can easily be formed per bridge by tools like FWbuilder. Without going into details: Note that FWbuilder handles the overall logical OR/AND switching during a negation of multiple groups of hosts correctly when compiling iptables rules.

Overall rules order in case of multiple and connected bridges

Taking into account the results of the first post in this series I suggest the following order of iptables rules:

  • We first define OUT DENY rules for all guest ports of all bridges – with ports grouped by bridges just to keep the overview. These rules are the most important ones to prevent ARP spoofing and a resulting packet redirection.
  • We then define all OUT DENY rules for border ports of all bridges – first grouped by bridges and then per bridge and ports grouped by hosts for the OUTgoing direction. These rules cover also port flooding situations with respect to neighboring linked bridges.
  • We then define IN DENY rules for incoming packets over border ports. These rules may in addition to the previous rules prevent implausible packet transport.
  • Now we apply OUT DENY and IN DENY rules for Ethernet devices on the virtualization host. Such rules must must not be forgotten and can be placed here in the rules’ sequence.
  • We then define IN ACCEPT rules on individual guest ports – ports again grouped by bridges.
  • We eventually define IN ACCEPT rules on bridge border ports – note that such rules are required for packets just passing an intermediate bridge without being destined to a guest of the bridge.
  • IN ACCEPT rules for the virtualization hosts’s Ethernet interfaces must not be forgotten and can be placed at the end.

How does that look like in FWbuilder?

Before looking at the pics note that we have defined the host groups

  • br6_grp to contain kali3, kali4, kali5,
  • br4_grp to contain only kali2,
  • ext_grp to contain the host and some external web server “lamp“.

With this we get the following 7 groups of rules:

full_1

full_2

full_3

full_4

full_5

full_6

full_7

Despite the host grouping : this makes quite a bunch of rules! But not uncontrollable …

Enough for today. I hope that tests being performed in a third post of this series will not proof me wrong. I am confident …. See
Linux bridges – can iptables be used against MiM attacks based on ARP spoofing ? – III