If you have just changed ISPs or moved house and your internet suddenly starts misbehaving the likelihood is your Maximum Transmission Unit (MTU) is set too high for your ISP. The default internet facing MTU is 1500 bytes, BUT depending on your setup, this often needs to be set much lower.
First check your current MTU.
$ networksetup -getMTU en0 Active MTU: 1500 (Current Setting: 1500)
As you can see, the Mac is set to 1500 bytes MTU. So how do we find out what it should be? We are going to send a fixed size Echo packet out, and tell the network not to fragment this packet. If somewhere along the line this packet is too big then this request will fail.
$ ping -D -s 1500 www.google.com PING www.google.com (184.108.40.206): 1500 data bytes ping: sendto: Message too long ping: sendto: Message too long Request timeout for icmp_seq 0 ping: sendto: Message too long Request timeout for icmp_seq 1 ping: sendto: Message too long
Ok, so our MTU is too high.
Procedure to find optimal MTU:
Hint: For PPPoE, your Max MTU should be no more than 1492 to allow space for the 8 byte PPPoE “wrapper”. 1492 + 8 = 1500. The ping test we will be doing does not include the IP/ICMP header of 28 bytes. 1500 – 28 = 1472. Include the 8 byte PPPoE wrapper if your ISP uses PPPoE and you get 1500 – 28 – 8 = 1464.
The best value for MTU is that value just before your packets get fragmented. Add 28 to the largest packet size that does not result in fragmenting the packets (since the ping command specifies the ping packet size, not including the IP/ICMP header of 28 bytes), and this is your Max MTU setting.
The below is an automated ping sweep, that tests various packet sizes until it fails (increasing in 10 bytes per iteration):
$ ping -g 1300 -G 1600 -h 10 -D www.google.com PING www.google.com (220.127.116.11): (1300 ... 1600) data bytes Request timeout for icmp_seq 0 Request timeout for icmp_seq 1 Request timeout for icmp_seq 2 Request timeout for icmp_seq 3 Request timeout for icmp_seq 4 Request timeout for icmp_seq 5 Request timeout for icmp_seq 6 ping: sendto: Message too long Request timeout for icmp_seq 7
As you can see it failed on the 7th attempt (giving you a 1300 + 60 MTU).
Once you find the MTU, you can set it as per below:
$ ping -D -s 1360 www.google.com PING www.google.com (18.104.22.168): 1370 data bytes Request timeout for icmp_seq 0
So I can set my MTU as 1360 + 28 = 1386:
networksetup -setMTU en0 1386