[파이썬] 소켓 프로그래밍과 서비스 거부 공격과 대응 전략

소켓(Socket) 프로그래밍은 컴퓨터 네트워크를 통해 데이터를 교환하기 위한 프로세스 간 통신에 사용되는 방법입니다. 소켓은 클라이언트와 서버 간의 양방향 통신을 가능하게 하는 인터페이스입니다. 이러한 소켓 프로그래밍은 서비스 거부 공격(DoS)과 같은 공격 유형에 취약할 수 있습니다. 이 글에서는 Python을 사용한 소켓 프로그래밍과 서비스 거부 공격에 대한 대응 전략에 대해 알아보겠습니다.

소켓 프로그래밍 기초

Python에서 소켓 프로그래밍을 시작하려면 socket 모듈을 import해야 합니다. 다음은 간단한 클라이언트와 서버의 소켓 프로그래밍 예제입니다.

클라이언트 예제

import socket

# 클라이언트 소켓 생성
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 서버에 연결
server_address = ('localhost', 1234)
client_socket.connect(server_address)

# 서버에 메시지 전송
message = "Hello, server!"
client_socket.sendall(message.encode())

# 서버로부터 응답 받기
response = client_socket.recv(1024)
print("서버로부터 받은 메시지:", response.decode())

# 클라이언트 소켓 닫기
client_socket.close()

서버 예제

import socket

# 서버 소켓 생성
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 포트와 IP 주소 설정
server_address = ('localhost', 1234)
server_socket.bind(server_address)

# 클라이언트의 연결을 기다림
server_socket.listen(1)
print("클라이언트 연결 대기 중...")

# 클라이언트 요청을 받아들임
client_socket, client_address = server_socket.accept()
print("클라이언트가 연결되었습니다:", client_address)

# 클라이언트로부터 메시지 받기
message = client_socket.recv(1024)
print("클라이언트로부터 받은 메시지:", message.decode())

# 클라이언트에 응답 전송
response = "Hello, client!"
client_socket.sendall(response.encode())

# 서버 소켓 닫기
server_socket.close()

서비스 거부 공격과 대응 전략

서비스 거부 공격(DoS)은 시스템의 리소스를 고갈시켜 정상적인 서비스를 제공하지 못하게 만드는 공격입니다. 소켓 프로그래밍에서는 이러한 공격에 취약할 수 있습니다. 그러나 몇 가지 대응 전략을 통해 이러한 공격에 대비할 수 있습니다.

1. 연결 요청 제한

DoS 공격을 방지하기 위해 연결 요청을 제한할 수 있습니다. 예를 들어, 클라이언트의 IP 주소를 추적하고 연결 요청을 받기 전에 해당 IP 주소의 연결 개수를 확인하여 제한할 수 있습니다.

import socket

# 연결 제한 개수
CONNECTION_LIMIT = 10

# 서버 소켓 생성
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 포트와 IP 주소 설정
server_address = ('localhost', 1234)
server_socket.bind(server_address)

# 클라이언트의 연결을 기다림
server_socket.listen(1)
print("클라이언트 연결 대기 중...")

connection_count = 0
while True:
    # 클라이언트 요청을 받아들임
    client_socket, client_address = server_socket.accept()
    print("클라이언트가 연결되었습니다:", client_address)
  
    # 연결 개수 체크
    if connection_count >= CONNECTION_LIMIT:
        print("연결 요청을 제한합니다:", client_address)
        client_socket.close()
    else:
        connection_count += 1
        
        # 클라이언트와 통신하는 로직 수행
        
        connection_count -= 1
        client_socket.close()

2. 접속 시간 초과 설정

서버 소켓에 접속 시간 초과를 설정하여 일정 시간 내에 연결이 이루어지지 않으면 연결을 종료할 수 있습니다. 이는 일부 DoS 공격의 특징 중 하나인 연결을 맺어놓고 대기하는 행위를 방지합니다.

import socket

# 접속 시간 초과 설정 (5초)
TIMEOUT = 5

# 서버 소켓 생성
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 포트와 IP 주소 설정
server_address = ('localhost', 1234)
server_socket.bind(server_address)

# 접속 시간 초과 설정
server_socket.settimeout(TIMEOUT)

try:
    # 클라이언트의 연결을 기다림
    server_socket.listen(1)
    print("클라이언트 연결 대기 중...")
    
    # 클라이언트 요청을 받아들임
    client_socket, client_address = server_socket.accept()
    print("클라이언트가 연결되었습니다:", client_address)
    
    # 클라이언트와 통신하는 로직 수행
    
finally:
    # 서버 소켓 닫기
    server_socket.close()

3. IP 주소의 유효성 검사

서버에 들어오는 요청의 IP 주소를 검사하여 유효하지 않은 주소로부터의 연결을 차단할 수 있습니다. 이를 통해 잠재적인 DoS 공격을 막을 수 있습니다.

import socket

# 유효한 IP 주소 목록
VALID_IPS = ['192.168.0.1', '192.168.0.2']

# 서버 소켓 생성
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 포트와 IP 주소 설정
server_address = ('localhost', 1234)
server_socket.bind(server_address)

while True:
    # 클라이언트 요청을 받아들임
    client_socket, client_address = server_socket.accept()
    
    # IP 주소의 유효성 검사
    if client_address[0] not in VALID_IPS:
        print("잘못된 IP 주소:", client_address)
        client_socket.close()
        continue
      
    # 유효한 IP 주소로부터의 요청에 대해 로직 수행
    
    client_socket.close()

위의 예제들은 소켓 프로그래밍을 통해 클라이언트와 서버 간 통신을 수행하는 기본적인 방법과 DoS 공격에 대처하는 방법을 보여줍니다. 그러나 실제로 완벽한 보안은 불가능합니다. 서비스 거부 공격에 대한 대응은 다양한 요소들을 고려해야 하며, 해당 시나리오에 맞게 적용해야 합니다.