Post

TCP/UDP

TCP/UDP

TCP/UDP Protocol Security: Analysis of Vulnerabilities and Attack Techniques

Introduction

TCP and UDP protocols, which form the foundation of Internet communications, each have unique security characteristics and vulnerabilities. This article analyzes the security mechanisms of both protocols and examines key attack techniques and defense strategies. Understanding how TCP’s connection-oriented nature and UDP’s connectionless design create different security issues is particularly important.

TCP Protocol and Security

Basic Security Mechanisms of TCP

TCP (Transmission Control Protocol) was designed to provide reliable, connection-oriented communication. Its key security features include:

  1. 3-way handshake: Performs bidirectional verification during connection establishment.
  2. Sequence numbers: Assigns unique sequence numbers to each segment, enabling accurate order and transmission verification.
  3. State management: Tracks connection states to detect abnormal packets.

However, these mechanisms do not guarantee perfect security.

TCP Connection States and TCB

TCP connections are stored in a data structure called TCB (Transmission Control Block). A TCB includes:

  • Source/destination IP addresses and ports
  • Sequence and acknowledgment numbers
  • Window size
  • Timer information
  • Connection state information

Each TCP connection consumes server memory resources, making this a potential attack target.

Detailed Analysis of TCP Handshake Process

Connection Establishment (3-way Handshake)

  1. Client → Server: Sends SYN packet
    1
    
    SYN=1, seq=x
    
    • Client transitions to SYN_SENT state
    • Initial sequence number (ISN) x is randomly selected
  2. Server → Client: Responds with SYN-ACK packet
    1
    
    SYN=1, ACK=1, seq=y, ack=x+1
    
    • Server transitions to SYN_RECEIVED state
    • Server also selects its own ISN y
  3. Client → Server: Sends ACK packet
    1
    
    ACK=1, seq=x+1, ack=y+1
    
    • Both sides transition to ESTABLISHED state
    • Data transmission begins

Connection Termination (4-way Handshake)

  1. Terminator → Receiver: FIN packet
  2. Receiver → Terminator: ACK packet
  3. Receiver → Terminator: FIN packet
  4. Terminator → Receiver: ACK packet

TCP Vulnerabilities and Attack Techniques

1. SYN Flooding Attack

SYN Flooding is a DoS attack that exploits TCP’s 3-way handshake process.

Attack Mechanism:

  1. Attacker sends a large number of SYN packets with spoofed source IPs to the server
  2. Server responds with SYN-ACK for each packet and stores the connection state (half-open) in its backlog queue
  3. No ACK returns because the spoofed IPs either don’t exist or don’t respond
  4. Server’s backlog queue becomes saturated, preventing legitimate connection requests

Key Characteristics:

  • Consumes memory and connection table resources rather than CPU resources
  • Relatively effective with few packets due to limited backlog queue size (typically 128-256)
  • Occupies server resources until timeout (typically 30-120 seconds)

Detection Method:

1
netstat -tna | grep SYN_RECEIVED

A large number of connections in SYN_RECEIVED state may indicate an attack.

2. TCP RST Attack

The RST (Reset) attack forcibly terminates existing TCP connections. In the TCP protocol, the RST flag was designed as a mechanism to immediately terminate connections in abnormal situations, but this can be exploited.

Detailed Attack Mechanism:

  1. The attacker spoofs the source IP/port of an active connection.
  2. They determine the current connection’s sequence number range (through sniffing or prediction).
  3. They send an RST packet with a valid sequence number.
    • According to TCP specifications, if the RST packet’s sequence number falls within the receiver’s window range, it will be accepted.
    • Modern OSes perform stricter validation, but attack possibilities still exist.
  4. The receiving side recognizes this as a normal connection termination signal and immediately closes the session.
  5. Both endpoints experience an error indicating that the connection was suddenly terminated.

Attack Methods and Technical Details:

  1. Blind RST Attack: When the exact sequence number is unknown, an attacker can brute-force by sending RST packets across all possible sequence number ranges.
  2. ACK Number Manipulation: Some implementations also check the ACK number, so a valid ACK value might be required.
  3. Window Size Exploitation: The larger the target system’s window size, the wider the valid sequence number range, increasing the probability of successful attacks.
  4. Man-in-the-Middle (MITM) Position: If positioned in the network path where packets can be observed, obtaining accurate sequence numbers becomes easier.

