-
Notifications
You must be signed in to change notification settings - Fork 340
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Option -a/--address does not work. #250
Comments
After bug submission I found the same bug as #232, sorry for duplicaion. Testcase is quite simple: multihomed host (several interfaces with different addresses), mtr sent packets via default route regardless of -a option. |
Just to confirm that I also came in practice to the same bug
|
Test case. Normal PC, The -I on "ping" hints at using an INTERFACE as the source, but I don't think that can be done with the networking-interface on Unix-like machines. the -a option on mtr explains better what it does: The source address is set. The kernel then often decides to use the interface that you meant to use, but if it doesn't... well mtr can't do much about that. When mtr submits packet FROM your second interface IP address, TO "random IP on the internet", you still expect the routing tables to work and tell that packet where to go. As an example: If you ping-or-mtr a host not on your local network, you expect the kernel to look up how to reach that host and often then use the default route to try to reach that host, right? |
On Thu, Aug 02, 2018 at 11:36:19PM -0700, Roger Wolff wrote:
Test case. Normal PC, ifconfig eth0:1 <a second IP addres>
Now ping -I <second ip adress> a host and see that the second IP address
is being used.
Now mtr -a <second ip address> that host and see that the second IP
address is being used.
The -I on "ping" hints at using an INTERFACE as the source, but I don't
think that can be done with the networking-interface on Unix-like
machines. the -a option on mtr explains better what it does: The source
address is set. The kernel then often decides to use the interface that
you meant to use, but if it doesn't... well mtr can't do much about that.
To set ip-address of source packets application MUST(!) do bind(2) syscall.
For check run "strace -e bind -o mtr.trace mtr -a <src_ip> <dst_ip>" and
look into resulting mtr.trace, you will see that mtr does not call bind().
It's a bug. And it's practice, not abstract theory. Ping works fine.
--
Eugene Berdnikov
|
@rewolff , on the same machine |
I have same issue with mtr package in version 0.92-2 on Debian buster. |
I have simple machines. If any of you can provide me a "howto reproduce" that I can run to reproduce this, then the chances that I can look into it improve dramatically. |
On Wed, Jan 15, 2020 at 09:33:04AM -0800, Roger Wolff wrote:
I have simple machines. If any of you can provide me a "howto reproduce"
that I can run to reproduce this, then the chances that I can look into it
improve dramatically.
What do you mean by "simple machines"? Machines with one (single)
network interface except loopback? You can't reproduce problem with
one interface. The point is: if you have several interfaces to destination
with different addresses, then wrong interface may be chosen.
Manual page told:
-a ADDRESS, --address ADDRESS
Use this option to bind the outgoing socket to ADDRESS, so that
all packets will be sent with ADDRESS as source address. NOTE
that this option doesn't apply to DNS requests (which could be
and could not be what you want).
This is a lie: mtr do not bind outgoing socket to this address. Really,
it does not call bind(2) at all, that can be easily proved with strace.
There no invocation of bind() in the source code!
Mtr uses raw socket and tries to feed kernel with packet having
"-a" value as its source address field in ip header. Strace shows:
9580 socket(AF_INET, SOCK_RAW, IPPROTO_RAW) = 3
9580 setsockopt(3, SOL_IP, IP_HDRINCL, [1], 4) = 0
then something like that:
9580 read(0, "33000 send-probe ip-4 192.168.16.47 local-ip-4 192.168.30.1 protocol icmp size 64 bit-pattern 0 tos 0 ttl 1 timeout 10\n", 4095) = 119
9580 getpid() = 9580
9580 sendto(3, "E\0\0@\0\0\0\0\1\1\0\0\300\250\36\1\300\250\20/\10\0Q\253%l\200\350\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 64, 0, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("192.168.16.47")}, 16) = 64
This logic is defective: kernel DOES NOT scan packet ip-headers in order
to make route lookup. That's why filling source ip field in ip-4 header
is not enouph for correct routing. You must additionally do bind() on socket
to the source address, otherwise kernel peeks wrong interface to send.
Namely, without bind() it peaks interface corresponding to default route.
How to reproduce on Linux: connect 2 interfaces (say, eth0 and eth1) to
some switch, and configure them to one subnet:
ip addr add 192.168.0.2/24 dev eth0
ip rule add pref 2 from 192.168.0.2 lookup 2
ip route add table 2 192.168.0.0/24 dev eth0
sysctl -w net.ipv4.conf.eth0.rp_filter=1
sysctl -w net.ipv4.conf.eth0.arp_filter=1
ip addr add 192.168.0.3/24 dev eth1
ip rule add pref 3 from 192.168.0.3 lookup 3
ip route add table 3 192.168.0.0/24 dev eth1
sysctl -w net.ipv4.conf.eth1.rp_filter=1
sysctl -w net.ipv4.conf.eth1.arp_filter=1
Plug a target host with ip=192.168.0.1 (mask /24) to the same switch.
Check that depending on source ip-address ping sends packets via
right interface and get replies on the same interface:
ping -n -I 192.168.0.2 192.168.0.1 # use eth0
ping -n -I 192.168.0.3 192.168.0.1 # use eth1
It can be watched by interfaces packet counters on host and switch,
or by blinking leds, or by tcpdump, or even by disconnecting cables.
Then run mtr:
mtr -n -a 192.168.0.2 192.168.0.1
mtr -n -a 192.168.0.3 192.168.0.1
You should see that mtr in both cases use one interface.
However, old versions of mtr worked right.
--
Eugene Berdnikov
|
Hi, This issue is still present in latest release 0.93. Neither -I or -a change the source address of a packet. Cheers, |
One way of fixing it. One small problem is, you need to find out the device name first. |
On Thu, Sep 24, 2020 at 11:08:46AM -0700, Tom Hetmer wrote:
A raw socket can be bound to a specific local address using the bind(2)
call. If it isn't bound, all packets with the specified IP protocol are
received. In addition, a RAW socket can be bound to a specific network
device using SO_BINDTODEVICE; see socket(7).
One way of fixing it. One small problem is, you need to find out the
device name first.
It's not a problem but small task to get device name from CLI.
There is already a command line option to get bind address, so 1st variant
"bind to IP addr" is even simpler. It might be good to implement both.
--
Eugene Berdnikov
|
Please check commit totoCZ@19a1fba cc @rewolff i'll do a pull request if it's okay. |
The "HDR_INCL" define has completely vanished. Could it be that this is going to be a problem on some machines that you did not test? |
Linux doesn't require this, but BSD derived network stacks do.
Any idea what those machines are?
Would be weird since it's copied from the IPv6 code and that one doesn't
use IPV6_HDRINCL.
Runs fine on Linux and OS X, anything else I don't have.
Best
Tom Hetmer
…On Fri, Sep 25, 2020 at 11:54 AM Roger Wolff ***@***.***> wrote:
The "HDR_INCL" define has completely vanished. Could it be that this is
going to be a problem on some machines that you did not test?
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#250 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABIR5GUZREMZP2BTVN7XTRTSHRSD5ANCNFSM4EYKLEQA>
.
|
sigh…… still broken in 0.93 |
any updates on this? |
I was able to reproduce it using
on Ubuntu 20.04 |
|
mtr 0.95 on Arch |
The configuration of my environment is as follows: [root@mtr ~]# ip rule show [root@mtr ~]# ip route show [root@mtr ~]# ip route show table net_252 [root@mtr ~]# mtr -r -n -a 99.99.23.6 1.1.1.1 Use tcpdump to capture packets. It is found that packets are not sent from eth1 but from eth0. Do you have any plans to repair it? |
I have the same problem, it looks like no one is going to solve it .... |
My impression was that 7a03200 fixed this issue. Instead of reporting issues about the |
On Mon, Nov 20, 2023 at 04:16:22PM -0800, Matt Kimball wrote:
My impression was that 7a03200 fixed this issue.
My impression is that this patch has relation to "-I" option, while
subject mentions "-a". Binding to source IP address and binding
to interface (SO_BINDTODEVICE) are different things.
… References
Visible links
1. 7a03200
2. #250 (comment)
--
Eugene Berdnikov
|
That fix was committed on 5th August 2022, however the last release of |
Why not cut a release? It's been 2 years since 0.95. (Same problem with 0.95 in current OPNsense) |
|
Based on my tests Edit: MTR 0.95 with commit 74d312d (from #484) additionally applied works for me in the above scenario on Linux (without the workaround to switch from ICMP to TCP). |
Option "-a|--address" does not work in package "mtr-tiny" (build without X11) on Debian Linux, version 0.92-1. Running under strace shows that program does NOT call bind(2).
Breif examination of source code from Github reveals that -a parameter value is assigned to ctl->InterfaceAddress, then is validated in net.c::net_validate_interface_address(), and never used later. Probably some piece of code was lost.
In previous mtr versions option "-a" worked as expected.
The text was updated successfully, but these errors were encountered: