Skip to content
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

"Invalid VRRPv3 checksum" in three-node VRRP v3 setup #642

Closed
thresheek opened this issue Aug 24, 2017 · 9 comments
Closed

"Invalid VRRPv3 checksum" in three-node VRRP v3 setup #642

thresheek opened this issue Aug 24, 2017 · 9 comments

Comments

@thresheek
Copy link
Contributor

We have a following setup on keepalived-1.3.6 with three nodes, running on Ubuntu 16.04:

I see the following messages on the node ub1604-kl3:

Aug 24 11:29:04 localhost systemd[1]: Starting LVS and VRRP High Availability Monitor...
Aug 24 11:29:04 localhost Keepalived[7327]: Starting Keepalived v1.3.6 (08/14,2017), git commit v1.3.6-1-g8ee15ec
Aug 24 11:29:04 localhost Keepalived[7327]: Opening file '/etc/keepalived/keepalived.conf'.
Aug 24 11:29:04 localhost Keepalived[7329]: Starting VRRP child process, pid=7330
Aug 24 11:29:04 localhost systemd[1]: Started LVS and VRRP High Availability Monitor.
Aug 24 11:29:04 localhost Keepalived_vrrp[7330]: Registering Kernel netlink reflector
Aug 24 11:29:04 localhost Keepalived_vrrp[7330]: Registering Kernel netlink command channel
Aug 24 11:29:04 localhost Keepalived_vrrp[7330]: Registering gratuitous ARP shared channel
Aug 24 11:29:04 localhost Keepalived_vrrp[7330]: Opening file '/etc/keepalived/keepalived.conf'.
Aug 24 11:29:04 localhost Keepalived_vrrp[7330]: WARNING - default user 'keepalived_script' for script execution does not exist - please create.
Aug 24 11:29:04 localhost Keepalived_vrrp[7330]: SECURITY VIOLATION - scripts are being executed but script_security not enabled.
Aug 24 11:29:04 localhost Keepalived_vrrp[7330]: Using LinkWatch kernel netlink reflector...
Aug 24 11:29:04 localhost Keepalived_vrrp[7330]: VRRP_Instance(VI_1) Entering BACKUP STATE
Aug 24 11:29:04 localhost Keepalived_vrrp[7330]: Opening script file /usr/lib/keepalived/nginx-ha-notify
Aug 24 11:29:04 localhost nginx-ha-keepalived: Transition to state 'BACKUP' on VRRP instance 'VI_1'.
Aug 24 11:29:04 localhost Keepalived_vrrp[7330]: VRRP_Script(chk_manual_failover) succeeded
Aug 24 11:29:04 localhost Keepalived_vrrp[7330]: VRRP_Script(chk_nginx_service) succeeded
Aug 24 11:29:04 localhost Keepalived_vrrp[7330]: (VI_1): Invalid VRRPv3 checksum
Aug 24 11:29:04 localhost Keepalived_vrrp[7330]: bogus VRRP packet received on eth0 !!!
Aug 24 11:29:04 localhost Keepalived_vrrp[7330]: VRRP_Instance(VI_1) ignoring received advertisment...
Aug 24 11:29:05 localhost Keepalived_vrrp[7330]: VRRP_Instance(VI_1) Changing effective priority from 10 to 110
Aug 24 11:29:05 localhost Keepalived_vrrp[7330]: (VI_1): Invalid VRRPv3 checksum
Aug 24 11:29:05 localhost Keepalived_vrrp[7330]: bogus VRRP packet received on eth0 !!!
Aug 24 11:29:05 localhost Keepalived_vrrp[7330]: VRRP_Instance(VI_1) ignoring received advertisment...
Aug 24 11:29:06 localhost Keepalived_vrrp[7330]: (VI_1): Invalid VRRPv3 checksum
Aug 24 11:29:06 localhost Keepalived_vrrp[7330]: bogus VRRP packet received on eth0 !!!
Aug 24 11:29:06 localhost Keepalived_vrrp[7330]: VRRP_Instance(VI_1) ignoring received advertisment...

This also means that the ub1604-kl3 node is out of the VRRP elections, and isnt able to become a master in case bad things happen to first two nodes.

The messages, however, go away if I use vrrp_version 2 in the configuration files, and all three nodes are participating in elections & can become masters.

I believe vrrp3 checksum generation is broken for this particular case (judging by wireshark reports - as I did not read the VRRPv3 specifications and did not read keepalived code).

