diff --git a/imgs/base-alpine/bin/wait4network b/imgs/base-alpine/bin/wait4network
index f59c447141367a54339890b46d321e399561bbf8..d4fd2d8d45e53a13b41443ea9b53062e326796e5 100755
--- a/imgs/base-alpine/bin/wait4network
+++ b/imgs/base-alpine/bin/wait4network
@@ -1,8 +1,8 @@
 #!/bin/sh
 # This file is part of NSFarm
-# Call this script to block execution untill there is internet connection.
+# Call this script to block execution untill there is default route present.
 
 echo waiting for network
-while ! ping -c 1 nic.cz >/dev/null 2>&1; do
+while ! ip route | grep -q default; do
 	sleep 1
 done
diff --git a/nsfarm/board/_board.py b/nsfarm/board/_board.py
index f3375b39277448ed493fa5e492e5e9b56393fedb..b4c9befa2a9ccc8ca25e93289de9ce6421130799 100644
--- a/nsfarm/board/_board.py
+++ b/nsfarm/board/_board.py
@@ -79,8 +79,9 @@ class Board:
         # Wait for bootup
         self._pexpect.expect_exact(["Router Turris successfully started.", ], timeout=120)
         # Note Shell sends new line which opens terminal for it
-        # TODO why this flush timeouts?
-        return cli.Shell(self._pexpect, flush=False)
+        shell = cli.Shell(self._pexpect, flush=False)  # TODO why this flush timeouts?
+        shell.run("sysctl -w kernel.printk='0 4 1 7'")  # disable kernel print to not confuse console flow
+        return shell
 
     def _board_bootup(self, uboot):
         """Board specific bootup routine.
diff --git a/nsfarm/cli.py b/nsfarm/cli.py
index 80534a985d48b1d08269ec11a7ac570adc992309..c1fdc30d5d92c4f5bf347ec364cfbd54a66ac672 100644
--- a/nsfarm/cli.py
+++ b/nsfarm/cli.py
@@ -10,6 +10,7 @@ import base64
 def pexpect_flush(pexpect_handle):
     """Flush all input on pexpect. This effectively reads everything.
     """
+    # TODO fix: this timeouts if there is nothing to flush
     bufflen = 2048
     while len(pexpect_handle.read_nonblocking(bufflen)) == bufflen:
         pass
@@ -95,6 +96,7 @@ class Shell(Cli):
         r"(\r\n|\n\r|^).+? ($|#) ",
         r"(\r\n|\n\r|^)bash-.+?($|#) ",
         r"(\r\n|\n\r|^)root@[a-zA-Z0-9_-]*:",
+        r"(\r\n|\n\r|^).*root@turris.*#",  # TODO this is weird dual prompt from lxd ssh
         _NSF_PROMPT,
     ]
     # TODO compile prompt regexp to increase performance
diff --git a/tests/conftest.py b/tests/conftest.py
index b68e35078d2924c1308003c9959275472b775b1c..54778378320402ee286bf5d48bdce62849895470 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -1,3 +1,6 @@
+import time
+import random
+import string
 import pytest
 import nsfarm.board
 import nsfarm.cli
@@ -34,8 +37,8 @@ def fixture_lan1(request):
 ########################################################################################################################
 ## Boot and setup fixtures #############################################################################################
 
-@pytest.fixture(scope="session")
-def board_shell(request, board, wan):
+@pytest.fixture(name="board_serial", scope="session")
+def fixture_board_serial(request, board, wan):
     """Boot board to Shell.
     Provides instance of nsfarm.cli.Shell()
     """
@@ -43,11 +46,61 @@ def board_shell(request, board, wan):
     return board.bootup(wan)
 
 
+@pytest.fixture(name="board_root_password", scope="session")
+def fixture_board_root_password(request, board_serial):
+    """Sets random password for user root.
+    Returns configured random password
+    """
+    password = ''.join(random.choice(string.ascii_lowercase) for i in range(16))
+    board_serial.run("echo 'root:{}' | chpasswd".format(password))
+    request.addfinalizer(lambda: board_serial.run("passwd --delete root"))
+    return password
+
+
+@pytest.fixture(name="client_board", scope="session")
+def fixture_client_board(board, board_serial, board_root_password, lan1):
+    """Starts client on LAN1 and connect to board using SSH.
+    Provides instance of nsfarm.cli.Shell() connected to board shell using SSH trough client container.
+    """
+    # Let's have syslog on serial console as well as kernel log
+    board_serial.command('tail -f /var/log/messages')
+    # Now spawn client container and connect
+    with nsfarm.lxd.Container('client', devices=[lan1, ], internet=False) as container:
+        nsfarm.cli.Shell(container.pexpect()).run('wait4network')
+        pexp = container.pexpect(['ssh', '192.168.1.1'])
+        pexp.expect_exact("root@192.168.1.1's password:")
+        pexp.sendline(board_root_password)
+        pexp.expect_exact("root@turris:")
+        yield nsfarm.cli.Shell(pexp, flush=False)  # TODO drop this flush disable when it works
+    # Kill tail -f on serial console
+    board_serial.send('\x03')
+    board_serial.prompt()
+
+
 ########################################################################################################################
 ## Standard configuration ##############################################################################################
 
 @pytest.fixture(scope="session")
-def basic_config(board_shell, wan, lan1):
-    """Basic config we consider general. It provides you with configured WAN and one LAN client.
+def basic_config(client_board, wan):
+    """Basic config we consider general. It provides you with configured WAN.
+
+    Returns handle for ISP container on WAN interface.
     """
