Merge branch 'bugfix/interface_detection'

This commit is contained in:
Christian Stein 2020-02-14 09:34:41 +01:00
commit 90a8fab9cb
3 changed files with 129 additions and 75 deletions

View file

@ -21,16 +21,17 @@
function ConvertTo-IcingaIPBinaryString() function ConvertTo-IcingaIPBinaryString()
{ {
param( param(
$IP $IP
); );
if ($IP -like '*.*') {
$IP = ConvertTo-IcingaIPv4BinaryString -IP $IP;
} elseif ($IP -like '*:*') {
$IP = ConvertTo-IcingaIPv6BinaryString -IP $IP;
} else {
return 'Invalid IP was provided!';
}
return $IP; if ($IP -like '*.*') {
$IP = ConvertTo-IcingaIPv4BinaryString -IP $IP;
} elseif ($IP -like '*:*') {
$IP = ConvertTo-IcingaIPv6BinaryString -IP $IP;
} else {
return 'Invalid IP was provided!';
}
return $IP;
} }

View file

@ -21,18 +21,24 @@
function ConvertTo-IcingaIPv4BinaryString() function ConvertTo-IcingaIPv4BinaryString()
{ {
param( param(
[string]$IP [string]$IP
); );
$IP = $IP -split '\.' | ForEach-Object { try {
[System.Convert]::ToString($_, 2).PadLeft(8, '0'); $IP = $IP -split '\.' | ForEach-Object {
} [System.Convert]::ToString($_, 2).PadLeft(8, '0');
$IP = $IP -join ''; }
$IP = $IP -replace '\s',''; $IP = $IP -join '';
$IP = $IP -replace '\s','';
} catch {
# Todo: Should we handle errors? It might happen due to faulty routes or unhandled route config
# we throw errors which should have no effect at all
return $null;
}
return @{ return @{
'value' = $IP; 'value' = $IP;
'name' = 'IPv4' 'name' = 'IPv4'
} }
} }

View file

