Fail to bind to specific network interface on Linux - linux

=== Background stuff ===
I have two wired ethernet interface on my Debian 9 server, both of them have internet access but through different ISP.
enp11s0 192.168.0.9
eth0 192.168.2.2
iptables -L and iptables -L -t nat is empty and accepts all incoming and outgoing. Here is my route:
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
default 192.168.0.1 0.0.0.0 UG 0 0 0 enp11s0
116.xxx.xxx.0 192.168.2.1 255.255.255.0 UG 0 0 0 eth0
192.168.0.0 0.0.0.0 255.255.255.0 U 0 0 0 enp11s0
192.168.2.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
=== End of Background ===
I would like to let most traffic go through enp11s0 since the eth0 is metered, but few connection go through eth0 (e.g. 116.xxx.xxx.xxx). This works, but when I try to let a program bind to a specific interface, it becomes weird.
curl icanhazip.com --interface enp11s0 gives my ip address which is expected, however curl icanhazip.com --interface eth0 does not work. With -v flag here is the output:
* Rebuilt URL to: icanhazip.com/
* Trying 144.202.71.30...
* TCP_NODELAY set
* Local Interface eth0 is ip 192.168.2.2 using address family 2
* Local port: 0
* Trying 2001:19f0:6401:18fc:2709:e14e:21cd:4e41...
* TCP_NODELAY set
* Trying 2001:19f0:5c01:1aed:dcdf:7e47:e74b:1197...
* TCP_NODELAY set
And it just keeps repeating forever. I added -4 flag and Trying 2001:19f0:6401:18fc:2709:e14e:21cd:4e41 disappears, but it still doesn't work. How do I fix eth0? Thanks in advance!

see this question and answer here for a good explanation about how what you are attempting with curl is not what is happenning with curl.
You are curling an external address from eth0 via the server default gateway which is on the link enp11s0 . check that forwarding is enabled on the server.
You need to set up policy based routing. depending on what traffic you wan't to send out eth0, look into iproute2, ip rule, and
/etc/iproute2/rt_tables

Related

Network unreachable when address is IPv6 in Buildroot

I created a custom Buildroot 2015.01 distribution w/ 3.10.0 Linux Kernel with enabled IPv6 support in the Toolchain and the uClibc library.
There is a strange behaviour that takes place when trying to contact any IPv6 routed address, for example:
# wget google.com
Connecting to google.com ([2a00:1450:4002:809::200e]:80)
wget: can't connect to remote host: Network is unreachable
But, if I try the same thing on a non-IPv6 address, everything works correctly:
# wget abc.com
Connecting to abc.com (199.181.132.250:80)
Connecting to abc.go.com (23.21.209.55:80)
index.html 100% |*******************************| 46408 0:00:00 ETA
This is the IPv6 kernel routing table:
# route -A inet6
Destination Next Hop Flags Metric Ref Use Iface
::1/128 :: U 0 0 1 lo
fe80::20a:a5ff:fe12:3446/128 :: U 0 0 1 lo
fe80::/64 :: U 256 0 0 eth0
ff02::1:ffdc:adf/128 :: UC 0 1 0 eth0
ff02::1:fff4:5e3d/128 :: UC 0 1 0 eth0
ff00::/8 :: U 256 0 0 eth0
IPv4 one:
# route -A inet
Destination Gateway Genmask Flags Metric Ref Use Iface
default 192.168.0.230 0.0.0.0 UG 0 0 0 eth0
192.168.0.0 * 255.255.255.0 U 0 0 0 eth0
Any help or suggestion would be very appreciated.
I solved the issue by installing standard wget instead of the Busybox's integrated one.
As it seems our internal network was not IPv6 capable and Busybox's wget stopped when it couldn't reach the destination. Standard wget, instead, falls back to the IPv4 address, completing the download.
EDIT: apart from our network, seems Busybox's wget has some issues

how to route 2 Nics with 2 public IP on same subnet running with same gateway

I'm newbie in networking field. I have trouble with my web server Network configuration (OS is Centos).
I have 2 NICs (eth0 + eth2 - physically) running 2 public IP which have the same subnet, same gateway.
When I configure nginx to listen on these 2 NICs, everything works just fine. But when I monitor the traffic, all traffic is on the eth0 only, nothing on eth2.
My question is: How can I configure so that traffic goes in a NIC, go out on that NIC, too?
This is my ethernet card config:
DEVICE="eth0"
ONBOOT=yes
BOOTPROTO=static
IPADDR=x.x.x.38
PREFIX=27
GATEWAY=x.x.x.x.33
DNS1=8.8.8.8
DNS2=8.8.4.4
NAME="System eth0"
DEVICE="eth2"
ONBOOT=yes
BOOTPROTO=static
IPADDR=x.x.x.39
PREFIX=27
GATEWAY=x.x.x.33
DNS1=8.8.8.8
DNS2=8.8.4.4
NAME="System eth2"
This is my route -n result
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
10.14.8.0 0.0.0.0 255.255.255.0 U 0 0 0 eth1
y.z.0.0 0.0.0.0 255.255.0.0 U 1002 0 0 eth0
y.z.0.0 0.0.0.0 255.255.0.0 U 1003 0 0 eth1
y.z.0.0 0.0.0.0 255.255.0.0 U 1004 0 0 eth2
0.0.0.0 x.x.x.33 0.0.0.0 UG 0 0 0 eth0
Hope you can help, thanks in advanced!
In Linux, routing is performed by looking at the destination address only, so a packet will follow whichever route can be used to reach the packet's destination, with no regard to the source address.
The behaviour you want requires choosing a route depending not only on the destination address, but also on the source address — this is sometimes called source-sensitive routing or SADR (source-address dependent routing). The most portable way of implementing source-sensitive routing under Linux is to define routing rules across multiple routing tables using the ip rule and ip route ... table ... commands.
This is described in detail in Section 4 of the Linux Advanced Routing and Traffic Control HOWTO
Probably, the problem can be solved even with NAT.
ip tuntap add dev tap0 mode tap
ip tuntap add dev tap1 mode tap
Then you can assign separate ip addresses to these devices:
ifconfig tap0 10.10.10.1 netmask 255.255.255.255
ifconfig tap1 10.10.10.2 netmask 255.255.255.255
And finally - redirect incoming traffic to specific virtual device
iptables -t nat -A PREROUTING -i eth0 -j DNAT --to-destination 10.10.10.1
iptables -t nat -A PREROUTING -i eth2 -j DNAT --to-destination 10.10.10.2
In this case, all traffic will be routed definetely to the interface it came from.

Linux : I programatically changed my default route to eth0 but now I can't ping, any suggestions?

I'm writing a program for my embedded Debian Linux system. It has a cell modem that is brought up as ppp0 and also has eth0 that may or may not be plugged in. How I want the system to work is for it to use ppp0 as the default route, unless it can establish a connection to the outside world over eth0, in that case eth0 should be made the default route. The eth0 cable could be unplugged at any time. To do this I've written a C++ program that uses curl to try and establish a connection to a public web server over eth0. If successful it then tries to go and make the default route eth0. I've borrowed some code from the Linux pppd project to manipulate the routing information. The system boots up with ppp0 active. I then run my program, and it detects it can make a connection via eth0 (as the cable is plugged in), and it then changes the default route to eth0. After that networking somehow stops working, I can no longer ping and public servers. Somehow my changing the route has killed networking. Before I run my program, the output of "route" is:
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
80.sub-66-174-2 * 255.255.255.255 UH 0 0 0 ppp0
192.168.98.0 * 255.255.255.0 U 0 0 0 eth0
loopback * 255.0.0.0 U 0 0 0 lo
default * 0.0.0.0 U 0 0 0 ppp0
After I run my program, the output of "route" is:
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
66.174.217.80 * 255.255.255.255 UH 0 0 0 ppp0
192.168.98.0 * 255.255.255.0 U 0 0 0 eth0
loopback * 255.0.0.0 U 0 0 0 lo
default * 0.0.0.0 U 0 0 0 eth0
So I can't see any obvious signs of what's wrong. The code is posted at http://pastebin.com/AwKdvSf1
Thanks for any help or insights on how to fix this.
your default gateway ip address is not defined.
type route add default gw <gateway ip> as root (or sudo)
NOTE: using dhcp to assign ip settings would be best way I think to solve your problem otherwise you'll have to define the default route statically.
You'll have to add DEFROUTE=no in your ppp0 configuration.

