MacOS – Cannot ping devices from mac unless they ping the mac first

macosNetwork

My network looks like this and I have all sorts of devices: android phones, tablets, raspberry pis, some of which my Mac can’t ping over WiFi.

network diagram

Other devices on the network can ping the target just fine. In one case, I could even use ssh -L 2222:target:22 other-device -N; ssh localhost -p 2222 ping mac, and was then able to ssh to the target from the mac directly.

Targets do not respond to any connections from the mac (ping, ssh, http). Not a sleeping NIC problem on the targets because other devices can communicate with the targets just fine (on all the same protocols).

Mac is plugged in to ethernet, targets are wirelessly connected to the same network (no guest mode, vlan, etc., but there might be other options I haven't considered). However other-device in the instance above is also hardwired.

Edited to add network information:

  • targets are connected to a wireless AP which is connected to the main switch.
  • mac is connected to a switch which is connected to the main switch.
  • otherhost is connected to the main switch
  • main switch is the only LAN device connected to the router (the other device is the WAN cable modem)

Edited to add more information:

Ping from mac:

ping target
PING target.domain (192.168.1.126): 56 data bytes
Request timeout for icmp_seq 0
Request timeout for icmp_seq 1
ping: sendto: No route to host
Request timeout for icmp_seq 2
ping: sendto: Host is down
Request timeout for icmp_seq 3
ping: sendto: Host is down
Request timeout for icmp_seq 4
ping: sendto: Host is down
Request timeout for icmp_seq 5
ping: sendto: Host is down
Request timeout for icmp_seq 6
^C
--- target.domain ping statistics ---
8 packets transmitted, 0 packets received, 100.0% packet loss

Ping from otherhost:

ssh otherhost
ping target
PING target.domain (192.168.1.126) 56(84) bytes of data.
64 bytes from target.domain (192.168.1.126): icmp_seq=1 ttl=64 time=46.1 ms
64 bytes from target.domain (192.168.1.126): icmp_seq=2 ttl=64 time=70.2 ms
64 bytes from target.domain (192.168.1.126): icmp_seq=3 ttl=64 time=95.8 ms
64 bytes from target.domain (192.168.1.126): icmp_seq=4 ttl=64 time=118 ms
64 bytes from target.domain (192.168.1.126): icmp_seq=5 ttl=64 time=38.6 ms
^C
--- target.domain ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 6ms
rtt min/avg/max/mdev = 38.572/73.770/118.162/29.918 ms

netstat on mac: (thanks @slm)

netstat -rn -f inet
Routing tables

Internet:
Destination        Gateway            Flags        Refs      Use   Netif Expire
default            192.168.1.1        UGSc          222        0     en0
127                127.0.0.1          UCS             0        0     lo0
127.0.0.1          127.0.0.1          UH             20     1512     lo0
169.254            link#5             UCS             0        0     en0      !
192.168.1          link#5             UCS            14        0     en0      !
192.168.1.1/32     link#5             UCS             1        0     en0      !
192.168.1.1        78:8a:20:xx:xx:xx  UHLWIir       167      954     en0   1183
192.168.1.7        0:1e:6:xx:xx:xx    UHLWIi          1       43     en0   1149
192.168.1.59/32    link#5             UCS             0        0     en0      !
...
192.168.1.126      link#5             UHLWI           0       13     en0      !
...
192.168.1.186      9c:8e:cd:xx:xx:xx  UHLWI           0        0     en0   1180
...
192.168.1.255      ff:ff:ff:ff:ff:ff  UHLWbI          0       15     en0      !
224.0.0/4          link#5             UmCS            1        0     en0      !
224.0.0.251        1:0:5e:0:0:fb      UHmLWI          0        0     en0
255.255.255.255/32 link#5             UCS             1        0     en0      !
255.255.255.255    ff:ff:ff:ff:ff:ff  UHLWbI          0        7     en0      !

It looks like something is weird in the routing table. For otherhost (.7), there is a MAC address and expiry time, but for target there is only link#5 and an ! in expiry. (The flags also differ a bit, but there are other entries with the same flags that do include a MAC address and expiry, so I'm not sure that's relevant.)

traceroute from mac:

traceroute target
traceroute to target.domain (192.168.1.126), 64 hops max, 52 byte packets
 1  * *traceroute: sendto: No route to host
traceroute: wrote target.domain 52 chars, ret=-1
 *
traceroute: sendto: Host is down
 2 traceroute: wrote target.domain 52 chars, ret=-1
 *traceroute: sendto: Host is down
traceroute: wrote target.domain 52 chars, ret=-1
 *traceroute: sendto: Host is down
traceroute: wrote target.domain 52 chars, ret=-1

tracepath from otherhost (wired, but linux):

tracepath target
 1?: [LOCALHOST]                      pmtu 1500
 1:  target.domain                                         5.742ms reached
 1:  target.domain                                         3.304ms reached
     Resume: pmtu 1500 hops 1 back 1

netstat after pinging mac from target:

...
192.168.1.126      64:a2:f9:xx:xx:xx  UHLWI           0        9     en0   1133
...

traceroute after pinging mac from target:

traceroute target
traceroute to target.domain (192.168.1.126), 64 hops max, 52 byte packets
 1  target.domain (192.168.1.126)  5.718 ms  3.204 ms  3.538 ms

ifconfig en0 on mac:

en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
    options=10b<RXCSUM,TXCSUM,VLAN_HWTAGGING,AV>
    ether 38:c9:86:xx:xx:xx
    inet6 fe80::xx...xx%en0 prefixlen 64 secured scopeid 0x5
    inet6 2601:xx...xx prefixlen 64 autoconf secured
    inet6 2601:xx...xx prefixlen 64 autoconf temporary
    inet 192.168.1.59 netmask 0xffffff00 broadcast 192.168.1.255
    nd6 options=201<PERFORMNUD,DAD>
    media: autoselect (1000baseT <full-duplex>)
    status: active

Edit: Looks like the problem lies in the ARP table on mac.

arp -a during the problem:

target.domain (192.168.1.126) at (incomplete) on en0 ifscope [ethernet]

arp -a after pinging mac from target:

target.domain (192.168.1.126) at 64:a2:f9:xx:xx:xx on en0 ifscope [ethernet]

sudo arp -ad immediately reverts to the broken state, and requires a fresh ping from target.

How can I make sure the ARP table is built correctly?
(Restarting doesn't seem to help, all of the output above is from a fresh boot, up 31 mins)

Is there some ARP filtering built into mac, or some form of broadcast listening that needs to be enabled in macOS?

Best Answer

Make sure that your client's route tables have routes that will tell them how to direct traffic for specific IP addresses and blocks of IPs to your default route (router).

You can check like this:

$ netstat -rn -f inet
Routing tables

Internet:
Destination        Gateway            Flags        Refs      Use   Netif Expire
default            192.168.1.2        UGSc           73   320174     en0
10.3.144.1/32      link#10            UCS             0        0     en0
127                127.0.0.1          UCS             0        0     lo0
127.0.0.1          127.0.0.1          UH             47  5116272     lo0
169.254            link#10            UCS             1        0     en0
169.254.134.80     b8:27:eb:ee:bc:4c  UHLSW           0        0     en0
192.168.1          link#10            UCS             7        0     en0
192.168.1.2/32     link#10            UCS             1        0     en0
192.168.1.2        14:cc:20:d4:56:2a  UHLWIir        27      391     en0   1178
192.168.1.10       0:22:15:91:c1:2d   UHLWI           0       51     en0   1180
192.168.1.66       6c:ad:f8:75:71:6d  UHLWIi          1     1735     en0   1174
192.168.1.81       30:b5:c2:3d:6c:37  UHLWIi          1     1440     en0   1080
192.168.1.85       b8:27:eb:75:c5:c2  UHLWIi          2    21229     en0   1194
192.168.1.87       b8:27:eb:ee:bc:4c  UHLWI           0        0     en0    866
192.168.1.89       34:93:42:2d:92:c4  UHLWI           0       62     en0   1113
192.168.1.91       0:21:bd:af:61:cf   UHLWI           0        0     en0    784
192.168.1.95/32    link#10            UCS             0        0     en0
224.0.0/4          link#10            UmCS            2        0     en0
224.0.0.251        1:0:5e:0:0:fb      UHmLWI          0        0     en0
239.255.255.250    1:0:5e:7f:ff:fa    UHmLWI          0     2440     en0
255.255.255.255/32 link#10            UCS             0        0     en0

Here when I ping an IP that wasn't present:

$ ping -c 2 192.168.1.107
PING 192.168.1.107 (192.168.1.107): 56 data bytes
64 bytes from 192.168.1.107: icmp_seq=0 ttl=64 time=1.867 ms
64 bytes from 192.168.1.107: icmp_seq=1 ttl=64 time=7.939 ms

--- 192.168.1.107 ping statistics ---
2 packets transmitted, 2 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 1.867/4.903/7.939/3.036 ms

And you'll get a new entry to your route table:

$ netstat -rn -f inet
...
...
192.168.1.107      0:19:d1:e8:4c:95   UHLWI           0        2     en0   1197
...
...

These entries have an expiration time associated as well (far right column).