forked from StewLG/check_static_ip
-
Notifications
You must be signed in to change notification settings - Fork 0
/
CheckStaticIP.py
215 lines (161 loc) · 8.15 KB
/
CheckStaticIP.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
#!/usr/bin/env python3
# Copyright (c) 2020 Stewart Loving-Gibbard
# https://github.com/StewLG/check_static_ip
# Version 1.2
'''
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
'''
import argparse
import sys
import string
import requests
import time
# The true/false result of every service checked. If True, the IP address matched the expected one.
AllResults = []
# Only error messages/problems retrieving values.
ErrorMessages = []
def SetupParser():
# Build parser for arguments
parser = argparse.ArgumentParser(description='Checks to make sure that external IP V4 address is still an expected IP address')
parser.add_argument('-eip', '--expectedip', required=True, type=str, help='Expected IPV4 address')
parser.add_argument('-d', '--debug', required=False, action='store_true', help='Display debugging information; run script this way and record result when asking for help.')
parser.add_argument('-t', '--timeout', required=False, type=int, help='Timeout in seconds. This is the maximum amount of time in seconds to wait for any particular IP address service. If set to 10 the check will wait up to 10 second per service. The default is an indefinite timeout.')
return parser;
def ExitIfNoArguments(parser):
# if no arguments, print out help
if len(sys.argv)==1:
parser.print_help(sys.stderr)
sys.exit(1)
# IP4Only
IPV4_CHECK_URL = "http://ip4only.me/api";
def GetIPAddress_IP4OnlyDotMe(timeoutInSeconds, shouldShowDebugInfo):
try:
if (shouldShowDebugInfo):
print (f"Fetching from {IPV4_CHECK_URL}")
response = requests.get(IPV4_CHECK_URL, timeout=timeoutInSeconds);
except:
# Site wasn't there, internet is totally down, etc.
return f"Error retrieving {IPV4_CHECK_URL}"
# Site isn't working properly, URL changed, etc.
if (response.status_code != requests.codes.ok):
return f"Error retrieving {IPV4_CHECK_URL}, status code: {response.status_code}"
ipAddressLine = response.text;
# We expect commas in the output from the web site
if ("," not in ipAddressLine):
return f"Got unparsable response {ipAddressLine} from {IPV4_CHECK_URL}"
ipAddress = ipAddressLine.split(',')[1];
return ipAddress;
# https://ifconfig.co/ip
IPCONF_CHECK_URL = "https://ifconfig.co/ip";
def GetIPAddress_IPconf(timeoutInSeconds, shouldShowDebugInfo):
try:
if (shouldShowDebugInfo):
print (f"Fetching from {IPCONF_CHECK_URL}")
response = requests.get(IPCONF_CHECK_URL, timeout=timeoutInSeconds);
except:
# Site wasn't there, internet is totally down, etc.
return f"Error retrieving {IPCONF_CHECK_URL}"
# Site isn't working properly, URL changed, etc.
if (response.status_code != requests.codes.ok):
return f"Error retrieving {IPCONF_CHECK_URL}, status code: {response.status_code}"
# This service supports JSON etc, but the simple version with just the IP is fine.
ipAddress = response.text;
return ipAddress;
# https://icanhazip.com
ICANHAZIP_CHECK_URL = "https://icanhazip.com";
def GetIPAddress_icanhazIP(timeoutInSeconds, shouldShowDebugInfo):
try:
if (shouldShowDebugInfo):
print (f"Fetching from {ICANHAZIP_CHECK_URL}")
response = requests.get(ICANHAZIP_CHECK_URL, timeout=timeoutInSeconds);
except:
# Site wasn't there, internet is totally down, etc.
return f"Error retrieving {ICANHAZIP_CHECK_URL}"
# Site isn't working properly, URL changed, etc.
if (response.status_code != requests.codes.ok):
return f"Error retrieving {ICANHAZIP_CHECK_URL}, status code: {response.status_code}"
# This service supports JSON etc, but the simple version with just the IP is fine.
ipAddress = response.text;
return ipAddress;
# https://api.ipify.org
IPIFY_CHECK_URL = "https://api.ipify.org";
def GetIPAddress_IPify(timeoutInSeconds, shouldShowDebugInfo):
try:
if (shouldShowDebugInfo):
print (f"Fetching from {IPIFY_CHECK_URL}")
response = requests.get(IPIFY_CHECK_URL, timeout=timeoutInSeconds);
except:
# Site wasn't there, internet is totally down, etc.
return f"Error retrieving {IPIFY_CHECK_URL}"
# Site isn't working properly, URL changed, etc.
if (response.status_code != requests.codes.ok):
return f"Error retrieving {IPIFY_CHECK_URL}, status code: {response.status_code}"
# This service supports JSON etc, but the simple version with just the IP is fine.
ipAddress = response.text;
return ipAddress;
# https://ipv4.seeip.org
SEEIP_CHECK_URL = "https://ipv4.seeip.org";
def GetIPAddress_SEEip(timeoutInSeconds, shouldShowDebugInfo):
try:
if (shouldShowDebugInfo):
print (f"Fetching from {SEEIP_CHECK_URL}")
response = requests.get(SEEIP_CHECK_URL, timeout=timeoutInSeconds);
except:
# Site wasn't there, internet is totally down, etc.
return f"Error retrieving {SEEIP_CHECK_URL}"
# Site isn't working properly, URL changed, etc.
if (response.status_code != requests.codes.ok):
return f"Error retrieving {SEEIP_CHECK_URL}, status code: {response.status_code}"
# This service supports JSON etc, but the simple version with just the IP is fine.
ipAddress = response.text;
return ipAddress;
def AddResultsAndAnyErrors(expectedIP4Address, resultString):
currentResult = resultString == expectedIP4Address;
AllResults.append(currentResult);
if (not currentResult):
ErrorMessages.append(resultString);
def CheckAllExternalIPV4Providers(expectedIP4Address, timeoutInSeconds, shouldShowDebugInfo):
startTime = time.time()
AddResultsAndAnyErrors(expectedIP4Address, GetIPAddress_IPify(timeoutInSeconds, shouldShowDebugInfo))
AddResultsAndAnyErrors(expectedIP4Address, GetIPAddress_SEEip(timeoutInSeconds, shouldShowDebugInfo))
AddResultsAndAnyErrors(expectedIP4Address, GetIPAddress_IP4OnlyDotMe(timeoutInSeconds, shouldShowDebugInfo))
AddResultsAndAnyErrors(expectedIP4Address, GetIPAddress_IPconf(timeoutInSeconds, shouldShowDebugInfo))
AddResultsAndAnyErrors(expectedIP4Address, GetIPAddress_icanhazIP(timeoutInSeconds, shouldShowDebugInfo))
endTime = time.time();
elapsedTimeInSeconds = (endTime - startTime);
# Did at least one service match our expected IP address?
atLeastOnePositiveResult = any(AllResults);
# How many services did we check?
totalServicesChecked = len(AllResults);
# How many services succeeded?
totalServicesSucceeded = AllResults.count(True);
if (shouldShowDebugInfo):
print(f"AllResults: {AllResults}")
print(f"ErrorMessages: {ErrorMessages}")
if (atLeastOnePositiveResult):
print (f'OK - External IP address appears to be {expectedIP4Address} as expected, {totalServicesSucceeded}/{totalServicesChecked} IP address services succeeded. Elapsed time: {elapsedTimeInSeconds:.2f} seconds.')
sys.exit(0)
# No matching results? Indicate failure and print out errors for debugging.
if (not atLeastOnePositiveResult):
print (f'CRITICAL - Expected {expectedIP4Address}, but none matched. Got following mismatching addresses or errors from IP Address services: {ErrorMessages}. Elapsed time: {elapsedTimeInSeconds:.2f} seconds.');
sys.exit(2);
def main():
# Build parser for arguments
parser = SetupParser();
# Exit and show help if no arguments
ExitIfNoArguments(parser);
# Parse the arguments
args = parser.parse_args(sys.argv[1:])
# Check the static IPV4
CheckAllExternalIPV4Providers(args.expectedip, args.timeout, args.debug);
if __name__ == '__main__':
main()