You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The program below is intended to ping 8.8.8.8 over a specific network interface, as a test of whether that interface is up regardless of whether it is the one with the highest-priority default route.
In certain situations, the packets sent by this program go out over the default route, not the named interface. The exact combination required to make this happen is unclear, but we have seen it where the highest-priority default route (ie the one with the numerically lowest priority) is a PPP interface and the program is used to ping over a different interface. This can be seen by running tcpdump on the two interfaces, eg sudo tcpdump -i wlan0 icmp.
package main
import (
"encoding/binary"
"errors"
"time"
"os"
"syscall"
"net"
"fmt"
"flag"
"golang.org/x/net/icmp"
"golang.org/x/net/ipv4"
"github.com/vishvananda/netlink"
)
func valid_ip_address(ping_iface string) (net.IP, error) {
link, err := netlink.LinkByName(ping_iface)
if err != nil {
fmt.Println(err)
return net.ParseIP("0.0.0.0"), err
}
addresses, err := netlink.AddrList(link, syscall.AF_INET)
for _, address := range addresses {
if address.Scope == 253 {
// link-local address
continue
}
if ms0, ms1 := address.Mask.Size(); ms0 == ms1 {
// The address has a netmask implying there is only one host on this
// "network"
continue
}
return address.IP, nil
}
return net.ParseIP("0.0.0.0"), errors.New("No IP4 address found on interface")
}
func main() {
ping_iface := ""
flag.StringVar(&ping_iface, "p", "wlan0", "The interface over which to send ping packets")
flag.Parse()
local_address, err := valid_ip_address(ping_iface)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("Pinging through interface address %s\n", local_address.String())
c, err := icmp.ListenPacket("ip4:icmp", local_address.String())
if err != nil {
fmt.Println(err)
return
}
defer c.Close()
data := make([]byte, 16)
binary.BigEndian.PutUint64(data[0:8], uint64(time.Now().Unix()))
for ii := 8; ii < len(data); ii += 1 {
data[ii] = byte('V')
}
m := icmp.Message {
Type: ipv4.ICMPTypeEcho,
Code: 0,
Body: &icmp.Echo {
ID: os.Getpid() & 0xffff,
Seq: 1,
Data: data,
},
}
message, _ := m.Marshal(nil)
remote := net.IPAddr {
IP: net.ParseIP("8.8.8.8"),
}
fmt.Println(remote)
n, err := c.WriteTo(message, &remote)
if err != nil {
fmt.Println(err)
}
rmessage := make([]byte, 2000)
timeout := time.Now().Add(2 * time.Second)
c.SetReadDeadline(timeout)
n, _, _ = c.ReadFrom(rmessage)
msg, err:= icmp.ParseMessage(1, rmessage[:n])
if err != nil {
fmt.Println(err)
return
}
switch msg.Type {
case ipv4.ICMPTypeEchoReply:
fmt.Println("Received response to ping")
}
}
What did you expect to see?
Expected the packets to go over the interface named on the command line (or wlan0 by default).
What did you see instead?
Packets are routed according to the routing table.
The text was updated successfully, but these errors were encountered:
mikioh
changed the title
x/net net.icmp.ListenPacket doesn't bind socket to interface on Linux
x/net/icmp: dropping packets on IP unnumbered point-to-{,multi)point or non-multiaccess emulated link
Jan 17, 2019
I think this is not an issue to the Go language or its standard/external library. So next time, please use more appropriate forums described in https://github.com/golang/go/wiki/Questions.
You may have options as follows:
use a technique known as "policy-based IP routing"; on Linux, the interface to the implementation is ip{,6}tables or iproute2,
use an operating system-specific link-layer control knob (socket option); on Linux, BINDTODEVICE might be an option, though I'm not sure the option will work correctly in any condition,
use an operating system-specific network-layer control knob (socket option); on Linux, IPv{4,6} ancillary data for the control message,
replace the protocol stack inside the kernel with your own one; in general, many appliances running Linux kernel inject their purpose-specific kernel loadable modules.
For option (2), you may use a combination of net.ListenConfig.ListenPacket and ipv4.NewPacketConn.
For option (3), you may use the approach to option (2) or icmp.PacketConn.IPv{4,6}PacketConn.
For options (1) and (4), you may need to investigate the kernel code more carefully; actually I think that option (2) also requires this because there's no concrete/explicit documentation on the behavior of RIB/FIB what happens when the IP routing/forwarding information bases are tangled up, for example, a link/network-layer adjacency; an output interface is brought down and brought up (or flapping intermittently.)
mikioh
changed the title
x/net/icmp: dropping packets on IP unnumbered point-to-{,multi)point or non-multiaccess emulated link
x/net/icmp: dropping packets on IP unnumbered point-to-{,multi}point or non-multiaccess emulated link
Jan 23, 2019
What version of Go are you using (
go version
)?Also present in 1.10.4
Does this issue reproduce with the latest release?
Yes.
What operating system and processor architecture are you using (
go env
)?Observed both on Ubuntu 18.04 amd64 and Ubuntu 16.04 arm6.
go env
OutputWhat did you do?
The program below is intended to ping
8.8.8.8
over a specific network interface, as a test of whether that interface is up regardless of whether it is the one with the highest-priority default route.In certain situations, the packets sent by this program go out over the default route, not the named interface. The exact combination required to make this happen is unclear, but we have seen it where the highest-priority default route (ie the one with the numerically lowest priority) is a PPP interface and the program is used to ping over a different interface. This can be seen by running tcpdump on the two interfaces, eg
sudo tcpdump -i wlan0 icmp
.What did you expect to see?
Expected the packets to go over the interface named on the command line (or wlan0 by default).
What did you see instead?
Packets are routed according to the routing table.
The text was updated successfully, but these errors were encountered: