Ruby UDP:发送数据包时如何伪造IP地址与端口号?
Great question! The short answer is yes, you can forge the source IP address and port in UDP packets—but it requires working at a lower level than standard UDP sockets, and comes with important caveats around permissions, network behavior, and legality. Let’s break this down:
1. Why UDP Makes Forging Possible
UDP is a connectionless protocol, so unlike TCP, there’s no handshake to validate the source address. You can manually construct the entire IP and UDP headers, including the source IP/port, instead of relying on the OS to populate these fields automatically.
2. How to Implement It
To forge source details, you need to use raw sockets instead of standard UDP sockets. Raw sockets let you craft custom IP and transport layer headers. Here’s how it works across major OSes:
Linux/macOS
You’ll need root privileges to create a raw socket. Enable the IP_HDRINCL option to tell the OS you’re providing your own IP header, then manually populate the IP and UDP header fields.
Here’s a minimal C example:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <netinet/ip.h> #include <netinet/udp.h> #include <arpa/inet.h> // Helper function to calculate IP/UDP checksums unsigned short checksum(unsigned short *buf, int nwords) { unsigned long sum = 0; for (; nwords > 0; nwords--) sum += *buf++; sum = (sum >> 16) + (sum & 0xffff); sum += (sum >> 16); return (unsigned short)(~sum); } int main() { // Create raw socket for UDP int sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_UDP); if (sockfd < 0) { perror("Failed to create raw socket (need root?)"); exit(EXIT_FAILURE); } // Tell OS we'll handle IP header construction int optval = 1; setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, &optval, sizeof(optval)); char buffer[4096]; memset(buffer, 0, sizeof(buffer)); // Pointers to IP header, UDP header, and payload struct iphdr *ip = (struct iphdr *)buffer; struct udphdr *udp = (struct udphdr *)(buffer + sizeof(struct iphdr)); char *data = buffer + sizeof(struct iphdr) + sizeof(struct udphdr); strcpy(data, "Forged UDP test packet"); // Populate IP header ip->ihl = 5; ip->version = 4; ip->tos = 0; ip->tot_len = htons(sizeof(struct iphdr) + sizeof(struct udphdr) + strlen(data)); ip->id = htons(12345); ip->frag_off = 0; ip->ttl = 64; ip->protocol = IPPROTO_UDP; ip->check = 0; // Calculated later ip->saddr = inet_addr("192.168.1.100"); // Forged source IP ip->daddr = inet_addr("192.168.1.200"); // Target IP // Populate UDP header udp->source = htons(54321); // Forged source port udp->dest = htons(12345); // Target port udp->len = htons(sizeof(struct udphdr) + strlen(data)); udp->check = 0; // Optional: some systems skip UDP checksum validation // Calculate IP checksum ip->check = checksum((unsigned short *)buffer, ip->tot_len >> 1); // Send the forged packet struct sockaddr_in dest_addr; memset(&dest_addr, 0, sizeof(dest_addr)); dest_addr.sin_family = AF_INET; dest_addr.sin_addr.s_addr = ip->daddr; if (sendto(sockfd, buffer, ntohs(ip->tot_len), 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr)) < 0) { perror("Failed to send packet"); exit(EXIT_FAILURE); } close(sockfd); printf("Forged UDP packet sent!\n"); return 0; }
Compile with gcc fake_udp.c -o fake_udp, then run with sudo ./fake_udp (root is required).
Windows
Similar to Linux, you need administrator rights. Windows restricts raw sockets slightly (e.g., TCP forging is blocked), but UDP is allowed. You’ll use socket(AF_INET, SOCK_RAW, IPPROTO_UDP) and manually build headers, just like on Unix-like systems. Note that some Windows versions may require registry tweaks to enable full raw socket access.
3. Critical Caveats
- Permissions: You must run your program as root (Linux/macOS) or Administrator (Windows)—standard user accounts don’t have access to raw sockets.
- Network Filters: Many routers and firewalls use Reverse Path Forwarding (RPF) to drop packets with source IPs that don’t match the expected incoming interface. Your forged packet might never reach the target.
- Reply Handling: If the target server sends a response, it will be sent to the forged source IP/port—not your actual client. Unless you control that IP/port (which you probably don’t), you’ll never receive the reply.
- Legality/Ethics: Forging source IPs can be used for malicious purposes (e.g., DDoS attacks, spoofing). Make sure you’re only doing this in a controlled, authorized environment (like your own test network) and comply with local laws.
4. Alternatives If You Don’t Want Raw Sockets
If you just need to test how a server handles unexpected source addresses, tools like hping3 (Linux) or Nmap can send forged UDP packets without writing code. But if you need to integrate this into your own application, raw sockets are the way to go.
内容的提问来源于stack exchange,提问作者Nick Shears

