원시 소켓을 특정 인터페이스에 바인딩하는 방법
제 애플리케이션은 CentOS 5.5에서 실행되고 있습니다.원시 소켓을 사용하여 데이터를 보내고 있습니다.
sd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
if (sd < 0) {
// Error
}
const int opt_on = 1;
rc = setsockopt(m_SocketDescriptor, IPPROTO_IP, IP_HDRINCL, &opt_on, sizeof(opt_on));
if (rc < 0) {
close(sd);
// Error
}
struct sockaddr_in sin;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = my_ip_address;
if (sendto(m_SocketDescriptor, DataBuffer, (size_t)TotalSize, 0, (struct sockaddr *)&sin, sizeof(struct sockaddr)) < 0) {
close(sd);
// Error
}
이 소켓을 특정 네트워크 인터페이스(예: eth1)에 바인딩하려면 어떻게 해야 합니까?
const char *opt;
opt = "eth0";
const len = strnlen(opt, IFNAMSIZ);
if (len == IFNAMSIZ) {
fprintf(stderr, "Too long iface name");
return 1;
}
setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, opt, len);
첫번째 줄: 변수 설정
두 번째 줄: 바인딩할 인터페이스를 프로그램에 지정합니다.
3-5행: 인터페이스 이름의 길이를 구하고 크기가 너무 크지 않은지 확인합니다.
6라인: 소켓의 소켓 옵션 설정sd
, 장치에 바인딩opt
.
setsockopt 프로토타입:
int setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen);
또한, 당신은 다음을 포함해야 합니다.if.h
,socket.h
그리고.string.h
머리글 파일
앞서 언급한 바와 같이, 올바른 작업은struct ifreq
인터페이스 이름을 지정합니다.여기 제 코드 샘플이 있습니다.
#define SERVERPORT 5555
...
struct ifreq ifr;
/* Create the socket */
sd = socket(AF_INET, SOCK_STREAM, 0);
if (sd < 0)
{
printf("Error in socket() creation - %s", strerror(errno));
}
/* Bind to eth1 interface only - this is a private VLAN */
memset(&ifr, 0, sizeof(ifr));
snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "eth1");
if ((rc = setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr))) < 0)
{
perror("Server-setsockopt() error for SO_BINDTODEVICE");
printf("%s\n", strerror(errno));
close(sd);
exit(-1);
}
/* bind to an address */
memset(&serveraddr, 0x00, sizeof(struct sockaddr_in));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(SERVERPORT);
serveraddr.sin_addr.s_addr = inet_addr("9.1.2.3");
int rc = bind(sd, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
또한 보안적인 관점에서 소켓을 인터페이스에 바인딩하는 것은 좋지만 사용하는 것은 말이 안 된다는 점도 덧붙이고 싶습니다.INADDR_ANY
수신 IP 주소로서.이렇게 하면 모든 네트워크 인터페이스의 netstat에서 포트가 열려 있는 것으로 나타납니다.
Proto Recv-Q Send-Q Local Address Foreign Address State User Inode PID/Program name
tcp 0 0 0.0.0.0:5555 0.0.0.0:* LISTEN 0 210898 26996/myserver
대신 사용 중인 인터페이스에 특정한 IP 주소(전용 VLAN)를 지정했습니다.이것은 netstat 출력도 고쳤습니다.
Proto Recv-Q Send-Q Local Address Foreign Address State User Inode PID/Program name
tcp 0 0 9.1.2.3:5555 0.0.0.0:* LISTEN 0 210898 26996/myserver
소켓을 특정 인터페이스 IP 주소에 바인딩
int bind_using_iface_ip(int fd, char *ipaddr, uint16_t port)
{
struct sockaddr_in localaddr = {0};
localaddr.sin_family = AF_INET;
localaddr.sin_port = htons(port);
localaddr.sin_addr.s_addr = inet_addr(ipaddr);
return bind(fd, (struct sockaddr*) &localaddr, sizeof(struct sockaddr_in));
}
소켓을 특정 인터페이스 이름에 바인딩
int bind_using_iface_name(int fd, char *iface_name)
{
return setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, iface_name, strlen(iface_name))
}
인bind_using_iface_ip
, 어떤 항구에도 묶다0
통과되어야 합니다.그리고 만약에.fd
raw socket 그러면 포트를 통과해야 합니다.0
. 이 바인딩 메커니즘은 raw, dgram 및 stream과 같은 모든 종류의 소켓에 대해 일반적입니다.
언급URL : https://stackoverflow.com/questions/3998569/how-to-bind-raw-socket-to-specific-interface
'programing' 카테고리의 다른 글
heroku에서 db를 다운로드하려면 어떻게 해야 합니까? (0) | 2023.09.11 |
---|---|
폼 제어를 비활성화하되 값은 유지하는 방법 (0) | 2023.09.11 |
키 스트로크로 잠시 루프를 죽이는 방법? (0) | 2023.09.11 |
워드프레스에서 댓글 ID에서 게시물 ID를 얻을 수 있습니까? (0) | 2023.09.11 |
libxml/tree.h 해당 파일 또는 디렉토리가 없습니다. (0) | 2023.09.11 |