IPv6: Interface IP operations are stopped with floating IP in HA failover - linux-kernel

When a main node fails, its IP (IPv6) floats to standby node. The standby node is supposed to provide service henceforth on that IP.
Given that both these nodes co-exist in the same LAN, often it is seen that the standby node becomes unreachable. The interface is UP and RUNNING with the IPv6 address assigned, but all the IP operations are stopped.
One possibility is Duplicate Address Detection (DAD) is kicking in when the IP is getting configured on standby. The RFC says all IP operations must be stopped.
My question is regarding the specifics in Linux kernel IPv6 implementation. Previously, from kernel code, I supposed the sysctl variable "disable_ipv6" must be getting set. But the kernel is not disabling IPv6, it is just stops all IP operations on that interface.
Can anyone explain what Linux kernel IPv6 does when it "disables these IP operations" on DAD failure? Can this be reset to normal without doing the interface DOWN & UP? Any pointers in the code will be very helpful.

This article elaborates the specification and behavior w.r.t. what really is happening in the kernel w.r.t. IPv6 implementation and the floating IP configuration. It also suggests a solution:
http://criticalindirection.com/2015/06/30/ipv6_dad_floating_ips/
It mentions for "user-assigned link-local", the IPv6 allocation gets stuck in tentative state, marked by IFA_F_TENTATIVE in the kernel. This state implies DAD is in progress and the IP is not yet validated. For "auto-assigned link-local", if the DAD fails it retries accept_dad times (with new auto-generated IP each time), and after that it disables IPv6 on that interface.
Solution it suggests is: Disable DAD before configuring the floating IP and enable it back when it is out of the tentative state.
For more details refer above link.

This is related to a bug in nova, bug #101134
The documentation for accept_dad says:
accept_dad - INTEGER
Whether to accept DAD (Duplicate Address Detection).
0: Disable DAD
1: Enable DAD (default)
2: Enable DAD, and disable IPv6 operation if MAC-based
duplicate link-local address has been found.
So you can use sysctl -w net.ipv6.conf.default.accept_dad=0 to workaround the bug and disable DAD.
Alternatively, you can fix this bug by implementing the proposing patches to nova/virt/libvirt/firewall.py from that same bug report.
If it is not already present in the NWFilterFirewall class, add the following staticmethod:
def nova_no_nd_reflection_filter(self):
"""This filter protects false positives on IPv6 Duplicate Address
Detection(DAD).
"""
uuid = self._get_filter_uuid('nova-no-nd-reflection')
return '''<filter name='nova-no-nd-reflection' chain='ipv6'>
<!-- no nd reflection -->
<!-- drop if destination mac is v6 mcast mac addr and
we sent it. -->
<uuid>%s</uuid>
<rule action='drop' direction='in'>
<mac dstmacaddr='33:33:00:00:00:00'
dstmacmask='ff:ff:00:00:00:00' srcmacaddr='$MAC'/>
</rule>
</filter>''' % uuid
Then, add this filter to your filter lists in _ensure_static_filters() by adding:
self._define_filter(self.nova_no_nd_reflection_filter())
after filter_set is defined.

Related

Is tcpdump 100% reliable on outgoing connection?

I'm working on a server.
Its doing health check to another server, like a simple tcp open connection
Basically my tcpdump says that the packet (the health check tcp sYn packet) is going out of my interface.
But, the Firewall doesnt see anything.
I have doubt if the packet is going outside the server at all, or the problem is on the switch.
Is there a way to be sure about this?
Captured traffic == source of truth
It's possible for tcpdump to have false negatives (i.e. packets are sent but tcpdump doesn't record them). This can be due to hardware (CPU, RAM, disk) being maxed or if tcpdump's buffer size (-B) is too small. Likewise, it's possible your firewall isn't picking it up where it should.
It's highly unlikely for tcpdump to report a false positive. Tcpdump copies bytes from your network interface [0] and summarizes them in a text line (depending on your output options). If firewall rules from e.g. iptables would block traffic, tcpdump won't see the traffic. If tcpdump reports a packet, you can be sure it transited that interface.
[0]: If you're curious how tcpdump works at a lower level, use strace.
Flow-based troubleshooting
Flow-based troubleshooting can be required to figure out where packets get dropped in a network. For your network of server:A <-> B:switch:C <-> D:Firewall, we know that A sends it and D does not receive it. Thus you should check ports B and C to determine where the packet loss occurs. It's also possible that D reports a false negative. You can test both of these things by plugging this server directly into a different firewall that can take packet captures/monitor traffic.

