IP協定

IP(網際協定)是一種無連線協定,用於在第三層定義源和目標主機,並透過路由選擇最快的路徑。以下是一個使用Python解析IPv4頭的範例:

import struct

def parse_ipv4_header(packet):
    # 假設packet是一個二進位資料封套件,套件含IPv4頭
    ipv4_header = packet[14:34]  # IPv4頭從乙太網路頭後開始
    
    version_ihl, dscp_ecn, total_length, identification, flags_fragment_offset, \
    ttl, protocol, header_checksum, source_ip, destination_ip = struct.unpack('!BBHHHBBH4s4s', ipv4_header)
    
    version = version_ihl >> 4
    ihl = version_ihl & 0xF
    
    source_ip = '.'.join(str(ord(c)) for c in source_ip)
    destination_ip = '.'.join(str(ord(c)) for c in destination_ip)
    
    print(f"Version: {version}")
    print(f"IHL: {ihl}")
    print(f"DSCP: {(dscp_ecn >> 2) & 0x3F}")
    print(f"ECN: {dscp_ecn & 0x3}")
    print(f"Total Length: {total_length}")
    print(f"Identification: {identification}")
    print(f"Flags: {(flags_fragment_offset >> 13) & 0x7}")
    print(f"Fragment Offset: {flags_fragment_offset & 0x1FFF}")
    print(f"TTL: {ttl}")
    print(f"Protocol: {protocol}")
    print(f"Header Checksum: {hex(header_checksum)}")
    print(f"Source IP: {source_ip}")
    print(f"Destination IP: {destination_ip}")

# 範例資料封套件
sample_packet = b'\xaa\xbb\xcc\xdd\xee\xff\x00\x11\x22\x33\x44\x55\x08\x00' \
                b'\x45\x00\x00\x3c\x1c\x46\x40\x00\x40\x06\xa2\xb7\xc0\xa8\x01\x02\xc0\xa8\x01\x03'
parse_ipv4_header(sample_packet)

這個指令碼使用struct函式庫來解析IPv4頭,提取版本、IHL(Internet Header Length)、DSCP(DiffServ Code Point)、ECN(Explicit Congestion Notification)、總長度、識別碼、標誌、片偏移、TTL(Time-to-Live)、協定、頭部校驗和、源IP位元址和目標IP位元址。

IP Addressing

IPv4地址由四個八位元組成,每個八位元組可以從0到255。以下是一個使用Python計算IPv4網路地址的範例:

import ipaddress

def calculate_network_address(ip_address, netmask):
    network = ipaddress.ip_network(f"{ip_address}/{netmask}", strict=False)
    print(f"Network Address: {network.network_address}")
    print(f"Broadcast Address: {network.broadcast_address}")

calculate_network_address("192.168.1.2", "255.255.255.0")

這個指令碼使用ipaddress函式庫來計算IPv4網路地址和廣播地址。IPv4地址和子網路遮罩透過二進位元AND操作來計算網路起始地址。

透過這些範例,我們不僅能夠理解乙太網路頭、VLAN和ARP協定的運作方式,還能掌握IPv4協定的基本概念。從乙太網路頭到IP Addressing,理解這些技術不僅能夠提升我們的防禦能力,還能讓我們在這個不斷變化的數位世界中保持警覺。希望這篇文章能夠幫助大家更好地理解和應對網路安全挑戰。

IP Addressing與TCP協定:從子網計算到三次握手

在前面的文章中,我們探討了乙太網路頭、VLAN和ARP協定的運作方式。本文將繼續介紹IP Addressing的計算方法以及TCP協定的詳細結構和運作機制,幫助大家更好地理解網路的基本概念。

IP Addressing

IPv4地址由四個八位元組成,每個八位元組可以從0到255。以下是一個使用Python計算IPv4網路地址的範例:

import ipaddress

