首页
学习
活动
专区
圈层
工具
发布

Winsock,仅接受来自特定IP地址的请求

Winsock 仅接受来自特定IP地址的请求

基础概念

Winsock (Windows Sockets) 是 Windows 操作系统上的网络编程接口,基于 Berkeley Sockets 实现,用于开发网络应用程序。限制仅接受特定IP地址的请求是一种常见的安全措施,可以防止未经授权的访问。

实现方法

1. 服务器端IP过滤

在服务器端代码中,可以在接受连接后检查客户端IP地址,只处理来自允许IP的请求。

代码语言:txt
复制
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>

#pragma comment(lib, "ws2_32.lib")

int main() {
    WSADATA wsaData;
    SOCKET ListenSocket, ClientSocket;
    struct sockaddr_in server, client;
    int client_len;
    char allowedIP[] = "192.168.1.100"; // 允许的IP地址
    char clientIP[INET_ADDRSTRLEN];
    
    // 初始化Winsock
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
        printf("WSAStartup failed\n");
        return 1;
    }
    
    // 创建监听套接字
    ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (ListenSocket == INVALID_SOCKET) {
        printf("socket failed\n");
        WSACleanup();
        return 1;
    }
    
    // 绑定地址和端口
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = INADDR_ANY;
    server.sin_port = htons(8080);
    
    if (bind(ListenSocket, (struct sockaddr*)&server, sizeof(server)) == SOCKET_ERROR) {
        printf("bind failed\n");
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }
    
    // 开始监听
    if (listen(ListenSocket, SOMAXCONN) == SOCKET_ERROR) {
        printf("listen failed\n");
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }
    
    printf("Server listening on port 8080...\n");
    
    while (1) {
        // 接受连接
        client_len = sizeof(client);
        ClientSocket = accept(ListenSocket, (struct sockaddr*)&client, &client_len);
        if (ClientSocket == INVALID_SOCKET) {
            printf("accept failed\n");
            continue;
        }
        
        // 获取客户端IP
        inet_ntop(AF_INET, &(client.sin_addr), clientIP, INET_ADDRSTRLEN);
        printf("Connection from: %s\n", clientIP);
        
        // 检查IP是否允许
        if (strcmp(clientIP, allowedIP) == 0) {
            printf("Allowed IP - processing request\n");
            // 处理请求...
            send(ClientSocket, "Welcome, authorized client!", 28, 0);
        } else {
            printf("Blocked IP - closing connection\n");
            send(ClientSocket, "Access denied", 13, 0);
        }
        
        closesocket(ClientSocket);
    }
    
    closesocket(ListenSocket);
    WSACleanup();
    return 0;
}

2. 使用Windows防火墙

另一种方法是通过Windows防火墙配置入站规则,只允许特定IP地址访问指定端口:

  1. 打开"高级安全Windows防火墙"
  2. 选择"入站规则" → "新建规则"
  3. 选择"端口" → 指定TCP端口
  4. 选择"允许连接"
  5. 在"作用域"选项卡中,指定远程IP地址
  6. 完成规则创建

3. 使用AcceptEx和GetAcceptExSockaddrs

对于高性能服务器,可以使用AcceptEx函数并结合GetAcceptExSockaddrs获取客户端地址:

代码语言:txt
复制
// 使用AcceptEx的示例代码片段
SOCKET AcceptSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
char lpOutputBuf[1024];
int dwReceiveDataLength = 0;
int dwLocalAddressLength = sizeof(SOCKADDR_IN) + 16;
int dwRemoteAddressLength = sizeof(SOCKADDR_IN) + 16;

if (AcceptEx(ListenSocket, AcceptSocket, lpOutputBuf, dwReceiveDataLength,
    dwLocalAddressLength, dwRemoteAddressLength, NULL, NULL)) {
    
    SOCKADDR_IN* localAddr = NULL;
    SOCKADDR_IN* remoteAddr = NULL;
    int localLen = 0, remoteLen = 0;
    
    GetAcceptExSockaddrs(lpOutputBuf, dwReceiveDataLength,
        dwLocalAddressLength, dwRemoteAddressLength,
        (LPSOCKADDR*)&localAddr, &localLen,
        (LPSOCKADDR*)&remoteAddr, &remoteLen);
    
    char clientIP[INET_ADDRSTRLEN];
    inet_ntop(AF_INET, &(remoteAddr->sin_addr), clientIP, INET_ADDRSTRLEN);
    
    // 检查IP是否允许...
}

优势

  1. 增强安全性:减少潜在攻击面
  2. 访问控制:精确控制谁可以访问服务
  3. 资源保护:避免资源被未授权用户消耗
  4. 简单实现:代码层面实现相对简单

注意事项

  1. IP地址可以被伪造,不应作为唯一的安全措施
  2. 考虑使用更安全的认证方式如TLS/SSL
  3. 对于动态IP用户,可能需要结合其他认证方式
  4. 在高性能服务器中,IP检查可能成为性能瓶颈

应用场景

  1. 内部管理系统只允许管理员IP访问
  2. 企业应用只允许合作伙伴IP访问
  3. API服务限制特定客户IP调用
  4. 游戏服务器白名单机制

通过以上方法,可以有效地实现Winsock服务仅接受来自特定IP地址的请求。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

没有搜到相关的文章

领券