使用UDP将套接字绑定到特定接口?-C
我想知道如何将套接字绑定到C中的特定接口 My@IP是X.Y.Z.3,网关是eth1上的X.Y.Z.1 但是如果我发送数据包,它将通过环回接口发送 奇怪的是,如果我使用X.Y.Z.9(例如)作为IP源(而不是我的)制作数据包,它就可以工作 有线索吗使用UDP将套接字绑定到特定接口?-C,c,sockets,C,Sockets,我想知道如何将套接字绑定到C中的特定接口 My@IP是X.Y.Z.3,网关是eth1上的X.Y.Z.1 但是如果我发送数据包,它将通过环回接口发送 奇怪的是,如果我使用X.Y.Z.9(例如)作为IP源(而不是我的)制作数据包,它就可以工作 有线索吗 #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <pthread.h> #include <sys/ioct
#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);
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义PCK_MAX_LEN 1024
#定义IP_名称服务“172.20.10.1”
#定义IP_攻击者“172.20.10.3”
#定义端口查询5555
pthread_cond_t ans_listen=pthread_cond_初始值设定项;
pthread_cond_t ans_receiv=pthread_cond_初始值设定项;
pthread\u mutex\u t mutex=pthread\u mutex\u初始值设定项;
void*fctThreadSendQuery(void*arg);//向random.example.com发送1个查询
void*fctThreadListenResponse(void*arg);//倾听对该问题的回答
内部主(空)
{
pthread\u t threadSendQuery;
pthread_t threadListenResponse;
pthread_create(&threadSendQuery,NULL,fctThreadSendQuery,NULL);
pthread_create(&threadListenResponse,NULL,fctthreadslistenresponse,NULL);
pthread_join(threadListenResponse,NULL);
pthread_join(threadSendQuery,NULL);
返回0;
}
void*fctThreadSendQuery(void*arg){
无符号整数=1;
*sin\u攻击者,*sin\u解析器中的结构sockaddr\u;
sin_攻击者=calloc(1,sizeof(struct sockaddr_in));
sin_resolver=calloc(1,sizeof(struct sockaddr_in));
sin\u攻击者->sin\u家庭=家庭;
sin\u攻击者->sin\u addr.s\u addr=inet\u addr(IP\u攻击者);
sin\u攻击者->sin\u port=htons(port\u查询);
int fd=插座(AF_INET、SOCK_RAW、IPPROTO_RAW);
绑定(fd,sin_攻击者,sizeof(struct sockaddr_in));
sin\u解析器->sin\u系列=AF\u INET;
sin\u解析器->sin\u addr.s\u addr=inet\u addr(IP\u解析器);
sin_解析器->sin_端口=htons(53);
而(1){
//现在,我们可以构建并发送查询
char*packet=calloc(PCK_MAX_LEN,sizeof(char));
int pck_len=0;
int id=0;
char*target=calloc(16,sizeof(char));
strcpy(靶标,随机靶标(nQuery-1));
构建数据包(IP_SRC、IP_DST、端口查询、53、数据包和pck长度、目标、名称长度、id、查询);
//在发送数据包之前,我们要确保fctThreadListenResponse正在侦听
pthread_mutex_lock(&mutex);
puts(“发送:等待RECV收听”);
pthread_cond_wait(&ans_listen,&mutex);
puts(“发送:等待RECV侦听-确定”);
pthread_mutex_unlock(&mutex);
sendto(fd,packet,pck_len,0,sin_攻击者,sizeof(struct sockaddr_in));
看跌期权(“发送:PCK发送”);
pthread_mutex_lock(&mutex);
puts(“发送:等待RECV到RECV”);
pthread_cond_wait(&ans_receiv,&mutex);
puts(“发送:等待RECV到RECV-确定”);
pthread_mutex_unlock(&mutex);
nQuery++;
自由(目标);
免费(包);
}
自由(sin_解析器);
免费(sin_攻击者);
pthread_exit(NULL);
}
void*fctthreadsistenresponse(void*arg){
usleep(100);
*sin\u攻击者,*sin\u解析器中的结构sockaddr\u;
sin_攻击者=calloc(1,sizeof(struct sockaddr_in));
sin_resolver=calloc(1,sizeof(struct sockaddr_in));
sin\u攻击者->sin\u家庭=家庭;
sin\u攻击者->sin\u addr.s\u addr=inet\u addr(IP\u攻击者);
sin\u攻击者->sin\u port=htons(port\u查询);
int fd=插座(AF_INET、SOCK_RAW、IPPROTO_RAW);
绑定(fd,sin_攻击者,sizeof(struct sockaddr_in));
而(1){
char*packet=calloc(PCK_MAX_LEN,sizeof(char));
无符号整数pck_len;
pthread_mutex_lock(&mutex);
pthread_cond_信号(&ans_listen);
看跌期权(“记录:倾听”);
pthread_mutex_unlock(&mutex);
pck_len=recvfrom(fd,packet,pck_MAX_len,0,NULL,sin_解析器);
看跌期权(“RECV:PCK已收到”);
如果(pck_len>0){
pthread_mutex_lock(&mutex);
pthread_cond_信号(&ans_receiv);
pthread_mutex_unlock(&mutex);
}
免费(包);
}
pthread_exit(NULL);
}
我不知道build_数据包是做什么的,但是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\U攻击者配置了sin\U攻击者(dest\u addr参数),这似乎是您自己的地址。因此,sendto会看到本地系统上承载的目标地址,并使用环回适配器发送数据包。当然,您可以使用
bind()
函数来执行此操作。你一定是通过环回接口给自己发送的,这有什么不对?我不是给自己发送的。我要把它送到网关。我尝试了一些我发现的东西(SO_BINDTODEVICE,…),但似乎没有任何效果。为什么是原始插座?如果您想使用UDP(如您所述),SOCK_DGRAM和IPPROTO_UDP可能更合适