zmap/zgrab2

HTTP module and --source-ip= not working on multi-homed system

mzpqnxow opened this issue · 2 comments

I have a system with two WAN links. I noticed that --source-ip= does not have any effect in this configuration. I confirmed this using the http module by looking at the traffic leaving the respective interfaces (they're separate physical NICs, not aliased)

I have not yet looked at the cause of this but will give it a shot when I have time. If anyone else can take a look that'd be swell :)

Thanks

Source IP does not work at all and should be removed due to limitations with Go. If you need this behavior, use Linux network namespaces instead.

Source IP does not work at all and should be removed due to limitations with Go. If you need this behavior, use Linux network namespaces instead.

Thanks for this, I hadn't thought of it but it's quite a nice solution and (as I'm sure you know) can be done in a very lightweight manner without any dependencies, using only ip netns and network namespaces (no need for "container" solutions, nor filesystem namespaces, user/process namespaces, etc.)

For the benefit of others who may need to do this, here's the idiot's guide to doing it quickly in the form of a script

The caveat (if it isn't obvious) is that the interface will no longer be available in the primary namespace- so don't do it on your management/primary NIC by accident...

#!/bin/bash
set -euo pipefail
declare -r IFACE=eth0
declare -r NS=zg_ns
declare -r IP=1.2.3.4/20
declare -r GW=1.2.3.1
declare -r SUDO=sudo
declare -r SCAN_USER=user
# Create new network namespace (delete if already exists)
$SUDO ip netns del $NS &>/dev/null || true
$SUDO ip netns add $NS
# "move" the interface from the primary namespace into the new namespace
$SUDO ip link set $IFACE netns $NS
# Configure the interface as usual ...
$SUDO ip netns exec $NS ip addr add $IP dev $IFACE
$SUDO ip netns exec $NS ip link set $IFACE up
$SUDO ip netns exec $NS ip route add default via $GW dev $IFACE
# Enter the namespace and test networking (or run zgrab2, or an interactive shell)
echo Testing WAN connectivity inside $NS ...
$SUDO ip netns exec $NS sudo -u $SCAN_USER ping -c 3 8.8.8.8
# $SUDO ip netns exec $NS sudo -u $SCAN_USER -i
read -p "Press enter to destroy the namespace, control-C to leave it.."
$SUDO ip netns del $NS
read -p "Press enter to restart primary namespace networking, control-C to leave it.."
$SUDO systemctl restart networking

At that point you can use any network-aware application and the traffic will route properly through the assigned interface, regardless of what the primary namespace routing tables say

To save a bit of hassle, I found a simple script that migrates the address and route table info to the namespace based on the configuration it had before being assigned. It can be found here

Thanks again for the idea, it seems painfully obvious now, but I hadn't even considered it. I was thinking about clumsier and more invasive things, like using multiple routing tables and routing policies, iptables PID/owner rules, etc. The management of that solution "costs" more in several ways which makes this an easy choice

It's ridiculous that golang doesn't have a clean public interface for this. That said, this is probably a better solution anyway...

EDIT: I do have this hacky patch which does what I want on Linux, but it's probably not what most users are looking for when using the --source-ip feature. It requires that the interface specified has a route to the target- so on a multi-homed (dual-WAN) system, both interfaces need to have a path in the routing table to the target