turbulent / substance

Local Docker-powered development environments
Apache License 2.0
18 stars 8 forks source link

fix: arp poisoning bug and Virtual Box 6.1 support #55

Closed bbeausej closed 4 years ago

bbeausej commented 4 years ago

This MR fixes an issue with substance <= 1.1.4 where the DHCP servers and Host Only Interfaces were set with the same IP address. This was discovered to cause a problem on the guest because the Virtual Box engine actually gives both of those subsystems a different virtual MAC.

So the symptom on the guest is intermittent ARP poisoning, leading to double responses to an arping from the guest to the host only interface ip address.

(Ref: https://forums.virtualbox.org/viewtopic.php?f=7&t=58761)

At the same time, this MR allows compability with Virtual Box 6.1 (the output of VBoxManage dhcp servers changed). The change is backwards compatible to vbox <=6.

Should address #54

CLARENNE-Q commented 4 years ago

Hi Ben,

I made the update to VirtualBox 6.1:

turbulent@Quentin-MacBook-Pro my-website % vboxmanage --version
6.1.2r135662

I update /usr/local/lib/python3.7/site-packages/substance:

turbulent@Quentin-MacBook-Pro my-website % substance launch    
Provisioning engine "work" with driver "virtualbox"
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/substance/command/command.py", line 241, in main
    self.runCommand(self.cmdString)
  File "/usr/local/lib/python3.7/site-packages/substance/command/command.py", line 250, in runCommand
    self.command.execute(self.commandInput)
  File "/usr/local/lib/python3.7/site-packages/substance/command/command.py", line 94, in execute
    return self.main()
  File "/usr/local/lib/python3.7/site-packages/substance/command/launch.py", line 29, in main
    .bind(Engine.launch) \
  File "/usr/local/lib/python3.7/site-packages/substance/monads.py", line 167, in bind
    return mf(self.getOK(), *args, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/substance/engine.py", line 346, in launch
    .then(self.start) \
  File "/usr/local/lib/python3.7/site-packages/substance/monads.py", line 207, in then
    r = okF()
  File "/usr/local/lib/python3.7/site-packages/substance/engine.py", line 390, in start
    return self.__configure() \
  File "/usr/local/lib/python3.7/site-packages/substance/engine.py", line 507, in __configure
    return self.getDriver().configureMachine(self.getDriverID(), self)
  File "/usr/local/lib/python3.7/site-packages/substance/driver/virtualbox/__init__.py", line 194, in configureMachine
    return self.assertSetup() \
  File "/usr/local/lib/python3.7/site-packages/substance/driver/virtualbox/__init__.py", line 33, in assertSetup
    return self.assertConfig().then(self.assertNetworking)
  File "/usr/local/lib/python3.7/site-packages/substance/monads.py", line 207, in then
    r = okF()
  File "/usr/local/lib/python3.7/site-packages/substance/driver/virtualbox/__init__.py", line 79, in assertNetworking
    dhcp = network.readDHCP(interface) \
  File "/usr/local/lib/python3.7/site-packages/substance/driver/virtualbox/network.py", line 113, in readDHCP
    return readDHCPs() >> defer(filterDHCPs, interface=interface)
  File "/usr/local/lib/python3.7/site-packages/substance/driver/virtualbox/network.py", line 109, in readDHCPs
    .bind(defer(_mapAsBlocks, func=parseDHCPBlock))
  File "/usr/local/lib/python3.7/site-packages/substance/monads.py", line 167, in bind
    return mf(self.getOK(), *args, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/substance/driver/virtualbox/network.py", line 312, in _mapAsBlocks
    return OK(blocks).mapM(func)
  File "/usr/local/lib/python3.7/site-packages/substance/monads.py", line 240, in mapM
    return self.bind(mapper)
  File "/usr/local/lib/python3.7/site-packages/substance/monads.py", line 167, in bind
    return mf(self.getOK(), *args, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/substance/monads.py", line 239, in mapper
    return mapM(self, mf, xs)
  File "/usr/local/lib/python3.7/site-packages/substance/monads.py", line 343, in mapM
    mapped = list(map(mf, xs))
  File "/usr/local/lib/python3.7/site-packages/substance/driver/virtualbox/network.py", line 168, in parseDHCPBlock
    return _extractClassFromBlock(block, actions, DHCP)
  File "/usr/local/lib/python3.7/site-packages/substance/driver/virtualbox/network.py", line 334, in _extractClassFromBlock
    return OK(cls(**info))
TypeError: __init__() got an unexpected keyword argument 'dhcpIP'

Error running command launch: __init__() got an unexpected keyword argument 'dhcpIP'

Looks links to:

class DHCP(object):
    def __init__(self, interface, networkName, gateway, netmask, lowerIP, upperIP, enabled):
        self.interface = interface
        self.networkName = networkName
        self.gateway = gateway
        self.netmask = netmask
        self.lowerIP = lowerIP
        self.upperIP = upperIP
        self.enabled = True if enabled is True or enabled == "Yes" else False

        self.network = IPNetwork(gateway + "/" + netmask)

You need to update for this:

class DHCP(object):
    def __init__(self, interface, networkName, dhcpIP, netmask, lowerIP, upperIP, enabled):
        self.interface = interface
        self.networkName = networkName
        self.dhcpIP = dhcpIP
        self.netmask = netmask
        self.lowerIP = lowerIP
        self.upperIP = upperIP
        self.enabled = True if enabled is True or enabled == "Yes" else False

        self.network = IPNetwork(dhcpIP + "/" + netmask)
CLARENNE-Q commented 4 years ago

TESTS on 1.2.2:

turbulent@Quentin-MBP project-website % substance halt
====> Update to VirtualBox 6.1: https://www.virtualbox.org/wiki/Downloads
turbulent@Quentin-MBP project-website % vboxmanage --version
6.1.2r135662
turbulent@Quentin-MBP project-website % sudo pip3.7 uninstall substance 
turbulent@Quentin-MBP project-website % rm $HOME/.substance/virtualbox.yml
turbulent@Quentin-MBP project-website % sudo pip3.7 install substance

turbulent@Quentin-MBP project-website % substance help
Local docker-based development environments (version: 1.2.2)

turbulent@Quentin-MBP project-website % substance launch
Provisioning engine "work" with driver "virtualbox"
Generating default virtualbox config in /Users/turbulent/.substance/virtualbox.yml
Provisioning VirtualBox networking for substance
Provisioning DHCP service for host only interface
Checking for port conflicts
Determined SSH port as 4500
Configure machine shared folders
Configure machine profile
[work] ==> Updating network info from driver
[work] ==> Waiting for machine to boot...
[work] ==> Waiting for machine network...
[work] ==> Configuring machine hostname
 * WARNING: you are stopping a boot service
 * WARNING: you are stopping a boot service
 * Stopping busybox crond ...                                                                                                [ ok ]
 * Stopping busybox syslog ...                                                                                               [ ok ]
 * Setting hostname ...                                                                                                      [ ok ]
[work] ==> Mounting engine folders
[work] ==> Updating network info from driver
[work] ==> Registering engine as 'work.dev' in local hosts file
Hosts register work.dev: 172.21.21.11
'work.dev' found in local hosts file.
Engine "work" has been launched.
[work] ==> Starting all containers...
'dbmaster' has been started.
'cache' has been started.
'sessions' has been started.
'redis' has been started.
'qmgr' has been started.
'web' has been started.
'cron' has been started.
'logrotate' has been started.
'elasticsearch' has been started.

Look good for VirtualBox6.1 😃

turbulent@Quentin-MBP project-website % substance ssh
substance@work:~$ sudo arping 172.21.21.1
ARPING 172.21.21.1
42 bytes from 0a:00:27:00:00:00 (172.21.21.1): index=0 time=176.743 usec
42 bytes from 0a:00:27:00:00:00 (172.21.21.1): index=1 time=188.794 usec
42 bytes from 0a:00:27:00:00:00 (172.21.21.1): index=2 time=782.927 usec
42 bytes from 0a:00:27:00:00:00 (172.21.21.1): index=3 time=188.846 usec
42 bytes from 0a:00:27:00:00:00 (172.21.21.1): index=4 time=158.532 usec
42 bytes from 0a:00:27:00:00:00 (172.21.21.1): index=5 time=153.060 usec
42 bytes from 0a:00:27:00:00:00 (172.21.21.1): index=6 time=426.684 usec
42 bytes from 0a:00:27:00:00:00 (172.21.21.1): index=7 time=167.983 usec
42 bytes from 0a:00:27:00:00:00 (172.21.21.1): index=8 time=184.630 usec
42 bytes from 0a:00:27:00:00:00 (172.21.21.1): index=9 time=165.392 usec
42 bytes from 0a:00:27:00:00:00 (172.21.21.1): index=10 time=210.789 usec
42 bytes from 0a:00:27:00:00:00 (172.21.21.1): index=11 time=144.332 usec
42 bytes from 0a:00:27:00:00:00 (172.21.21.1): index=12 time=1.050 msec

Perfect for ARP poisoning ! 👍👍👍👍👍

But the IP is not show in 'substance status:'

turbulent@Quentin-MBP project-website % substance status 
ENGINE    SUBENV
work      projet-website

NAME           CONTAINER                  PID  IP          UPTIME          EXIT
dbmaster       6ee8bf15a741              3001  -           5 minutes ago   -
cache          26c3d33f0973              3106  -           5 minutes ago   -
sessions       47037db314de              3241  -           5 minutes ago   -
redis          2e1cb2ebf4ce              3351  -           5 minutes ago   -
qmgr           6cdfc2d2be19              3460  -           5 minutes ago   -
web            5a2654a8381d              3589  -           5 minutes ago   -
cron           67a4ceac8d2c              3691  -           5 minutes ago   -
logrotate      ac986484ee45              3813  -           5 minutes ago   -
elasticsearch  9b6e75b6d099              3950  -           5 minutes ago   -
bbeausej commented 4 years ago

Interesting! Can you file a new issue for the IP issue? It's fairly benign (since you never really use the IP) but might be good to fix in the future.