![](/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.