It is also possible that checksum check is broken as well, as ub1604-kl2 does not expose the same behaviour as the third node.

Here are the traffic dump files suitable to import to wireshark, taken on ub1604-kl1 node (being master in both cases) with 'tcpdump -w foo.dump -ni eth0 vrrp`:

checksums:

SHA512 (keepalived-1.3.6-vrrpv2.wireshark.dump) = ccb1e33b64c2bf6d1b8f77f396ef71b198348fe53b826d4871671a224a2d8854430f2385b1e02b544f2195c2d6785d0366338cbe7f1c631e66730339b68cc821
SHA512 (keepalived-1.3.6-vrrpv3.wireshark.dump) = 7fd108e4815b4d8e04e507e52d12b01bb0dd0abc071f737e01c8889658d8bd686742ba992bc21f176d8ec54eb7232236f5b60550c9d61774588ce7a7f192d9b7

Here's what wireshark tells about the packet in the VRRPv2 case:

Frame 1: 54 bytes on wire (432 bits), 54 bytes captured (432 bits)
Ethernet II, Src: RealtekU_ac:a0:bf (52:54:00:ac:a0:bf), Dst: RealtekU_38:e8:6e (52:54:00:38:e8:6e)
Internet Protocol Version 4, Src: 192.168.128.111, Dst: 192.168.128.112
Virtual Router Redundancy Protocol
Version 2, Packet type 1 (Advertisement)
Virtual Rtr ID: 51
Priority: 201 (Non-default backup priority)
Addr Count: 1
Auth Type: No Authentication (0)
Adver Int: 1
Checksum: 0x0ba9 [correct]
[Checksum Status: Good]
IP Address: 10.0.0.33

And here's what wireshark tells about the packet in the VRRPv3 case:

Frame 1: 46 bytes on wire (368 bits), 46 bytes captured (368 bits)
Ethernet II, Src: RealtekU_ac:a0:bf (52:54:00:ac:a0:bf), Dst: RealtekU_38:e8:6e (52:54:00:38:e8:6e)
Internet Protocol Version 4, Src: 192.168.128.111, Dst: 192.168.128.112
Virtual Router Redundancy Protocol
Version 3, Packet type 1 (Advertisement)
Virtual Rtr ID: 51
Priority: 201 (Non-default backup priority)
Addr Count: 1
0000 .... = Reserved: 0
.... 0000 0110 0100 = Adver Int: 100
Checksum: 0xd99e [incorrect, should be 0x7898]
[Expert Info (Warning/Checksum): Bad checksum [should be 0x7898]]
[Bad checksum [should be 0x7898]]
[Severity level: Warning]
[Group: Checksum]
[Checksum Status: Bad]
IP Address: 10.0.0.33

Thanks.

@dseeley
Copy link

dseeley commented Aug 29, 2017

Also experiencing this issue with VRRPv3. OK with VRRPv2. Observed the same with wireshark. I see the same behaviour on v1.3.5 & v1.2.4.

On CentOS7.3.

@pqarmitage
Copy link
Collaborator

A couple of months ago I found a checksum problem, but I can't remember the details of it now, but I do remember that I first noticed it due to wireshark reporting it. I didn't push a fix for it since it would have created incompatibility between versions.

I'll have a look this evening to see if what I found is the same as you are experiencing. Whatever fix we come up with we need to somehow ensure backward compatibility, but I would hope that we can make the default position going forward to generate the correct checksum.

@pqarmitage
Copy link
Collaborator

pqarmitage commented Aug 29, 2017

The good news is that this is the problem I found before and have a fix for. The only problem with the patch (attached) is that it is incompatible with unpatched versions of keepalived.

VRRPv3 adds a pseudo IP header into the checksum, whereas VRRPv2 doesn't. The problem is that whether unicast or multicast is used, keepalived at the moment is putting the multicast address into the pseudo header before calculating the checksum, but since the receive end is also putting the multicast address into the pseudo header before checking the checksum, the checksums match even though they are incorrect, as reported by Wireshark.

What I don't yet understand is why the checksum is 0000 when the advert is sent to the second unicast peer (ub1604-kl3) (I am seeing exactly the same behaviour on my system). I need to investigate this further so that I understand what is happening before pushing the patch upstream. With the attached patch applied, it sends the correct (non zero) checksum to each peer.

Is there a reason why you are using unicast rather than the default of multicast. If you switched to multicast, not only would you be conforming to the RFC and it would be more efficient for keepalived, you won't get the checksum problem even without applying the patch.