def calculate_network_address(ip_address, netmask):
    network = ipaddress.ip_network(f"{ip_address}/{netmask}", strict=False)
    print(f"Network Address: {network.network_address}")
    print(f"Broadcast Address: {network.broadcast_address}")

calculate_network_address("192.168.1.2", "255.255.255.0")

這個指令碼使用ipaddress函式庫來計算IPv4網路地址和廣播地址。IPv4地址和子網路遮罩透過二進位元AND操作來計算網路起始地址。

子網計算

子網路遮罩定義了IP位元址中用於網路和主機的位數。在我們的範例中,前24位元是1,這相當於/24,稱為CIDR塊。如果最後一個八位元組完全可用於主機,則該網路被分類別為C類別網路;兩個八位元組構成B類別網路,三個八位元組構成A類別網路,否則稱為子網。以下是一個使用Python進行子網計算的範例:

import ipaddress

def calculate_subnet(ip_address, netmask):
    network = ipaddress.ip_network(f"{ip_address}/{netmask}", strict=False)
    print(f"Network Address: {network.network_address}")
    print(f"Broadcast Address: {network.broadcast_address}")
    print(f"Subnet Mask: {network.netmask}")
    print(f"Number of Hosts: {network.num_addresses - 2}")  # 減去網路地址和廣播地址

calculate_subnet("192.168.1.2", "255.255.255.0")

這個指令碼使用ipaddress函式庫來計運算元網的詳細資訊,套件括網路地址、廣播地址、子網路遮罩和可用的主機數量。

路由決策

當一台主機想要與另一台主機通訊時,它會先計算目標的網路起始地址。如果目標在另一個網路中,資料封包將被傳送到預設閘道器,否則會查詢路由表並透過指定的裝置或下一個路由器傳送資料封包。以下是一個使用Python模擬路由決策的範例:

import ipaddress

def route_decision(source_ip, source_netmask, destination_ip):
    source_network = ipaddress.ip_network(f"{source_ip}/{source_netmask}", strict=False)
    destination_ip = ipaddress.ip_address(destination_ip)
    
    if destination_ip in source_network:
        print("Destination is in the same network, sending directly")
    else:
        print("Destination is in another network, sending to default gateway")

route_decision("192.168.1.2", "255.255.255.0", "192.168.1.3")
route_decision("192.168.1.2", "255.255.255.0", "192.168.2.3")

這個指令碼使用ipaddress函式庫來檢查目標IP是否在源IP的同一網路中。如果是,則直接傳送;否則,傳送到預設閘道器。

ICMP協定

ICMP(網際控制訊息協定)用於IP的錯誤處理。它在頭部設定型別和程式碼欄位來定義錯誤。以下是一個使用Python解析ICMP頭的範例:

import struct

def parse_icmp_header(packet):
    # 假設packet是一個二進位資料封套件,套件含ICMP頭
    icmp_header = packet[14+20:]  # ICMP頭從IPv4頭後開始
    
    icmp_type, icmp_code, checksum = struct.unpack('!BBH', icmp_header[:4])
    
    print(f"ICMP Type: {icmp_type}")
    print(f"ICMP Code: {icmp_code}")
    print(f"Checksum: {hex(checksum)}")

# 範例資料封套件
sample_packet = b'\xaa\xbb\xcc\xdd\xee\xff\x00\x11\x22\x33\x44\x55\x08\x00' \
                b'\x45\x00\x00\x3c\x1c\x46\x40\x00\x40\x01\xa2\xb7\xc0\xa8\x01\x02\xc0\xa8\x01\x03' \
                b'\x08\x00\x00\x00'
parse_icmp_header(sample_packet)

這個指令碼使用struct函式庫來解析ICMP頭,提取ICMP型別、程式碼和校驗和。ICMP協定最著名的應用程式是ping程式,它傳送ICMP echo-request資料封包並希望收到echo-response來測試主機是否可達並測量網路延遲。

ICMP類別型與程式碼

以下是一些常見的ICMP類別型與程式碼及其在Python中的實作:

def icmp_type_code_to_name(icmp_type, icmp_code):
    icmp_types = {
        0: {"0": "Echo-reply"},
        3: {
            "0": "Net-unreachable",
            "1": "Host-unreachable",
            "2": "Protocol-unreachable",
            "3": "Port-unreachable",
            "4": "Fragmentation-needed",
            "5": "Source-route-failed",
            "6": "Dest-network-unknown",
            "7": "Dest-port-unknown",
            "8": "Source-host-isolated",
            "9": "Network-admin",
            "10": "Host-admin",
            "11": "Network-service",
            "12": "Host-service",
            "13": "Com-admin-prohibited",
            "14": "Host-precedence-violation",
            "15": "Precedence-cuttof-in-effect"
        },
        4: {"0": "Source-quench"},
        5: {
            "0": "Redirect-network",
            "1": "Redirect-host",
            "2": "Redirect-service-network",
            "3": "Redirect-service-host"
        },
        6: {"0": "Alternate-host-address"},
        8: {"0": "Echo-request"},
        9: {"0": "Router-advertisement"},
        10: {"0": "Router-selection"},
        11: {
            "0": "ttl-exceeded",
            "1": "Fragment-reassembly-exceeded"
        },
        12: {
            "0": "Pointer-error",
            "1": "Missing-option",
            "2": "Bad-length"
        },
        13: {"0": "Timestamp-request"},
        14: {"0": "Timestamp-reply"},
        15: {"0": "Info-request"},
        16: {"0": "Info-reply"},
        17: {"0": "Mask-request"},
        18: {"0": "Mask-reply"},
        30: {
            "0": "Traceroute-forwarded",
            "1": "Packet-discarded"
        },
        31: {"0": "Datagram-conversion-error"},
        32: {"0": "Mobile-host-redirect"},
        33: {"0": "ipv6-where-are-you"},
        34: {"0": "ipv6-here-I-am"},
        35: {"0": "Mobile-registration-request"},
        36: {"0": "Mobile-registration-reply"},
        37: {"0": "Domain-name-request"},
        38: {"0": "Domain-name-reply"},
        40: {
            "0": "Bad-spi",
            "1": "Authentication-failed",
            "2": "Decompression-failed",
            "3": "Decryption-failed",
            "4": "Need-authentication",
            "5": "Need-authorization"
        }
    }
    
    if icmp_type in icmp_types and str(icmp_code) in icmp_types[icmp_type]:
        return icmp_types[icmp_type][str(icmp_code)]
    else:
        return f"Unknown ICMP Type/Code: {icmp_type}/{icmp_code}"

print(icmp_type_code_to_name(8, 0))  # Echo-request
print(icmp_type_code_to_name(3, 3))  # Port-unreachable

這個指令碼定義了一個字典,套件含了常見的ICMP型別和程式碼及其對應的名稱。透過這個字典,我們可以輕鬆地將ICMP型別和程式碼變形為其名稱。

TCP協定

TCP(傳輸控制協定)提供了工作階段管理功能。新的TCP工作階段透過著名的三次握手(Three-Way-Handshake)初始化。以下是一個使用Python模擬TCP三次握手的範例:

import scapy.all as scapy

def tcp_three_way_handshake(source_ip, destination_ip, source_port, destination_port):
    # SYN
    syn_packet = scapy.IP(src=source_ip, dst=destination_ip)/scapy.TCP(sport=source_port, dport=destination_port, flags="S", seq=1000)
    syn_ack_packet = scapy.sr1(syn_packet, timeout=1, verbose=False)
    
    if syn_ack_packet:
        # SYN-ACK
        syn_ack_seq = syn_ack_packet[TCP].seq
        syn_ack_ack = syn_ack_packet[TCP].ack
        
        # ACK
        ack_packet = scapy.IP(src=source_ip, dst=destination_ip)/scapy.TCP(sport=source_port, dport=destination_port, flags="A", seq=syn_ack_ack, ack=syn_ack_seq+1)
        scapy.send(ack_packet, verbose=False)
        
        print("TCP Three-Way Handshake completed successfully")
    else:
        print("TCP Three-Way Handshake failed")

tcp_three_way_handshake("192.168.1.2", "192.168.1.3", 1234, 80)

這個指令碼使用Scapy函式庫來模擬TCP三次握手過程。首先傳送SYN資料封套件,然後等待SYN-ACK回應,最後傳送ACK資料封包完成握手。

TCP頭結構

TCP頭包含了許多重要欄位,如連線埠、標誌、序列號、確認號和視窗大小。以下是一個使用Python解析TCP頭的範例:

import struct

def parse_tcp_header(packet):
    # 假設packet是一個二進位資料封套件,套件含TCP頭
    tcp_header = packet[14+20:]  # TCP頭從IPv4頭後開始
    
    source_port, destination_port, sequence_number, acknowledgment_number, \
    offset_reserved_flags = struct.unpack('!HHIIH', tcp_header[:14])
    
    offset = (offset_reserved_flags >> 12) * 4
    flags = offset_reserved_flags & 0x3F
    
    window_size, checksum, urgent_pointer = struct.unpack('!HHH', tcp_header[14:20])
    
    print(f"Source Port: {source_port}")
    print(f"Destination Port: {destination_port}")
    print(f"Sequence Number: {sequence_number}")
    print(f"Acknowledgment Number: {acknowledgment_number}")
    print(f"Offset: {offset}")
    print(f"Flags: {bin(flags)}")
    print(f"Window Size: {window_size}")
    print(f"Checksum: {hex(checksum)}")
    print(f"Urgent Pointer: {urgent_pointer}")

# 範例資料封套件
sample_packet = b'\xaa\xbb\xcc\xdd\xee\xff\x00\x11\x22\x33\x44\x55\x08\x00' \
                b'\x45\x00\x00\x3c\x1c\x46\x40\x00\x40\x06\xa2\xb7\xc0\xa8\x01\x02\xc0\xa8\x01\x03' \
                b'\x04\xd2\x00\x50\x00\x00\x00\x00\x50\x02\x20\x00\xa7\xe7\x00\x00'
parse_tcp_header(sample_packet)

這個指令碼使用struct函式庫來解析TCP頭,提取源連線埠、目標連線埠、序列號、確認號、偏移量、標誌、視窗大小、校驗和與緊急指標。

TCP標誌

TCP標誌用於工作階段管理,以建立或銷毀連線,並指示目標以更高優先順序處理資料封套件。以下是一些常見的TCP標誌及其功能:

def tcp_flags_to_function(flag):
    tcp_flags = {
        'SYN': 'Ask for a new connection',
        'ACK': 'Acknowledge the receipt of a packet',
        'RST': 'Cancel a connection attempt (is usually send when a host tries to connect to a closed port)',
        'FIN': 'Cleanly close an established connection (must be acknowledged by the counterpart)',
        'URG': 'Mark a packet as urgent',
        'PSH': 'Bid the receiver to handle packet with higher priority'
    }
    
    return tcp_flags.get(flag, f"Unknown TCP flag: {flag}")

print(tcp_flags_to_function('SYN'))  # Ask for a new connection
print(tcp_flags_to_function('ACK'))  # Acknowledge the receipt of a packet

這個指令碼定義了一個字典,套件含了常見的TCP標誌及其功能。透過這個字典,我們可以輕鬆地將TCP標誌變形為其功能描述。

序欄號與確認號

序列號用於將接收到的資料封套件排序為與源系統傳送時相同的順序,並檢測丟失的資料封套件。每個資料封套件都有一個獨立的序列號,每傳輸一個位元組就增加一個。確認號用於確認對方已正確接收到具有特定序列號的資料封套件。它使用序列號並加一,表格示下一個預期的序列號。以下是一個使用Python模擬序欄號與確認號互動的範例:

def simulate_sequence_and_acknowledgment():
    sequence_number = 1000
    acknowledgment_number = sequence_number + 1
    
    print(f"Initial Sequence Number: {sequence_number}")
    
    # 傳送第一個資料封套件
    print(f"Sending packet with Sequence Number: {sequence_number}")
    
    # 接收方確認
    print(f"Acknowledgment Number received: {acknowledgment_number}")
    
    # 傳送第二個資料封套件
    sequence_number += len("Hello, World!")
    print(f"Sending packet with Sequence Number: {sequence_number}")
    
    # 接收方確認
    acknowledgment_number = sequence_number + 1
    print(f"Acknowledgment Number received: {acknowledgment_number}")

simulate_sequence_and_acknowledgment()

這個指令碼模擬了序欄號與確認號的互動過程。首先設定初始序列號,然後模擬傳送資料封包和接收確認號的過程。

視窗大小

視窗大小定義了作業系統快取中已接收但尚未處理的資料封包的大小。如果視窗大小為零,表格示傳送站點正處於壓力之下,要求對方友好地減慢或甚至停止傳送更多資料封套件,直到收到更大的視窗大小。以下是一個使用Python模擬視窗大小的範例:

def simulate_window_size():
    window_size = 1024
    
    print(f"Initial Window Size: {window_size}")
    
    # 模擬接收到大量資料封套件
    window_size = 0
    print(f"Window Size after receiving many packets: {window_size}")
    
    # 模擬傳送方收到零視窗大小後停止傳送
    print("Sender stops sending packets due to zero window size")
    
    # 模擬接收方處理完資料封包後還原視窗大小
    window_size = 2048
    print(f"Window Size after processing packets: {window_size}")
    
    # 模擬傳送方繼續傳送資料封套件
    print("Sender resumes sending packets")

simulate_window_size()

這個指令碼模擬了視窗大小的變化過程。當視窗大小變為零時,傳送方會停止傳送資料封套件,直到接收方處理完資料封包並還原視窗大小。

透過這些範例,我們不僅能夠理解IP Addressing的計算方法和TCP協定的詳細結構,還能掌握其運作機制。從子網計算到三次握手,理解這些技術不僅能夠提升我們的防禦能力,還能讓我們在這個不斷變化的數位世界中保持警覺。希望這篇文章能夠幫助大家更好地理解和應對網路安全挑戰。

在前面的文章中,我們探討了IP Addressing的計算方法以及TCP協定的詳細結構。本文將繼續介紹TCP連線的建立過程、UDP協定的運作方式,以及一個實際的網路範例,幫助大家更好地理解網路的基本概念。

TCP連線的建立:三次握手

TCP連線的建立過程被稱為三次握手(Three-Way-Handshake)。以下是一個使用Python模擬TCP三次握手的範例:

import scapy.all as scapy

def tcp_three_way_handshake(source_ip, destination_ip, source_port, destination_port):
    # SYN
    syn_packet = scapy.IP(src=source_ip, dst=destination_ip)/scapy.TCP(sport=source_port, dport=destination_port, flags="S", seq=1000)
    syn_ack_packet = scapy.sr1(syn_packet, timeout=1, verbose=False)
    
    if syn_ack_packet:
        # SYN-ACK
        syn_ack_seq = syn_ack_packet[TCP].seq
        syn_ack_ack = syn_ack_packet[TCP].ack
        
        # ACK
        ack_packet = scapy.IP(src=source_ip, dst=destination_ip)/scapy.TCP(sport=source_port, dport=destination_port, flags="A", seq=syn_ack_ack, ack=syn_ack_seq+1)
        scapy.send(ack_packet, verbose=False)
        
        print("TCP Three-Way Handshake completed successfully")
    else:
        print("TCP Three-Way Handshake failed")

tcp_three_way_handshake("192.168.1.2", "192.168.1.3", 1234, 80)

這個指令碼使用Scapy函式庫來模擬TCP三次握手過程。首先,傳送方傳送一個帶有SYN標誌的資料封套件,並設定初始序列號為1000。初始序列號必須盡可能隨機,以避免盲目IP偽造攻擊。接著,接收方回應一個帶有SYN和ACK標誌的資料封套件,設定初始序列號為5000,並將確認號設定為傳送方的序列號加一(1001)。最後,傳送方傳送一個帶有ACK標誌(但不帶SYN)的資料封套件,使用SYN/ACK資料封套件的確認號作為序列號,並將前一個資料封套件的序列號加一作為確認號。這就完成了三次握手。

關閉連線:RST標誌

當資料封包到達一個關閉的連線埠時,目標主機必須傳送一個RST資料封包以符合RFC793標準。這表示請求無效。以下是一個使用Python模擬RST資料封包的範例:

import scapy.all as scapy

def send_rst_packet(source_ip, destination_ip, source_port, destination_port):
    rst_packet = scapy.IP(src=source_ip, dst=destination_ip)/scapy.TCP(sport=source_port, dport=destination_port, flags="R", seq=1000)
    scapy.send(rst_packet, verbose=False)
    print("RST packet sent")

send_rst_packet("192.168.1.2", "192.168.1.3", 1234, 80)

這個指令碼使用Scapy函式庫來傳送一個RST資料封套件,表格示連線請求無效。許多現代防火牆違反了這個標準,透過靜默丟棄資料封包或生成虛假的ICMP訊息。這種行為對攻擊者來説是有用的,因為它可以幫助他們確定防火牆的廠商甚至版本,這是攻擊時寶貴的資訊。

UDP協定

UDP(使用者資料報協定)是傳輸層的一種協定,但與TCP不同,它不支援工作階段管理,因此被分類別為無狀態協定。它也不關心資料封包丟失或順序,只實作透過連線埠對程式進欄 Addressing。以下是一個使用Python解析UDP頭的範例:

import struct

def parse_udp_header(packet):
    # 假設packet是一個二進位資料封套件,套件含UDP頭
    udp_header = packet[14+20:]  # UDP頭從IPv4頭後開始
    
    source_port, destination_port, length, checksum = struct.unpack('!HHHH', udp_header)
    
    print(f"Source Port: {source_port}")
    print(f"Destination Port: {destination_port}")
    print(f"Length: {length}")
    print(f"Checksum: {hex(checksum)}")

# 範例資料封套件
sample_packet = b'\xaa\xbb\xcc\xdd\xee\xff\x00\x11\x22\x33\x44\x55\x08\x00' \
                b'\x45\x00\x00\x3c\x1c\x46\x40\x00\x40\x11\xa2\xb7\xc0\xa8\x01\x02\xc0\xa8\x01\x03' \
                b'\x04\xd2\x00\x35\x00\x28\x9f\x7e'
parse_udp_header(sample_packet)

這個指令碼使用struct函式庫來解析UDP頭,提取源連線埠、目標連線埠、長度和校驗和。UDP遵循“發射後不管”的原則,主要用於串流媒體服務,如網路廣播或電視,但也是DNS最常用的傳輸協定。UDP頭的大小較小,因此傳輸速度更快。

實際網路範例

一個典型的乙太網/TCP/IP網路是我們現在想到的網路,因為它是最常見的。它由五層而不是理論上的七層組成。以下是一個使用Python展示HTTP資料封包如何透過這些層的範例:

import scapy.all as scapy

def http_packet_layers():
    # 應用程式層(Layer 7)
    http_header = "GET / HTTP/1.1\r\nHost: www.springer.com\r\n\r\n"
    
    # 傳輸層(Layer 4-6)
    tcp_header = scapy.TCP(sport=1234, dport=80, flags="S", seq=1000)
    
    # 網路層(Layer 3)
    ip_header = scapy.IP(src="192.168.1.2", dst="62.50.45.35")
    
    # 資料鏈路層(Layer 2)
    ethernet_header = scapy.Ether(src="00:11:22:33:44:55", dst="ff:ff:ff:ff:ff:ff")
    
    # 構建完整資料封套件
    packet = ethernet_header/ip_header/tcp_header/http_header
    
    print("HTTP Packet Layers:")
    print(f"Layer 7 (Application): {http_header}")
    print(f"Layer 4-6 (Transport): {tcp_header.summary()}")
    print(f"Layer 3 (Network): {ip_header.summary()}")
    print(f"Layer 2 (Data Link): {ethernet_header.summary()}")

http_packet_layers()

這個指令碼使用Scapy函式庫來構建一個HTTP請求資料封套件,並展示其透過各層的過程。首先,應用程式層解析URL www.springer.com,並構建HTTP頭。接著,傳輸層透過三次握手建立連線,使用目標連線埠80(HTTP)和隨機源連線埠。網路層識別到不能直接使用www.springer.com,因此進欄DNS查詢以解析主機名的IP位元址。在這個範例中,目標IP位元址是62.50.45.35。網路層檢查目標主機是否在同一網路中,如果不在,則查詢路由表並使用預設閘道器傳送資料封包。最後,資料鏈路層透過ARP解析目標IP位元址的MAC位元址,並將源MAC位元址寫入頭部,然後將資料封包轉發到物理層,由網路卡驅動程式將其變形為二進位資料並傳輸。

網路架構

從客戶端的角度來看,網路可以有兩種邏輯結構:客戶端/伺服器或對等(P2P)。

客戶端/伺服器架構

客戶端/伺服器架構(例如HTTP)由一台實作一個或多個服務的電腦(伺服器)和另一台使用服務的電腦(客戶端)組成。以下是一個使用Python模擬客戶端/伺服器互動的範例:

import requests

def client_server_interaction(url):
    try:
        response = requests.get(url)
        print(f"Request sent to: {url}")
        print(f"Response received: Status Code {response.status_code}")
        print(f"Response Content: {response.text[:100]}...")  # 只顯示前100個字元
    except requests.RequestException as e:
        print(f"Error during client/server interaction: {e}")

client_server_interaction("http://www.springer.com")

這個指令碼使用requests函式庫來模擬客戶端/伺服器互動過程。客戶端傳送請求,伺服器如果喜歡請求的格式並認為客戶端有權提出請求,則會回應。

對等(P2P)架構

對等架構允許每個參與者既是客戶端又是伺服器。以下是一個使用Python模擬P2P互動的簡單範例:

import socket

def p2p_interaction(host_ip, host_port):
    # 建立一個通訊端
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
    try:
        # 連線到另一個對等節點
        sock.connect((host_ip, host_port))
        print(f"Connected to peer at {host_ip}:{host_port}")
        
        # 傳送訊息
        message = "Hello from peer!"
        sock.sendall(message.encode())
        print(f"Message sent: {message}")
        
        # 接收回應
        response = sock.recv(1024).decode()
        print(f"Response received: {response}")
    except socket.error as e:
        print(f"Error during P2P interaction: {e}")
    finally:
        sock.close()

p2p_interaction("192.168.1.3", 8888)

這個指令碼使用socket函式庫來模擬P2P互動過程。每個參與者都可以傳送和接收訊息,形成一個去中心化的網路。

透過這些範例,我們不僅能夠理解TCP連線的建立過程和UDP協定的運作方式,還能掌握實際網路範例中的各層互動以及不同的網路架構。從三次握手到P2P互動,理解這些技術不僅能夠提升我們的防禦能力,還能讓我們在這個不斷變化的數位世界中保持警覺。希望這篇文章能夠幫助大家更好地理解和應對網路安全挑戰。