다른 패키지 없이, 공인 IP를 알아낼 필요가 생겼다. 요구사항은 다음과 같다.
- 다른 패키지를 사용하지 말고 python3의 기본 built-in 패키지만 사용할 것 (python3.11)
- crontab에 등록하여 사용할 것
- 여러 네트워크 인터페이스(랜카드)가 사용 가능한 상황에서 특정 네트워크 인터페이스를 사용하도록 할 것
- 두 개의 랜카드가 eth0, eth1로 인터넷에 접속 가능한 시스템에서, 특정 네트워크 인터페이스를 지정하여 public IP를 받아오는 것
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import socket | |
import ssl | |
NETWORK_TIMEOUT = 3 | |
def get_public_ip(ethernet_interface=None): | |
host = 'cloudflare.com' | |
location = '/cdn-cgi/trace' | |
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |
s.settimeout(NETWORK_TIMEOUT) | |
if ethernet_interface: | |
s.setsockopt( | |
socket.SOL_SOCKET, socket.SO_BINDTODEVICE, ethernet_interface.encode()) | |
s.connect((host, 443)) | |
s = ssl.create_default_context().wrap_socket(s, server_hostname=host) | |
request = f'GET {location} HTTP/1.1\r\nHost:{host}\r\nConnection: close\r\n\r\n'.encode() | |
sent = 0 | |
while sent < len(request): | |
sent = sent + s.send(request[sent:]) | |
response = b'' | |
while True: | |
try: | |
chunk = s.recv(4096) | |
except socket.timeout: | |
break | |
if len(chunk) == 0: | |
break | |
response += chunk | |
s.close() | |
for line in response.decode().split(): | |
if 'ip' in line: | |
return line.split('=')[1] | |
return '' | |
print(get_public_ip('eth0')) | |
print(get_public_ip('eth1')) |