0

I'd like to do some experiments to test the ping and fping commands (see: Equivalent of `ping -o` on Linux), but I need a local virtual Ethernet interface to test this.

I'd like to have a scenario where I can run ping 10.0.0.1 (or any other IP) and have it fail. Then, while ping is still running, I run some commands that bring up the interface and have it pass. In other words, the output of ping will change while it is running, as the virtual device comes "alive". I don't want to have to use physical hardware.

How can I do this?

I've already tried following my own instructions here (How can I create a virtual ethernet interface on a machine without a physical adapter?), but unfortunately even after running sudo ip link set eth10 down, pinging eth10 via ping 10.0.0.1 still succeeds. After running sudo ip link delete eth10 type dummy to delete the dummy virtual device, ping 10.0.0.1 also still succeeds.


Summary of functional answers so far:

(as of 22 Nov. 2021)

3 answers received (my own included), and all 3 answers work!:

  1. by Stephen Harris - use loopback sub-interfaces (probably the best answer so far)
  2. by Hauke Laging - use iptables
  3. my own answer - use virtual interfaces
  • 1
    Why don't you just use the firewall (iptables / nft) for sometimes allowing packets to reach their target and sometimes not? If this is only about ping and fping then that seems to be a lot easier than using virtual interfaces. Independent of that: There may be a different 10.0.0.1 somewhere. Compare the outputs of ip route get 10.0.0.1 in both cases. – Hauke Laging Nov 18 '21 at 21:32
  • @HaukeLaging, thanks! I'd like to use iptables but don't yet know how. Can you provide an example command to block and unblock ping from reaching a given IP address? – Gabriel Staples Nov 18 '21 at 22:49

3 Answers3

2

On Linux you could do this with sub-interfaces on lo (loopback).

eg in one window I run

% ping 10.200.200.1
PING 10.200.200.1 (10.200.200.1) 56(84) bytes of data.

And I get no response, 'cos I don't have anything with that address.

In another window

% sudo ifconfig lo:100 10.200.200.1 netmask 255.255.255.0 up

And now the ping starts to responde

64 bytes from 10.200.200.1: icmp_seq=25 ttl=64 time=0.058 ms
64 bytes from 10.200.200.1: icmp_seq=26 ttl=64 time=0.035 ms
64 bytes from 10.200.200.1: icmp_seq=27 ttl=64 time=0.037 ms
64 bytes from 10.200.200.1: icmp_seq=28 ttl=64 time=0.040 ms

I can then do

% sudo ifconfig lo:100 down

and the ping stops working again.

Essentially all we're doing as adding a "sub-interface" to the loopback interface. In this case I call it lo:100 but you can pick lo:1 -> lo:255.

Sub-interfaces are really just a way of assigning 2 or more addresses to the same interface. For example if you assigned an address to eth0:1 then your machine would have 2 address on the physical interface and other machines on your network could reach it on both. Putting them on lo (loopback) means that only your test machine knows about the extra address and the rest of your network isn't impacted.

At a packet level any traffic for lo:100 flows through lo. This is different to dummy interfaces where a whole new interface is created and traffic is isolated.

  • Woah, that's pretty awesome! Upvoted. Best answer so far in my opinion, and every answer so far here works just fine. Can you update the answer to explain in detail exactly what's happening with these calls and in the computer with these commands and options? I'd like to understand both the commands and the actual communication path. – Gabriel Staples Nov 19 '21 at 06:32
  • 1
    Brief description of sub-interfaces added. – Stephen Harris Nov 19 '21 at 12:13
1

if you have added 10.0.0.1 to one of your interfaces then you can throw away ping packets to that address with

iptables -I OUTPUT 1 -p icmp --icmp-type echo-request -d 10.0.0.1 -j DROP

You can delete this rule with

iptables -D OUTPUT -p icmp --icmp-type echo-request -d 10.0.0.1 -j DROP

By executing these two commands alternatingly you can switch between the two states.