@ -37,7 +37,7 @@ function Get-IcingaNetworkInterface()
} }
try { try {
$IP = ([System.Net.Dns]::GetHostAddresses($IP)).IPAddressToString; [array]$IP = ([System.Net.Dns]::GetHostAddresses($IP)).IPAddressToString;
} catch { } catch {
Write-Host 'Invalid IP was provided!'; Write-Host 'Invalid IP was provided!';
return $null; return $null;
@ -53,72 +53,119 @@ function Get-IcingaNetworkInterface()
foreach ( $Info in $InterfaceInfo ) { foreach ( $Info in $InterfaceInfo ) {
$Counter++; $Counter++;
$Divide = $Info.DestinationPrefix; $Divide = $Info.DestinationPrefix;
$IP,$Mask = $Divide.Split('/'); $IP, $Mask = $Divide.Split('/');
foreach ($destinationIP in $IPBinStringMaster) {
[string]$Key = '';
[string]$MaskKey = '';
############################################################################ ############################################################################
################################ IPv4 #################################### ################################ IPv4 ####################################
############################################################################ ############################################################################
if ($IPBinStringMaster.name -eq 'IPv4') { if ($destinationIP.name -eq 'IPv4') {
if ($IP -like '*.*') { if ($IP -like '*.*') {
############################################################################ ############################################################################
if ([int]$Mask -lt 10) { if ([int]$Mask -lt 10) {
[string]$MaskKey = [string]::Format('00{0}', $Mask); $MaskKey = [string]::Format('00{0}', $Mask);
} else { } else {
[string]$MaskKey = [string]::Format('0{0}', $Mask); $MaskKey = [string]::Format('0{0}', $Mask);
}
[string]$Key = [string]::Format('{0}-{1}', $MaskKey, $Counter);
$InterfaceData.Add(
$Key, @{
'Binary IP String' = (ConvertTo-IcingaIPBinaryString -IP $IP).value;
'Mask' = $Mask;
'Interface' = $Info.ifIndex;
} }
);
############################################################################ ############################################################################
}
}
############################################################################
################################ IPv4 ####################################
############################################################################
if ($IPBinStringMaster.name -eq 'IPv6') {
if ($IP -like '*:*') {
############################################################################
if ([int]$Mask -lt 10) {
[string]$MaskKey = [string]::Format('00{0}', $Mask);
} elseif ([int]$Mask -lt 100) {
[string]$MaskKey = [string]::Format('0{0}', $Mask);
} else {
[string]$MaskKey = $Mask;
} }
[string]$Key = [string]::Format('{0}-{1}', $MaskKey, $Counter);
$InterfaceData.Add(
$Key, @{
'Binary IP String' = (ConvertTo-IcingaIPBinaryString -IP $IP);
'Mask' = $Mask;
'Interface' = $Info.ifIndex;
}
);
############################################################################
} }
############################################################################
################################ IPv6 ####################################
############################################################################
if ($destinationIP.name -eq 'IPv6') {
if ($IP -like '*:*') {
############################################################################
if ([int]$Mask -lt 10) {
$MaskKey = [string]::Format('00{0}', $Mask);
} elseif ([int]$Mask -lt 100) {
$MaskKey = [string]::Format('0{0}', $Mask);
} else {
$MaskKey = $Mask;
}
############################################################################
}
}
$Key = [string]::Format('{0}-{1}', $MaskKey, $Counter);
if ($InterfaceData.ContainsKey($Key)) {
continue;
}
$InterfaceData.Add(
$Key, @{
'Binary IP String' = (ConvertTo-IcingaIPBinaryString -IP $IP).value;
'Mask' = $Mask;
'Interface' = $Info.ifIndex;
}
);
} }
} }
$InterfaceDataOrdered = $InterfaceData.GetEnumerator() | Sort-Object -Property Name -Descending; $InterfaceDataOrdered = $InterfaceData.GetEnumerator() | Sort-Object -Property Name -Descending;
$ExternalInterfaces = @{};
foreach ( $Route in $InterfaceDataOrdered ) { foreach ( $Route in $InterfaceDataOrdered ) {
[string]$RegexPattern = [string]::Format("^.{{{0}}}", $Route.Value.Mask); foreach ($destinationIP in $IPBinStringMaster) {
[string]$ToBeMatched = $Route.Value."Binary IP String"; [string]$RegexPattern = [string]::Format("^.{{{0}}}", $Route.Value.Mask);
$Match1=[regex]::Matches($ToBeMatched, $RegexPattern).Value; [string]$ToBeMatched = $Route.Value."Binary IP String";
$Match2=[regex]::Matches($IPBinStringMaster.Value, $RegexPattern).Value; if ($null -eq $ToBeMatched) {
continue;
}
If ($Match1 -like $Match2) { $Match1=[regex]::Matches($ToBeMatched, $RegexPattern).Value;
return ((Get-NetIPAddress -InterfaceIndex $Route.Value.Interface -AddressFamily $IPBinStringMaster.name).IPAddress); $Match2=[regex]::Matches($destinationIP.Value, $RegexPattern).Value;
If ($Match1 -like $Match2) {
$ExternalInterface = ((Get-NetIPAddress -InterfaceIndex $Route.Value.Interface -AddressFamily $destinationIP.Name -ErrorAction SilentlyContinue).IPAddress);
# If no interface was found -> skip this entry
if ($null -eq $ExternalInterface) {
continue;
}
if ($ExternalInterfaces.ContainsKey($ExternalInterface)) {
$ExternalInterfaces[$ExternalInterface].count += 1;
} else {
$ExternalInterfaces.Add(
$ExternalInterface,
@{
'count' = 1
}
);
}
}
} }
} }
return ((Get-NetIPAddress -InterfaceIndex (Get-NetRoute | Where-Object -Property DestinationPrefix -like '0.0.0.0/0')[0].IfIndex -AddressFamily $IPBinStringMaster.name).IPAddress).split('%')[0];
if ($ExternalInterfaces.Count -eq 0) {
foreach ($destinationIP in $IPBinStringMaster) {
$ExternalInterface = ((Get-NetIPAddress -InterfaceIndex (Get-NetRoute | Where-Object -Property DestinationPrefix -like '0.0.0.0/0')[0].IfIndex -AddressFamily $destinationIP.name).IPAddress).split('%')[0];
if ($ExternalInterfaces.ContainsKey($ExternalInterface)) {
$ExternalInterfaces[$ExternalInterface].count += 1;
} else {
$ExternalInterfaces.Add(
$ExternalInterface,
@{
'count' = 1
}
);
}
}
}
$InternalCount = 0;
$UseInterface = '';
foreach ($interface in $ExternalInterfaces.Keys) {
$currentCount = $ExternalInterfaces[$interface].count;
if ($currentCount -gt $InternalCount) {
$InternalCount = $currentCount;
$UseInterface = $interface;
}
}
return $UseInterface;
} }