connman: Auto-Connecting to multiple Ethernet interfaces at a time

Quite easy use-case: I have two Ethernet interfaces which should both be connected using DHCP. It does not matter which one the default route is, since it is just a dedicated proof-of-concept setup. However, hot-plugging must work for both interfaces (one of them is a CDC-NCM connection).
connman 1.17 seems only to try to establish a connection to one of the interfaces. If I unplug this connection, DHCP is started on the second interface and everything continues to work. I can connect the second interface always by using “connmanctl connect” manually. But…
… is there any way to configure connman to connect AUTOMATICALLY to both networks via DHCP?
is there any way to configure connman to connect AUTOMATICALLY to both networks via DHCP?
By default most DHCP servers are configured to issue a default route to the client. If you get two default routes, it's impossible for the linux networking stack to function properly.
Since you would want DHCP clients on both networks to be able to function properly, perhaps the best thing you can do is scan the system routing table and remove one of the default routes.
Typically you'd use netstat -rn to find the duplicate default...
[mpenning#tsunami micro]$ netstat -rn
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
172.16.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
172.16.2.0 0.0.0.0 255.255.255.0 U 0 0 0 eth1
239.0.0.0 0.0.0.0 255.0.0.0 U 0 0 0 eth0
0.0.0.0 172.16.1.1 0.0.0.0 UG 0 0 0 eth0 <--
0.0.0.0 172.16.2.1 0.0.0.0 UG 0 0 0 eth1 <--
[mpenning#tsunami micro]$
Then remove one of them...
[mpenning#tsunami micro]$ sudo route del default dev eth1
[mpenning#tsunami micro]$ netstat -rn
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
172.16.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
172.16.2.0 0.0.0.0 255.255.255.0 U 0 0 0 eth1
239.0.0.0 0.0.0.0 255.0.0.0 U 0 0 0 eth0
0.0.0.0 172.16.1.1 0.0.0.0 UG 0 0 0 eth0
[mpenning#tsunami micro]$
It's not so hard to write a shell script to check for this issue. However, a better solution is just to get a static address on one of the networks so you don't have to manage around the DHCP issue.

How do I route a packet to use localhost as a gateway?

I'm trying to test a gateway I wrote(see What's the easiest way to test a gateway? for context). Due to an issue I'd rather not get into, the gateway and "sender" have to be on the same machine. I have a receiver(let's say 9.9.9.9) which the gateway is able to reach.
So I'll run an application ./sendStuff 9.9.9.9 which will send some packets to that IP address.
The problem is: how do I get the packets destined for 9.9.9.9 to go to the gateway on localhost? I've tried:
sudo route add -host 9.9.9.9 gw 127.0.0.1 lo
sudo route add -host 9.9.9.9 gw <machine's external IP address> eth0
but neither of those pass packets through the gateway. I've verified that the correct IPs are present in sudo route. What can I do?
Per request, here is the route table, after running the second command(IP addresses changed to match the question. x.y.z.t is the IP of the machine I'm running this on):
Destination Gateway Genmask Flags Metric Ref Use Iface
9.9.9.9 x.y.z.t 255.255.255.255 UGH 0 0 0 eth0
x.y.z.0 0.0.0.0 255.255.254.0 U 0 0 0 eth0
0.0.0.0 <gateway addr> 0.0.0.0 UG 100 0 0 eth0
127.0.0.1 is probably picking up the packets, then forwarding them on their merry way if ipv4 packet forwarding is enabled. If it's not enabled, it will drop them.
If you are trying to forward packets destined to 9.9.9.9 to 127.0.0.1, look into iptables.
Edit: try this:
iptables -t nat -A OUTPUT -d 9.9.9.9 -j DNAT --to-destination 127.0.0.1
That should redirect all traffic to 9.9.9.9 to localhost instead.

Resources