Common Use Cases and Real Attack Examples:

  • Censorship and Communication Blocking: Used by nation-state censorship systems like China’s Great Firewall to terminate TCP connections when sensitive keywords are detected
  • Persistent Service Disruption:
    • Interrupting YouTube, Netflix, or other streaming services
    • Forcing disconnection in online games
    • Terminating video conferences or VoIP calls
  • Secure Communication Blocking: Disrupting SSH, VPN, or TOR encrypted communication sessions
  • Data Leak Prevention: Blocking specific types of external communications in corporate networks
  • Comcast Case (2007): U.S. ISP Comcast was found to be injecting RST packets to limit BitTorrent traffic, revealed through FCC investigation

Detection Methods:

1
2
3
4
5
# Monitor TCP RST packets
tcpdump -nn "tcp[tcpflags] & tcp-rst != 0"

# Analyze RST packets for specific connections
wireshark -Y "tcp.flags.reset == 1 && ip.addr == target_ip"

3. TCP Session Hijacking

Session hijacking involves predicting/sniffing sequence numbers to intervene in normal connections.

Attack Stages:

  1. Identify and monitor target TCP session
  2. Block legitimate client’s ACK packets (via DoS attack, etc.)
  3. Insert forged packets with predicted sequence numbers
  4. Hijack session and intervene in communication

TCP Security Enhancement Methods

1. SYN Cookies

Instead of immediately creating a TCB when receiving a SYN packet, the server generates a special sequence number (cookie):

1
ISN = hash(src IP, src port, dst IP, dst port, secret key, timestamp)

After sending SYN-ACK, the server only creates a TCB if the client’s ACK contains the correct number. This stateless approach defends against backlog queue depletion attacks.

2. Backlog Queue Management and Timeout Adjustment

1
2
3
4
5
6
7
8
# Increase backlog queue size on Linux systems
sysctl -w net.ipv4.tcp_max_syn_backlog=4096

# Limit SYN retransmissions
sysctl -w net.ipv4.tcp_synack_retries=2

# Enable SYN cookies
sysctl -w net.ipv4.tcp_syncookies=1

3. TCP Sequence Number Randomization

Modern operating systems use cryptographically secure random number generators to determine ISNs.

UDP Protocol and Security

Basic Characteristics of UDP

UDP (User Datagram Protocol) is a simple, connectionless protocol with the following characteristics:

  1. Header simplicity: Uses only 8-byte header (source/destination ports, length, checksum)
  2. Connectionless: No handshake process
  3. Stateless: No state information maintained between packets
  4. No reliability mechanisms: No retransmission, sequence guarantees, or flow control

These characteristics are advantageous for performance but create vulnerabilities from a security perspective.

UDP Vulnerabilities and Attack Techniques

1. UDP Amplification Attack

UDP amplification attacks exploit protocols that generate large responses from small requests.

Attack Mechanism:

  1. Attacker sends small requests with the victim’s spoofed IP to reflection servers (DNS, etc.)
  2. Reflection servers send much larger responses to the victim
  3. Bandwidth consumption according to amplification ratio (BAF: Bandwidth Amplification Factor)

Major Amplification Protocols and Ratios:

ProtocolPortMax AmplificationExploited Query/Command
DNS5328-54xANY query
NTP123556.9xMONLIST command
SSDP190030xM-SEARCH
Memcached1121151,000xSTATS command
CharGEN19358.8xRandom characters

Real Attack Cases:

  • 2018 GitHub attack of 1.35 Tbps (using Memcached)
  • 2016 Dyn DNS service attack causing major internet service disruptions

2. UDP Flood Attack

Attack Mechanism:

  1. Send large volumes of UDP packets to various ports
  2. Target system generates “ICMP Destination Unreachable” messages for each closed port
  3. System resource consumption and network bandwidth saturation

3. Protocol-Specific UDP Attacks

DNS-Related Attacks:

  • DNS Cache Poisoning: Manipulate cache with forged DNS responses
  • DNS Tunneling: Covert data transmission through DNS queries/responses

SNMP Attacks:

  • Exposure of community strings in SNMPv1/v2c
  • Massive information collection and configuration changes

VoIP/SIP Attacks:

  • Call interception and eavesdropping
  • Registration hijacking
  • Denial of service attacks

UDP Security Enhancement Methods

1. Reflection Attack Defense

Implement BCP 38 (Network Ingress Filtering):

  • Filter incorrect source IPs at network boundaries
  • Block packets with source IPs not from your network block

Apply uRPF (unicast Reverse Path Forwarding):

1
2
interface GigabitEthernet0/0
 ip verify unicast source reachable-via rx

2. Response Rate Limiting

Implement DNS Response Rate Limiting (RRL):

1
2
3
4
5
6
options {
    rate-limit {
        responses-per-second 5;
        window 5;
    };
};

3. Protocol-Specific Security Enhancements

DNS:

  • Implement DNSSEC
  • Limit recursive queries
  • Restrict response size

NTP:

1
2
3
restrict default kod nomodify notrap nopeer noquery
restrict -6 default kod nomodify notrap nopeer noquery
disable monitor  # Disable monlist command

SNMP:

  • Use SNMPv3 (supports authentication and encryption)
  • Use strong community strings
  • Restrict to read-only access

TCP and UDP Security Comparison

Security AspectTCPUDP
Authentication Mechanism3-way handshake, sequence numbersNo built-in mechanisms
Spoofing DifficultyRelatively difficultVery easy
Major Attack TypesSYN Flooding, RST attacks, session hijackingAmplification DDoS, UDP Flood
Resource ConsumptionState information stored per connectionIndependent packet processing
Encryption IntegrationCombined with TLS (HTTPS)Requires DTLS
Defense ApproachState management optimizationTraffic filtering, rate limiting

Security Best Practices

1. Network Perimeter Security

1
2
3
4
5
6
7
# TCP SYN packet rate limiting using iptables
iptables -A INPUT -p tcp --syn -m limit --limit 1/s --limit-burst 3 -j ACCEPT
iptables -A INPUT -p tcp --syn -j DROP

# UDP traffic limitation
iptables -A INPUT -p udp -m limit --limit 10/s -j ACCEPT
iptables -A INPUT -p udp -j DROP

2. Monitoring and Alerting

1
2
3
4
5
6
7
# TCP SYN connection state monitoring script
#!/bin/bash
THRESHOLD=100
COUNT=$(netstat -tna | grep SYN_RECEIVED | wc -l)
if [ $COUNT -gt $THRESHOLD ]; then
    echo "WARNING: Possible SYN flood attack. $COUNT SYN_RECEIVED connections detected." | mail -s "SYN Flood Alert" admin@example.com
fi

3. Defense-in-Depth Strategy

  • Implement appropriate load balancing
  • Application layer filtering
  • Detect and block abnormal traffic patterns
  • Regular security audits and configuration reviews

References


TCP/UDP 프로토콜 보안: 취약점과 공격 기법 분석

서론

인터넷 통신의 근간이 되는 TCP와 UDP 프로토콜은 각각 고유한 보안 특성과 취약점을 가지고 있습니다. 이 글에서는 두 프로토콜의 보안 메커니즘을 분석하고, 주요 공격 기법과 방어 전략을 살펴보겠습니다. 특히 TCP의 연결 지향적 특성과 UDP의 비연결성이 어떻게 다른 보안 이슈를 만들어내는지 이해하는 것이 중요합니다.

TCP 프로토콜과 보안

TCP의 기본 보안 메커니즘

TCP(Transmission Control Protocol)는 신뢰성 있는 연결 지향적 통신을 제공하기 위해 설계되었습니다. 주요 보안 특성은 다음과 같습니다:

  1. 3-way 핸드셰이크: 연결 수립 과정에서 양방향 검증을 수행합니다.
  2. 시퀀스 번호: 각 세그먼트에 고유한 시퀀스 번호를 할당하여 정확한 순서와 전송 검증을 가능하게 합니다.
  3. 상태 관리: 연결의 상태를 추적하여 비정상적인 패킷을 감지할 수 있습니다.

그러나 이러한 메커니즘들이 완벽한 보안을 보장하지는 않습니다.

TCP 연결 상태와 TCB

TCP 연결은 TCB(Transmission Control Block)라는 데이터 구조에 저장됩니다. TCB는 다음 정보를 포함합니다:

  • 소스/목적지 IP 주소 및 포트
  • 시퀀스 번호와 확인 응답 번호
  • 윈도우 크기
  • 타이머 정보
  • 연결 상태 정보

각 TCP 연결은 서버 메모리의 자원을 소비하므로, 이는 잠재적인 공격 대상이 됩니다.

TCP 핸드셰이크 과정 상세 분석

연결 수립 (3-way Handshake)

  1. 클라이언트 → 서버: SYN 패킷 전송
    1
    
    SYN=1, seq=x
    
    • 클라이언트는 SYN_SENT 상태로 전환
    • 초기 시퀀스 번호(ISN) x는 무작위로 선택됨
  2. 서버 → 클라이언트: SYN-ACK 패킷 응답
    1
    
    SYN=1, ACK=1, seq=y, ack=x+1
    
    • 서버는 SYN_RECEIVED 상태로 전환
    • 서버도 자신의 ISN y를 선택
  3. 클라이언트 → 서버: ACK 패킷 전송
    1
    
    ACK=1, seq=x+1, ack=y+1
    
    • 양측 모두 ESTABLISHED 상태로 전환
    • 데이터 전송 시작

연결 종료 (4-way Handshake)

  1. 종료 요청자 → 수신자: FIN 패킷
  2. 수신자 → 종료 요청자: ACK 패킷
  3. 수신자 → 종료 요청자: FIN 패킷
  4. 종료 요청자 → 수신자: ACK 패킷

TCP 취약점과 공격 기법

1. SYN Flooding 공격

SYN Flooding은 TCP의 3-way 핸드셰이크 과정을 악용한 DoS 공격입니다.

공격 메커니즘:

  1. 공격자는 위조된(spoofed) 소스 IP로 대량의 SYN 패킷을 서버에 전송
  2. 서버는 각 SYN에 대해 SYN-ACK로 응답하고 연결 상태(half-open)를 백로그 큐에 저장
  3. 위조된 IP는 존재하지 않거나 응답하지 않으므로 ACK가 돌아오지 않음
  4. 서버의 백로그 큐가 포화 상태가 되어 정상 연결 요청 처리 불가

주요 특징:

  • CPU 자원보다는 메모리와 연결 테이블 자원을 소진시키는 공격
  • 백로그 큐 크기가 제한적(보통 128~256개)이라 비교적 적은 패킷으로도 효과적
  • 타임아웃(보통 30-120초)까지 서버 자원 점유

탐지 방법:

1
netstat -tna | grep SYN_RECEIVED

대량의 SYN_RECEIVED 상태 연결은 공격 징후일 수 있습니다.

2. TCP RST 공격

RST(Reset) 공격은 기존 TCP 연결을 강제로 종료시키는 공격입니다. TCP 프로토콜에서 RST 플래그는 비정상적인 상황에서 연결을 즉시 종료하기 위한 메커니즘으로 설계되었으나, 이를 악용할 수 있습니다.

공격 메커니즘 상세:

  1. 공격자는 활성 연결의 소스 IP/포트를 스푸핑합니다.
  2. 현재 연결의 시퀀스 번호 범위를 파악합니다(스니핑 또는 추측).
  3. 유효한 시퀀스 번호를 가진 RST 패킷을 전송합니다.
    • TCP 명세에 따르면, RST 패킷의 시퀀스 번호가 수신자의 윈도우 범위 내에 있으면 수락됩니다.
    • 최신 OS는 더 엄격한 검증을 수행하지만, 여전히 공격 가능성이 존재합니다.
  4. 수신 측은 이를 정상적인 연결 종료 신호로 인식하고 즉시 세션을 종료합니다.
  5. 양쪽 엔드포인트 모두 연결이 갑자기 끊겼다는 오류를 경험하게 됩니다.

공격 방법 및 기술적 세부사항:

  1. 블라인드 RST 공격: 정확한 시퀀스 번호를 모를 경우, 공격자는 가능한 모든 시퀀스 번호 범위에 대해 RST 패킷을 브루트포스 방식으로 전송할 수 있습니다.
  2. ACK 번호 조작: 일부 구현에서는 ACK 번호도 확인하므로, 유효한 ACK 값도 필요할 수 있습니다.
  3. 윈도우 크기 활용: 대상 시스템의 윈도우 크기가 클수록 유효한 시퀀스 번호 범위가 넓어져 공격 성공 확률이 높아집니다.
  4. 중간자(MITM) 위치 활용: 네트워크 경로 상에서 패킷을 관찰할 수 있는 위치에 있다면, 정확한 시퀀스 번호를 얻기 더 쉽습니다.

주요 사용 사례 및 실제 공격 예시:

  • 검열 및 통신 차단: 중국의 Great Firewall과 같은 국가 단위 검열 시스템에서 민감한 키워드가 감지된 TCP 연결을 차단하기 위해 사용
  • 지속적 서비스 방해:
    • 유튜브, 넷플릭스 등 스트리밍 서비스 시청 방해
    • 온라인 게임 연결 강제 종료로 게임플레이 방해
    • 화상 회의나 VoIP 통화 중단
  • 보안 통신 차단: SSH, VPN, TOR 등 암호화된 통신 세션 차단
  • 정보 유출 방지: 기업 네트워크에서 특정 유형의 외부 통신 차단
  • Comcast 사례(2007): 미국 ISP인 Comcast가 BitTorrent 트래픽을 제한하기 위해 RST 패킷을 삽입한 사례가 FCC 조사로 밝혀짐

탐지 방법:

1
2
3
4
5
# TCP RST 패킷 모니터링
tcpdump -nn "tcp[tcpflags] & tcp-rst != 0"

# 특정 연결에 대한 RST 패킷 분석
wireshark -Y "tcp.flags.reset == 1 && ip.addr == target_ip"

3. TCP 세션 하이재킹

세션 하이재킹은 시퀀스 번호를 예측/스니핑하여 정상 연결에 개입하는 공격입니다.

공격 단계:

  1. 공격 대상 TCP 세션 식별 및 모니터링
  2. 합법적인 클라이언트의 ACK 패킷 차단(DoS 공격 등으로)
  3. 예측된 시퀀스 번호로 위조 패킷 삽입
  4. 세션 탈취 및 통신 개입

TCP 보안 강화 방법

1. SYN 쿠키 (SYN Cookies)

서버는 SYN 패킷 접수 시 즉시 TCB를 생성하지 않고, 특별한 시퀀스 번호(쿠키)를 생성합니다:

1
ISN = hash(src IP, src port, dst IP, dst port, secret key, timestamp)

SYN-ACK를 보낸 후, 클라이언트의 ACK가 올바른 번호를 가질 경우에만 TCB를 생성합니다. 이는 상태 비저장(stateless) 방식으로 백로그 큐 소진 공격을 방어합니다.

2. 백로그 큐 관리 및 타임아웃 조정

1
2
3
4
5
6
7
8
# Linux 시스템의 백로그 큐 크기 증가
sysctl -w net.ipv4.tcp_max_syn_backlog=4096

# SYN 재전송 횟수 제한
sysctl -w net.ipv4.tcp_synack_retries=2

# SYN 쿠키 활성화
sysctl -w net.ipv4.tcp_syncookies=1

3. TCP 시퀀스 번호 무작위화

현대 운영체제는 암호학적으로 안전한 난수 생성기를 사용하여 ISN을 결정합니다.

UDP 프로토콜과 보안

UDP의 기본 특성

UDP(User Datagram Protocol)는 단순하고 비연결성 프로토콜로, 다음과 같은 특징을 가집니다:

  1. 헤더 단순성: 8바이트 헤더만 사용 (소스/목적지 포트, 길이, 체크섬)
  2. 비연결성: 핸드셰이크 과정 없음
  3. 상태 비저장: 패킷 간 상태 정보 유지 안 함
  4. 신뢰성 메커니즘 없음: 재전송, 순서 보장, 흐름제어 없음

이러한 특성은 성능 면에서 유리하지만 보안 측면에서는 취약점을 만듭니다.

UDP 취약점과 공격 기법

1. UDP 증폭 공격 (Amplification Attack)

UDP 증폭 공격은 소량의 요청으로 대량의 응답을 생성하는 프로토콜의 특성을 악용합니다.

공격 메커니즘:

  1. 공격자는 피해자의 IP로 위조된 소규모 요청을 반사 서버(DNS 등)에 전송
  2. 반사 서버는 훨씬 큰 응답을 피해자에게 전송
  3. 증폭 비율(BAF: Bandwidth Amplification Factor)에 따라 대역폭 소모

주요 증폭 프로토콜 및 증폭 비율:

프로토콜포트최대 증폭 비율악용 쿼리/명령
DNS5328-54배ANY 쿼리
NTP123556.9배MONLIST 명령
SSDP190030배M-SEARCH
Memcached1121151,000배STATS 명령
CharGEN19358.8배임의 문자

실제 공격 사례:

  • 2018년 GitHub 대상 1.35 Tbps DDoS 공격(Memcached 이용)
  • 2016년 Dyn DNS 서비스 대상 공격으로 대규모 인터넷 서비스 중단

2. UDP Flood 공격

공격 메커니즘:

  1. 대량의 UDP 패킷을 다양한 포트로 전송
  2. 대상 시스템이 각 닫힌 포트에 대해 “ICMP Destination Unreachable” 메시지 생성
  3. 시스템 리소스 소모 및 네트워크 대역폭 포화

3. 프로토콜별 UDP 공격

DNS 관련 공격:

  • DNS 캐시 포이즈닝: 위조된 DNS 응답으로 캐시 조작
  • DNS 터널링: DNS 쿼리/응답을 통한 은밀한 데이터 전송

SNMP 공격:

  • SNMPv1/v2c의 community string 노출
  • 대량의 정보 수집 및 구성 변경 가능

VoIP/SIP 공격:

  • 통화 가로채기 및 도청
  • 등록 하이재킹
  • 서비스 거부 공격

UDP 보안 강화 방법

1. 반사 공격 방어

BCP 38 (Network Ingress Filtering) 구현:

  • 네트워크 경계에서 잘못된 소스 IP를 필터링
  • 자신의 네트워크 블록이 아닌 소스 IP 패킷 차단

uRPF(unicast Reverse Path Forwarding) 적용:

1
2
interface GigabitEthernet0/0
 ip verify unicast source reachable-via rx

2. 응답 속도 제한

DNS Response Rate Limiting (RRL) 구현:

1
2
3
4
5
6
options {
    rate-limit {
        responses-per-second 5;
        window 5;
    };
};

3. 프로토콜별 보안 강화

DNS:

  • DNSSEC 구현
  • 재귀 쿼리 제한
  • 응답 크기 제한

NTP:

1
2
3
restrict default kod nomodify notrap nopeer noquery
restrict -6 default kod nomodify notrap nopeer noquery
disable monitor  # monlist 명령 비활성화

SNMP:

  • SNMPv3 사용 (인증 및 암호화 지원)
  • 강력한 community string 사용
  • 읽기 전용 접근으로 제한

TCP와 UDP 보안 비교

보안 측면TCPUDP
인증 메커니즘3-way 핸드셰이크, 시퀀스 번호내장 메커니즘 없음
스푸핑 난이도상대적으로 어려움매우 용이함
주요 공격 유형SYN Flooding, RST 공격, 세션 하이재킹증폭 DDoS, UDP Flood
리소스 소모연결당 상태 정보 저장패킷별 독립 처리
암호화 통합TLS와 결합 (HTTPS)DTLS 필요
방어 접근법상태 관리 최적화트래픽 필터링, 속도 제한

보안 모범 사례

1. 네트워크 경계 보안

1
2
3
4
5
6
7
# iptables를 이용한 TCP SYN 패킷 속도 제한
iptables -A INPUT -p tcp --syn -m limit --limit 1/s --limit-burst 3 -j ACCEPT
iptables -A INPUT -p tcp --syn -j DROP

# UDP 트래픽 제한
iptables -A INPUT -p udp -m limit --limit 10/s -j ACCEPT
iptables -A INPUT -p udp -j DROP

2. 모니터링 및 알림

1
2
3
4
5
6
7
# TCP SYN 연결 상태 모니터링 스크립트
#!/bin/bash
THRESHOLD=100
COUNT=$(netstat -tna | grep SYN_RECEIVED | wc -l)
if [ $COUNT -gt $THRESHOLD ]; then
    echo "WARNING: Possible SYN flood attack. $COUNT SYN_RECEIVED connections detected." | mail -s "SYN Flood Alert" admin@example.com
fi

3. 심층 방어 전략

  • 적절한 부하 분산 구현
  • 애플리케이션 계층 필터링
  • 비정상 트래픽 패턴 탐지 및 차단
  • 정기적인 보안 감사 및 구성 검토

참고 자료

This post is licensed under CC BY 4.0 by the author.