2016-09-22 4 views
0

C에서 간단한 서버/클라이언트 프로그램을 작성하고 있습니다. 어디서나 액세스 할 수있는 IP 포트를 열려고합니다. 현재, 내 서버는 127.0.0.1 (로컬 시스템)과 0.0.0.0 (잘 모르겠다) 이외에는 작동하지 않습니다. IP_TRANSPARENT 옵션을 지정했는데 클라이언트를 제외하고 모두 여전히 connect에서 실패합니다.외부 IP에 connect()가 작동하지 않습니다.

서버 :

// definitions, everything 
struct addrinfo hints, *res; 

hints.ai_family = AF_INET; 
hints.ai_socktype = SOCK_STREAM; 

getaddrinfo("192.168.1.1","4001",&hints,&res); 

sockfd = socket(res->ai_family,res->ai_socktype,res->ai_protocol); 

setsockopt(sockfd,IPPROTO_IP,IP_TRANSPARENT,(void*)&sockopt,sizeof(sockopt)); 

bind(sockfd,res->ai_addr,res->ai_addrlen); 
listen(sockfd,0); 

addr_size = sizeof(ext_addr); 
extfd = accept(sockfd,(struct sockaddr *)&ext_addr,&addr_size); 

write(extfd,"Success",7); 
// cleanup 

클라이언트 :

// definitions, everything 
struct sockaddr_in serv_addr; 

sockfd = socket(AF_INET,SOCK_STREAM,0); 
setsockopt(sockfd,IPPROTO_IP,IP_TRANSPARENT,(void*)&sockopt,sizeof(sockopt)); 

serv_addr.sin_family = AF_INET; 
serv_addr.sin_port = htons(4001); 

inet_pton(AF_INET,"192.168.1.1",&serv_addr.sin_addr); 

connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)); // fails here 
read(sockfd,rcvBuf,sizeof(rcvBuf)-1); 

// clean up 

내 문제가 무엇

? 나는 편의를 위해 오류 검사를 꺼냈다. 서버가 정상적으로 실행됩니다. 클라이언트는 127.0.0.1로 정상적으로 실행됩니다.

+0

서버의 IP 주소는 192.168.1.1입니까? – immibis

답변

3

일반적으로 로컬 컴퓨터에 속하지 않는 IP에 대해서는 bind() 수 없습니다. 그러나, IP_TRANSPARENT 문서 당 :

IP_TRANSPARENT
(리눅스 2.6.24 이후)이 부울 옵션 설정이 소켓에 투명 프록시를 할 수 있습니다. 이 소켓 옵션을 사용하면 호출 응용 프로그램이 로컬이 아닌 IP 주소에 바인드하여 외부 주소가 로컬 끝점 인 클라이언트와 서버로 모두 작동 할 수 있습니다. 참고 : 이는 외부 주소로가는 패킷이 TProxy 상자 (즉, IP_TRANSPARENT 소켓 옵션을 사용하는 응용 프로그램을 호스팅하는 시스템)을 통해 라우팅되는 방식으로 라우팅을 설정해야합니다. 이 소켓 옵션을 사용하려면 수퍼 유저 권한 (CAP_NET_ADMIN 기능)이 필요합니다.

iptables TPROXY 대상을 사용하는 TProxy 리디렉션도이 옵션을 리디렉션 된 소켓에서 설정해야합니다.

IP_TRANSPARENT을 용이하게하기 위해 네트워크에서 필요한 프록시를 구성 했습니까?

잠시 동안 IP_TRANSPARENT을 무시하고 일반적으로 사용되지 않았으므로 존재하지 않는 척하십시오.

127.0.0.1은 IPv4 루프백 주소입니다. 서버를 여기에 바인딩하면 127.0.0.1에 연결하는 로컬 IPv4 클라이언트 만 연결할 수 있습니다.

0.0.0.0은 IPv4 와일드 카드 주소입니다. 서버를이 소켓에 바인딩하면 소켓은 모든 로컬 IPv4 주소에서 수신 대기합니다. 로컬 시스템이나 네트워크의 모든 클라이언트는 서버 시스템에 속한 모든 IPv4 주소에 연결할 수 있습니다.

192.168.1.1은 특정 IPv4 주소입니다. 이 서버를 바인딩하면 소켓은 해당 IPv4 주소에서만 수신 대기합니다. 로컬 시스템이나 네트워크의 클라이언트는 해당 IPv4 주소에만 연결할 수 있습니다.

클라이언트와 서버가 동일한 시스템에 있으면 클라이언트는 서버가 바인드 된 모든 로컬 IP에 연결할 수 있습니다.

클라이언트와 서버가 동일한 시스템에 있지 않은 경우 동일한 네트워크에 bur가 있고 서버가 해당 네트워크에 액세스 할 수있는 IP에 바인딩되어 있으면 클라이언트가 서버에 연결할 수 있습니다. 즉, 0.0.0.0 또는 192.168.1.1에 바인딩 한 다음 192.168.1.1에 연결하는 것입니다.

클라이언트와 서버가 동일한 네트워크에 있지 않은 경우 클라이언트는 서버가 공용 IP가있는 라우터 뒤에있을 경우에만 서버에 연결할 수 있습니다. 서버는 라우터에 액세스 할 수있는 로컬 네트워크 IP에 바인딩되어야하며 공용 IP의 주어진 포트에서 서버의 내부 IP로 인바운드 연결을 전달하도록 라우터를 구성해야합니다. 이는 서버를 0.0.0.0 또는 192.168.1.1으로 바인딩하고 서버의 내부 IP에 연결을 전달한 다음 라우터의 공용 IP에 연결한다는 의미입니다.

+0

'0.0.0.0'에 바인드 한 다음 같은 머신에서'192.168.1.1'에 연결할 수 있습니까? 작동하는 것처럼 보이지 않기 때문입니다. –

+0

@MDXF 만약'192.168.1.1'이 로컬 머신에 속한다면 네, 로컬 클라이언트가 로컬 서버가 '0.0.0.0'에 바인드 될 때 로컬 클라이언트가 연결할 수 있어야합니다. –

+0

실제로 호스트 '0.0.0.0' 포트'4001'에서 서버를 실행하고 호스트 '192.168.1.1'과 포트'4001'에서 클라이언트를 실행하면'오류시 연결 '됩니다. 192.168.1.1이 네트워크 라우터에 속해 있지 않습니까? –

관련 문제