Find internal IP address with BASH - 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.

Related

If I want to set aside range of addresses to be assigned to servers

I am assigning the DHCP IPv4 addresses and I would like to set aside 5 addresses for future servers, will that mean that I have to have the end IP address as 192.168.1.249?
screenchot of the range I currently assigned
DHCP description
If your 5 servers will have static IP configured, Yes it's enough to shrink last ip-range to 192.168.1.249
If your 5 servers will be configured with DHCP too, you need to leave it to 192.168.1.254 and then create static reserves for them. ( on DHCP server window)
Folder Reservation > second button New reservation
Fill all data, if you don't know what mac will have each one, you can invent like 00-00-00-00-00-01 until you know them
Tutorial with images

getaddrinfo with flag AI_NUMERICHOST

Please tell me something I can't understand. There is a function getaddrinfo() and there is a flag AI_NUMERICHOST. MSDN says that in getaddrinfo() with this flag, you need to send the numeric value of the IP address, and not the domain name. But why?
I already have an IP address, why should I ask DNS for an IP address?
getaddrinfo() outputs sockaddr_... structs (sockaddr_in or sockaddr_in6) for the requested host/service. It is not just about IP addresses, it is also about other things, like socket types, service ports, etc, depending on your input and hint values.
So, if you already have an IP address in a string format, you can have getaddrinfo() parse that string for you (specifying AI_NUMERICHOST to avoid DNS) into a binary format in the output sockaddr_..., as well as fill in other sockaddr_... fields at the same time.

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

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.

ipv6calc outputs wrong address when converting from ipv4 to ipv6?

Having a strange issue while trying to convert an ipv4 list file to ipv6:
ipv6calc -q --action conv6to4 --in ipv4 1.1.23.1 --out ipv6
2002:101:1701::
Trying to validate that result is correct, I used some online converters and it seems that 1.1.23.1 is 2002:0:0:0:0:0:101:1701 (or else 2002::101:1701).
So the last "::" should be removed & 2002 should have extra ":".
I really don't want to use sed/awk commands in order to manipulate this result, so the questions are:
is there alternative cmd/linux SW?
is this somehow fixed inside ipv6 calc, am I doing something wrong?
Thanks
This is the correct 6to4 address. A 6to4 subnet is on the format 2002:IP4_HI:IP4_LO::/48. IP4_HI is the top 16 bits of the IPv4 address, while IP4_LO is the low 16 bits of the address.
For example, the IPv4 address 1.2.3.4 gives you the 6to4 subnet 2002:0102:0304::/48.
See 6to4 address block allocation for more details.
A different question is whether this is actually the address you want? There are other ways to map IPv4 addresses to IPv6 addresses. For example, there are IPv4-mapped IPv6 addresses, which are typically written as ::ffff:1.2.3.4.
The address format you need depends on what you are going to use it for.

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.

Resources