Here is some sample ping 10.0.0.1 output showing the packets going through, then getting blocked, then going through again:

$ ping 10.0.0.1
PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
64 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=5.04 ms
64 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=4.20 ms
64 bytes from 10.0.0.1: icmp_seq=3 ttl=64 time=3.33 ms
ping: sendmsg: Operation not permitted
ping: sendmsg: Operation not permitted
ping: sendmsg: Operation not permitted
ping: sendmsg: Operation not permitted
64 bytes from 10.0.0.1: icmp_seq=8 ttl=64 time=8.49 ms
64 bytes from 10.0.0.1: icmp_seq=9 ttl=64 time=3.33 ms
64 bytes from 10.0.0.1: icmp_seq=10 ttl=64 time=6.90 ms
64 bytes from 10.0.0.1: icmp_seq=11 ttl=64 time=6.91 ms
^C
--- 10.0.0.1 ping statistics ---
11 packets transmitted, 7 received, 36% packet loss, time 10088ms
rtt min/avg/max/mdev = 3.330/5.459/8.491/1.859 ms
Hauke Laging
  • 90,279
  • I had to use sudo for both commands. The error I got was: iptables v1.6.1: can't initialize iptables table \filter`: Permission denied (you must be root) Perhaps iptables or your kernel needs to be upgraded.` – Gabriel Staples Nov 18 '21 at 23:16
0

@Hauke Laging is right in his comment under my question:

There may be a different 10.0.0.1 somewhere. Compare the outputs of ip route get 10.0.0.1 in both cases.

ip route get 10.0.0.1 shows this before deleting the dummy interface:

local 10.0.0.1 dev lo src 10.0.0.1 uid 46153590

...indicating that that route is going through the dummy interface I created, and it shows this after deleting the dummy interface by running sudo ip link delete eth10 type dummy:

10.0.0.1 dev wlp0s20f3 src 10.0.0.36 uid 28301632

...indicating that IP is now being routed through my wlp0s20f3 wireless card. I guess that makes sense because my local WiFi is using and assigning 10.0.0.x IP addresses.

The solution, therefore, is to simply choose a different IP which is not pingable before creating the virtual interface to it! Using 10.0.0.100 instead of 10.0.0.1 in my case worked just fine. But, let's just use 254.254.254.254 for the case of this example.

Full Example:

First, ensure the desired IP address you'd like to use is NOT currently responding to ping:

ping -c 1 -W 1 254.254.254.254

Sample output:

PING 254.254.254.254 (254.254.254.254) 56(84) bytes of data.

--- 254.254.254.254 ping statistics --- 1 packets transmitted, 0 received, 100% packet loss, time 0ms

Now create a dummy eth99 interface (for a full explanation, see my other answer here: How can I create a virtual ethernet interface on a machine without a physical adapter?):

sudo modprobe dummy \
&& sudo ip link add eth99 type dummy \
&& sudo ip address change dev eth10 254.254.254.254 \
&& ip address

Now it IS pingable. Run ping 254.254.254.254. Sample cmd and output:

$ ping 254.254.254.254
PING 254.254.254.254 (254.254.254.254) 56(84) bytes of data.
64 bytes from 254.254.254.254: icmp_seq=1 ttl=64 time=0.086 ms
64 bytes from 254.254.254.254: icmp_seq=2 ttl=64 time=0.093 ms
64 bytes from 254.254.254.254: icmp_seq=3 ttl=64 time=0.086 ms
64 bytes from 254.254.254.254: icmp_seq=4 ttl=64 time=0.051 ms
^C
--- 254.254.254.254 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3050ms
rtt min/avg/max/mdev = 0.051/0.079/0.093/0.016 ms

Now, if you run ping 254.254.254.254 in one terminal, and sudo ip link delete eth99 type dummy in another, the ping response will quit incrementing once you delete the interface. sudo modprobe dummy; sudo ip link add eth99 type dummy; sudo ip address change dev eth99 254.254.254.254; ip address again will re-create the interface and make the ping start responding again.