-    raise NotImplementedError
+    # TODO what about other settings that are part of guide
+    with nsfarm.lxd.Container('isp-common', devices=[wan, ]) as container:
+        client_board.run("uci set network.wan.proto='static'")
+        client_board.run("uci set network.wan.ipaddr='172.16.1.42'")
+        client_board.run("uci set network.wan.netmask='255.240.0.0'")
+        client_board.run("uci set network.wan.gateway='172.16.1.1'")
+        client_board.run("uci set network.wan.dns='1.1.1.1'")  # TODO configure to ISP
+        client_board.run("uci commit network")
+        client_board.run("/etc/init.d/network restart")
+        client_board.run("while ! ip route | grep -q default; do sleep 1; done")  # Wait for default route
+        # TODO this does not ensure that we ping gateway but why?
+        yield container
+        client_board.run("uci set network.wan.proto='none'")
+        client_board.run("uci delete network.wan.ipaddr")
+        client_board.run("uci delete network.wan.netmask")
+        client_board.run("uci delete network.wan.gateway")
+        client_board.run("uci delete network.wan.dns")
+        client_board.run("uci commit network")
diff --git a/tests/network/common.py b/tests/network/common.py
index 0f7ce8e7dcdb6df006e29f19c5f0114406a3eb71..bca8fae6e1bb80257818146752469a52066c16d5 100644
--- a/tests/network/common.py
+++ b/tests/network/common.py
@@ -17,21 +17,21 @@ class InternetTests:
         "turris.cz",
         "google.com"
     ])
-    def test_ping(self, board_shell, server):
+    def test_ping(self, client_board, server):
         """Ping various IPv4 servers.
 
         We send only one ICMP packet to not flood and to be quickly done with it (the success takes less than second)
         """
-        board_shell.run("ping -c 1 '{}'".format(server))
+        client_board.run("ping -c 1 '{}'".format(server))
 
     @pytest.mark.parametrize("server", [
         "nic.cz",
         "turris.cz",
         "google.com"
     ])
-    def test_dns(self, board_shell, server):
+    def test_dns(self, client_board, server):
         """Try to resolve verious domain names.
         """
-        board_shell.run("nslookup '{}'".format(server))
+        client_board.run("nslookup '{}'".format(server))
 
     # TODO more excessive DNS testing