I have noticed that ub1604-kl2 and ub1604-kl3 are both using priority 100. This is probably not ideal, since if ub1604-kl1 goes away, both backup instances will attempt to become master at the same time (give or take a few microseconds). If both the backup instances transition to master at the same time (because they timeout before they see an advert from the other backup instance) the one with the lower primary IP address will then have to transition again to backup. It is probably better to make sure they have difference priorities.

vrrpv3_checksum.patch.txt

@thresheek
Copy link
Contributor Author

Many thanks for looking into this issue, @pqarmitage! I'll apply the patch and do the tests here too.

The reason we use unicast is that multicast is not widely supported in public/private cloud networks; I absolutely get the reasons to use it on-premises in fully controlled environment, but in our experience those are rarely seen these days and unicast is just something that will mostly work everywhere.

Thanks for the advice on the priorities for 2nd and 3rd node - it's actually a proof-of-concept setup to reproduce the issue and it makes perfect sense to have lower priority on the third node.

@pqarmitage
Copy link
Collaborator

I've now found the reason the checksum was changing from the (incorrectly calculated) checksum to 0. When constructing the packet for the next unicast destination, the same buffer was used as for the previous unicast destination, and the previous checksum was not cleared before calculating the next checksum, and so the checksum was alternating between the (incorrectly calculated) checksum and 0.

This is the actual cause of your problem of invalid checksums being reported by keepalived. The patch i provided above resolves the issue of wireshark reporting incorrect checksums, but also solves your problem since it clears the checksum field before calculating the new checksum.

The patch I previously posted will resolve your problem and also stop wireshark reporting invalid checksums; the patch from this update is the minimal change to allow keepalived to work but doesn't resolve the bad checksum reported by wireshark, but it does maintain backward compatibility with previous versions of keepalived.
checksum_fix.patch.txt

dseeley added a commit to dseeley/keepalived that referenced this issue Aug 30, 2017
dseeley added a commit to dseeley/keepalived that referenced this issue Aug 30, 2017
@dseeley
Copy link

dseeley commented Aug 30, 2017

Thanks for looking in to this.

I'm similarly using unicast mode because we're going to be in public cloud (and openstack in private). I've tested both the patches for my usecase (which only uses VRRP, no IPVS): Both patches work fine in unicast mode (unable to test multicast unfortunately) - no checksum errors, correct handovers etc.

The first patch is clearly more ideal - wireshark checksum errors when trying to diagnose network issues would remain confusing. Is the backwards compatibility issue that all participating keepalived clients would have to be upgraded to this fixed version at the same time, (if so, maybe a major version release for this fix)? Either way though, one of these would be good to have upstream.

@pqarmitage
Copy link
Collaborator

Commit 67275d2 fixes the problem of alternate unicast hosts having the checksum set to 0.

This does not resolve the issue of Wireshark reporting incorrect checksums. I think I have devised a way of fixing the checksum algorithm while maintaining backward compatibility. I'll write it up later and it would be useful to have feedback.

@thresheek
Copy link
Contributor Author

Thanks @pqarmitage. I've backported the following four commits on top of 1.3.6:

67275d2
eb64954
bcf2936
0d52573

And it seems it the problem with invalid VRRP checksums went away and cluster is now operational as it should be.

I've also checked a two-node vrrp3 setup migration from an older version (in my case, 1.3.4) to 1.3.6+patches, and the step-by-step solution outlined in 0d52573 appears to be correct. Hopefully it will make it into extended notes/changelog etc.

I've also checked the packets with wireshark, they have correct checksums as well.

dseeley added a commit to dseeley/contrib that referenced this issue Sep 22, 2017
…release has a problem with V3 when there are more than 2 nodes (acassen/keepalived#642).  This has been fixed in master, but not part of a release yet.  Using VRRP V2 bypasses the issue.
@pqarmitage
Copy link
Collaborator

Closing since problem resolved in master branch.

k8s-github-robot pushed a commit to kubernetes-retired/contrib that referenced this issue Sep 29, 2017
Automatic merge from submit-queue.

Allow vrrp v2 to be specified as an argument in the container specification

Add ability to specify VRRP V2 (as opposed to default of 3) in the keepalived template. Current and previous keepalived releases have a problem with VRRP V3 when there are more than 2 nodes (acassen/keepalived#642).  This has been fixed in master, but not part of a release yet.  Using VRRP V2 bypasses the issue.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants