使用TCP协议绑定原始套接字到地址导致进程崩溃
问题成因分析
在Windows系统上,直接创建并绑定TCP协议的原始套接字会触发错误An invalid argument was supplied. (os error 10022),核心原因是Windows对原始套接字的功能做了严格的系统级限制:
- TCP协议的原始套接字功能受限:Windows内核完全接管TCP协议的核心逻辑(如握手流程、序列号维护、流量控制等),不允许用户态程序通过
SOCK_RAW类型的套接字直接操作TCP报文。当你创建Type::RAW+Protocol::TCP的套接字时,这类套接字仅能用于被动接收TCP数据包,无法执行绑定(bind)或主动发送数据的操作,强行调用就会返回无效参数错误。 - 绑定操作不符合Windows套接字规则:对于TCP协议,常规场景使用的是
SOCK_STREAM类型套接字;而SOCK_RAW类型套接字在Windows上仅支持ICMP、UDP等少数协议的主动操作,TCP不在此允许范围内,绑定操作本身对于TCP原始套接字就是非法参数。 - 安全机制限制:即使以管理员权限运行程序,Windows也禁止用户态程序通过原始套接字发送TCP报文——这是为了防止绕过TCP栈的安全校验,避免恶意构造报文破坏网络秩序。
问题复现代码
use socket2::{Domain, Protocol, SockAddr, Socket, Type}; use std::{env, net::SocketAddr, process::{Command, Stdio}, thread, time::Duration, io::{BufReader, BufRead}}; fn main() -> std::io::Result<()> { let mut args: Vec<String> = std::env::args().collect(); args.remove(0); if args.len() == 0 { let file_path = env::current_exe().unwrap(); let file_path = file_path.to_str().unwrap(); let (command, cmd_args) = ( "powershell.exe", vec![ String::from("-NoProfile"), String::from("-NoExit"), String::from("-Command"), String::from("Start-Process"), String::from(file_path), String::from("-Verb"), String::from("RunAs"), String::from("-ArgumentList"), String::from("'bind'"), ], ); let mut cmd = Command::new(command) .args(cmd_args) .stderr(Stdio::piped()) .spawn() .unwrap(); let err = cmd.stderr.take().unwrap(); let reader = BufReader::new(err); for line in reader.lines() { println!("{}", line.unwrap()); } println!("DONE"); } else { thread::sleep(Duration::from_secs(5)); let address = SockAddr::from(SocketAddr::new([0, 0, 0, 0].into(), 0)); let send_socket = Socket::new(Domain::IPV4, Type::RAW, Some(Protocol::TCP))?; send_socket.bind(&address)?; loop {} } Ok(()) }
内容的提问来源于stack exchange,提问作者NaN
相关产品推荐
相关产品推荐