diff --git a/tests/network/test_wan.py b/tests/network/test_wan.py
index 72c63d6675fd4e7fe77506267ecb7441a5b89dd9..da09fb660fdf2ef97ececa7c6602664a644104a4 100644
--- a/tests/network/test_wan.py
+++ b/tests/network/test_wan.py
@@ -11,11 +11,10 @@ from . import common
 # TODO: add support for IPV6, currently we only test IPv4
 
 
-def _apply(board_shell):
-    board_shell.run("uci commit network")
-    board_shell.run("/etc/init.d/network restart")
-    time.sleep(5)  # TODO drop this as this is just to prevent problems with kernel log in console
-    board_shell.run("while ! ip route | grep -q default; do sleep 1; done")  # Wait for default route
+def _apply(client_board):
+    client_board.run("uci commit network")
+    client_board.run("/etc/init.d/network restart")
+    client_board.run("while ! ip route | grep -q default; do sleep 1; done")  # Wait for default route
 
 
 class TestStatic(common.InternetTests):
@@ -23,24 +22,24 @@ class TestStatic(common.InternetTests):
     """
 
     @pytest.fixture(scope="class", autouse=True)
-    def configure(self, board_shell, wan):
+    def configure(self, client_board, wan):
         """Configure WAN to use static IP
         """
         with nsfarm.lxd.Container('isp-common', devices=[wan, ]) as container:
             # TODO implement some utility class to set and revert uci configs on router
-            board_shell.run("uci set network.wan.proto='static'")
-            board_shell.run("uci set network.wan.ipaddr='172.16.1.42'")
-            board_shell.run("uci set network.wan.netmask='255.240.0.0'")
-            board_shell.run("uci set network.wan.gateway='172.16.1.1'")
-            board_shell.run("uci set network.wan.dns='1.1.1.1'")  # TODO configure to ISP
-            _apply(board_shell)
+            client_board.run("uci set network.wan.proto='static'")
+            client_board.run("uci set network.wan.ipaddr='172.16.1.42'")
+            client_board.run("uci set network.wan.netmask='255.240.0.0'")
+            client_board.run("uci set network.wan.gateway='172.16.1.1'")
+            client_board.run("uci set network.wan.dns='1.1.1.1'")  # TODO configure to ISP
+            _apply(client_board)
             yield container
-            board_shell.run("uci set network.wan.proto='none'")
-            board_shell.run("uci delete network.wan.ipaddr")
-            board_shell.run("uci delete network.wan.netmask")
-            board_shell.run("uci delete network.wan.gateway")
-            board_shell.run("uci delete network.wan.dns")
-            board_shell.run("uci commit network")
+            client_board.run("uci set network.wan.proto='none'")
+            client_board.run("uci delete network.wan.ipaddr")
+            client_board.run("uci delete network.wan.netmask")
+            client_board.run("uci delete network.wan.gateway")
+            client_board.run("uci delete network.wan.dns")
+            client_board.run("uci commit network")
 
 
 class TestDHCP(common.InternetTests):
@@ -48,13 +47,13 @@ class TestDHCP(common.InternetTests):
     """
 
     @pytest.fixture(scope="class", autouse=True)
-    def configure(self, board, board_shell, wan):
+    def configure(self, board, client_board, wan):
         """Configure WAN to use DHCP
         """
         with nsfarm.lxd.Container('isp-dhcp', devices=[wan, ]) as container:
-            board_shell.run("uci set network.wan.proto='dhcp'")
-            board_shell.run("uci commit network")
-            _apply(board_shell)
+            client_board.run("uci set network.wan.proto='dhcp'")
+            client_board.run("uci commit network")
+            _apply(client_board)
             yield container
-            board_shell.run("uci set network.wan.proto='none'")
-            board_shell.run("uci commit network")
+            client_board.run("uci set network.wan.proto='none'")
+            client_board.run("uci commit network")