![](/img/trans.png)
[英]Linux: Bind UDP listening socket to specific interface (or find out the interface a datagram came in from)?
[英]Bind a socket to a specific interface with UDP? - C
我想知道如何将套接字绑定到C中的特定接口。
我的@IP是XYZ3,网关是eth1上的XYZ1,但是如果我发送数据包,它将在回送接口上发送。
奇怪的是,如果我使用XYZ9(例如)作为IP源(而不是我的IP)来制作数据包,则它可以工作。
有什么线索吗?
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <string.h>
#include <netdb.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/time.h>
#define PCK_MAX_LEN 1024
#define IP_NAMESERV "172.20.10.1"
#define IP_ATTACKER "172.20.10.3"
#define PORT_QUERY 5555
pthread_cond_t ans_listen = PTHREAD_COND_INITIALIZER;
pthread_cond_t ans_receiv = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *fctThreadSendQuery (void *arg); // Send 1 query to random.example.com
void *fctThreadListenResponse (void *arg); // Listen for response to that query
int main (void)
{
pthread_t threadSendQuery;
pthread_t threadListenResponse;
pthread_create (&threadSendQuery, NULL, fctThreadSendQuery, NULL);
pthread_create (&threadListenResponse, NULL, fctThreadListenResponse, NULL);
pthread_join (threadListenResponse, NULL);
pthread_join (threadSendQuery, NULL);
return 0;
}
void *fctThreadSendQuery(void *arg) {
unsigned int nQuery = 1;
struct sockaddr_in *sin_attacker, *sin_resolver;
sin_attacker = calloc(1, sizeof(struct sockaddr_in));
sin_resolver = calloc(1, sizeof(struct sockaddr_in));
sin_attacker->sin_family = AF_INET;
sin_attacker->sin_addr.s_addr = inet_addr(IP_ATTACKER);
sin_attacker->sin_port = htons(PORT_QUERY);
int fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
bind(fd, sin_attacker, sizeof(struct sockaddr_in));
sin_resolver->sin_family = AF_INET;
sin_resolver->sin_addr.s_addr = inet_addr(IP_RESOLVER);
sin_resolver->sin_port = htons(53);
while (1) {
// Now, we can build and send the query
char *packet = calloc(PCK_MAX_LEN, sizeof(char));
int pck_len = 0;
int id = 0;
char *target = calloc(16, sizeof(char));
strcpy(target, randomTarget(nQuery-1));
build_packet(IP_SRC, IP_DST, PORT_QUERY, 53, packet, &pck_len, target, NAME_LEN, id, QUERY);
// Before sending the packet, we want to be sure that fctThreadListenResponse is listening
pthread_mutex_lock (&mutex);
puts("SEND: wait for RECV to LISTEN");
pthread_cond_wait (&ans_listen, &mutex);
puts("SEND: wait for RECV to LISTEN - OK");
pthread_mutex_unlock(&mutex);
sendto (fd, packet, pck_len, 0, sin_attacker, sizeof(struct sockaddr_in));
puts("SEND: PCK SENT");
pthread_mutex_lock (&mutex);
puts("SEND: wait for RECV to RECV");
pthread_cond_wait (&ans_receiv, &mutex);
puts("SEND: wait for RECV to RECV - OK");
pthread_mutex_unlock(&mutex);
nQuery++;
free(target);
free(packet);
}
free(sin_resolver);
free(sin_attacker);
pthread_exit(NULL);
}
void *fctThreadListenResponse (void *arg) {
usleep(100);
struct sockaddr_in *sin_attacker, *sin_resolver;
sin_attacker = calloc(1, sizeof(struct sockaddr_in));
sin_resolver = calloc(1, sizeof(struct sockaddr_in));
sin_attacker->sin_family = AF_INET;
sin_attacker->sin_addr.s_addr = inet_addr(IP_ATTACKER);
sin_attacker->sin_port = htons(PORT_QUERY);
int fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
bind(fd, sin_attacker, sizeof(struct sockaddr_in));
while (1) {
char *packet = calloc(PCK_MAX_LEN, sizeof(char));
unsigned int pck_len;
pthread_mutex_lock (&mutex);
pthread_cond_signal (&ans_listen);
puts("RECV: LISTENING");
pthread_mutex_unlock(&mutex);
pck_len = recvfrom(fd, packet, PCK_MAX_LEN, 0, NULL, sin_resolver);
puts("RECV: PCK RECEIVED");
if (pck_len > 0) {
pthread_mutex_lock (&mutex);
pthread_cond_signal (&ans_receiv);
pthread_mutex_unlock (&mutex);
}
free(packet);
}
pthread_exit(NULL);
}
我不知道build_packet是做什么的,但是sendto的文档仅列出了一些可能的原型,其中只有一个具有要使用的参数列表:
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);
在通话中,您可以使用:
sendto (fd, packet, pck_len, 0, sin_attacker, sizeof(struct sockaddr_in));
使用IP_ATTACKER(似乎是您自己的地址)配置了sin_attacker(dest_addr参数)的位置。 因此sendto可以看到托管在本地系统上的目标地址,并使用回送适配器发送数据包。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.