Why?
I cannot fully explain.
How can I solve this problem?
Usually Linux reaches locally assigned IP addresses internally and it just works. It seems the problem appears when one really needs packets to travel to the outside (e.g. via a cable) and back – like in your case.
You can make it work by using network namespaces. I adjusted this other answer of mine to your needs.
Notes:
- I tested on Debian 10.
- Where the command is
ip … you will probably need sudo ip …. For readability I omit sudo. Work in an elevated shell or (temporarily) define alias ip='sudo ip' to be able to copy-paste conveniently.
- I assume no automation interferes, i.e. there is no daemon that would try to configure the relevant interfaces in its own way.
- To run a command in a non-default network namespace I use
ip netns exec …. It's possible to run a shell this way; then everything you run from the shell will use the network namespace. This answer uses ip netns exec … every time we need to run something in a non-default network namespace.
Proceed like this:
Define useful variables. Here ns1 is an arbitrary name for a namespace; eth1 and eth2 are the devices you want to use.
netns=ns1
dev1=eth1
dev2=eth2
Create a new network namespace.
ip netns add "$netns"
Bring the devices down in the default namespace.
ip link set dev "$dev1" down
ip link set dev "$dev2" down
Add one of the devices to the new namespace (it will disappear from the default namespace). Here I choose to move $dev2 to the new namespace.
ip link set dev "$dev2" netns "$netns"
Assign IP addresses.
ip address add 192.168.1.5/24 dev "$dev1"
ip netns exec "$netns" ip address add 192.168.1.6/24 dev "$dev2"
Confirm the two devices are where they should be, with the right IP addresses.
ip address show
ip netns exec "$netns" ip address show
# examine output
Physically connect the two interfaces with a cable, if not yet done.
Bring the interfaces up. The namespace contains its own loopback device lo. I bring it up just in case, because in general programs may want to rely on it.
ip link set dev "$dev1" up
ip netns exec "$netns" ip link set dev "$dev2" up
ip netns exec "$netns" ip link set dev lo up
Check routes. In my Debian 10 sane routes appear automatically. This command
ip route show
prints (among other lines)
192.168.1.0/24 dev eth1 proto kernel scope link src 192.168.1.5
and this command
ip netns exec "$netns" ip route show
prints
192.168.1.0/24 dev eth2 proto kernel scope link src 192.168.1.6
Ping one way or the other.
ping 192.168.1.6
ip netns exec "$netns" ping 192.168.1.5
You can use -I but it's not necessary. The address 192.168.1.6 is not assigned to any interface in the default network namespace; and 192.168.1.5 is not assigned in the non-default namespace.
And this is it. It should work. My tests indicate these pings really use the cable. I can tell because:
- disconnecting the cable makes them stop flowing; for comparison: "internal" pings (from a wired interface to its own IP address) flow even without a cable;
iptraf-ng monitoring the pinged interface shows ICMP echo requests and ICMP echo replies; for comparison: the tool doesn't show "internal" pings for a wired interface.
Basic cleanup: delete the network namespace.
ip netns del "$netns"
This will move the second device back to the default network namespace.
None of the commands we used implements a permanent change, so in case of any trouble just reboot.