How to determine the default network adapter through WinApi?

Is there a way through Windows API to determine which is the primary/default network adapter?
For example, if I have a PC with two network cards, I need to know which one is used by the system to access internet, similarly if I have a network adapter and a virtual adapter.
I tried with GetAdaptersAddresses but it doesn't show which is the favourite one, maybe with GetBestInterface?
How about using GetAdaptersInfo and looking for an IP range that satisfies your requirement?
Alternatively, came across this (WMI):
https://msdn.microsoft.com/en-us/library/windows/desktop/aa394216(v=vs.85).aspx
~snip:
Once you have done so, you will likely have reduced your list to one
or two configured adapters.
You can also use the following procedure to find the default adapter:
Run the following query: "SELECT InterfaceIndex, Destination FROM Win32_IP4RouteTable WHERE Destination='0.0.0.0'" You should only have
one default network destination 0.0.0.0.
Use the InterfaceIndex to retrieve the Network Adapter you want. "SELECT * FROM Win32_NetworkAdapter WHERE InterfaceIndex=" +
insertVariableHere
Here's a CodeProject article claiming to determine the default:
http://www.codeproject.com/Articles/13421/Getting-the-Physical-MAC-address-of-a-Network-Inte
Getting the Physical (MAC) address of a Network Interface Card and finding out if it is the primary adapter on a multi-homed system
Finding out if the adapter with the given index is the primary adapter
In order to find out if the adapter with the given index is the
primary adapter, I had to add a function to the dialog class
CNetCfgDlg. This code iterates over the m_pAdapters array, comparing
the given adapter index with the index for each adapter in the array.
If the given adapter index is equal to the smallest index of all
adapters in the array, then it is the primary adapter
And one more thing to consider, is there's the 'Automatic Metric' setting for each adapter which seems to choose the lowest setting as the preferred (although not sure how to access this metric setting programmatically):
http://www.softminer.net/2011/09/setting-default-network-adapter-in.html
This SO Answer explains how to determine the local IP address used to connect to the Internet (like Google's DNS servers), you can then compare this local IP address with the list returned by GetAdaptersAddresses to determine which network card was used for Internet Access.

Can any port in the sate of "LISTEN" be seen to the outter?

I execute the command "netstat -tln" in the shell, here is what it outputs.
the 5th field is the foreign address, i dont' know what it means here. Does "0.0.0.0:" mean any address can be connected to this port without the consideration of iptables, if so what does ":::" mean?
The 3 Colons (:::) signifies IPv6.
The 0.0.0.0 means that a given socket is listening on all the available IP addresses the computer has available.
If you wish to not use IPv6 i believe you can remove it.
Verify the Man Page but probably removing "ipv6.o"" will work.

How to add persistent IPv6 address in Vista/Windows7?

I want to add a persistent IPv6 address using just API calls or with Registry edits. I have currently implemented a code which uses CreateUnicastIpAddressEntry API to add the IPv6 address successfully, but the IP address is destroyed when the adapter is reset or machine rebooted (as mentioned in MSDN docs).
With IPv4, it was easy to do. Just use AddIPAddress API combined with registry entries to get the desired result.
I have tried to find any entry in the Windows Registry which is being used to save the IPv6 address without any success. The MSDN docs suggests to use netsh.exe to do the task, but then I am quite sure netsh.exe is doing some API call or Registry entry to achieve this task (which is not documented by Microsoft anywhere).
How can this be achieved?
Well, after some reverse engineering of netsh.exe and detailed analysis I think there is sufficient info to create a persistent ipv6 address.
The ipv6 address (UNICAST) is stored in following registry key:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nsi\{eb004a01-9b1a-11d4-9123-0050047759bc}\10
For every ipv6 address to be added, create a REG_BINARY value such that the name of the value contains NET_LUID concatenated with the ipv6 address in full. Like for example, if the ipv6 address is 2001::1, the name of the value will be 000000090000060020010000000000000000000000000001, where the first 16 characters is the NET_LUID of the network adapter and the rest the ipv6 address in full.
This registry value data is made of a 48 byte long structure given below:
typedef struct _UNKNOWN {
ULONG ValidLifetime;
ULONG PreferredLifetime;
NL_PREFIX_ORIGIN PrefixOrigin;
NL_SUFFIX_ORIGIN SuffixOrigin;
UINT8 OnLinkPrefixLength;
BOOLEAN SkipAsSource;
UCHAR Unknown[28];
} UNKNOWN;
The last 28 bytes of this structure is unknown and must be initialized to 0xFF.
Refer to MIB_UNICASTIPADDRESS_ROW structure info in msdn for more info on the UNKNOWN structure members.
While doing this, I also figured out that ipv6 ANYCAST addresses are stored similarly in registry key:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nsi\{eb004a01-9b1a-11d4-9123-0050047759bc}\8`\

Find internal IP address with BASH

I am already aware of many ways of getting your internal IP (ifconfig, ip addr, /etc/hosts, etc), but I am trying to write a bash script that will always return the internal IP. The problem is, many one-liners (/sbin/ifconfig|grep inet|head -1|sed 's/\:/ /'|awk '{print $3}') can return multiple IPs, and I need to distinguish the internal one manually.
I suspect that to the computer, there is no difference between and an external IP and an internal IP, and thus no 100%, guaranteed way to get the right IP.
The end result is that this script will return the internal IP, no matter if its a 192 address or a 204 address, etc.
Thanks in advance.
"hostname -i" should hopefully give you the same result
As others have mentioned, a machine is not really guaranteed, or even likely, to have a single IP address. I'm not sure exactly what you mean by "internal IP"; sometimes this can mean "IP address on the local network", i.e. the interface which connects to a NAT-enabled firewall.
I'm thinking that the best way to do this is to connect to a host on the network you want and use the address from which that connection originates. This will be the interface which the machine normally uses to connect to that network. The user Unkwntech had the same idea on this thread. The code below is just taken from that answer.
I don't know if this really qualifies as a "bash" solution, since it's just an inline Python script, but anyway this will get you the local ip address used to reach google.com. So this will give you the IP address of whichever interface the machine uses to reach Internet hosts.
$ python -c 'import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("google.com", 80))
print s.getsockname()[0]'
A more bash-y solution might use tracepath or some similar utility.
Systems can have multiple private IPs too though. You would have to limit your searching on IPs to private IPs. 10.0.0.0/8, 172.16.0.0/12, and 192.168.0.0/16.
Within the RFC 1918 private address spaces, a machine could conceivably have every address in the 10/8 range, the 172.16/12 range, and the 192.168/16 range, for a total of 17891328 IP addresses, and all of them would be legal "internal" IPs.
Oh yes, don't forget IPv6 :) 2^64 possible addresses per network for a single machine, which might participate in multiple networks.
This isn't exactly academic, either: it is quite common for VMWare, VirtualBox, QEMU, etc. host systems to have multiple RFC 1918 addresses assigned; one for the 'usual use', and one that is used specifically to communicate with guest operating systems. Or routers / firewalls, they might have a dozen internal IPs specifically to subnet a network for access control reasons.

Resources