2014-04-14 5 views
0

우리는 다양한 TCP 구현 (Windows 8, Ubuntu 13.10)의 동작을 분석하려고합니다. 이를 위해 우리는 패킷을 만들고 패킷을 네트워크로 보내고 응답을 분석하는 데 사용할 수있는 Python 도구 인 Scapy을 사용하고 있습니다.Linux TCP 이상한 동작

우리는 Scapy 가짜 가이드 클라이언트와 수신 서버를 설치했습니다. 클라이언트에서는 서버에 TCP 패킷 시퀀스를 보내고 응답을 확인합니다. 서버는 연결을 받아들이고 아무것도하지 않습니다. 목표는 간단하지만보다 구체적인 서버 동작 모델을 얻는 것입니다. 우리는 모델에서 제외하고/재전송, 윈도우, 심지어 데이터 교환과 같은 복잡성을 무시합니다.

Windows 8에서 수신 서버의 동작을 분석 할 때 꽤 좋은 모델을 얻었습니다. 그러나 우분투에서 실험을 해보니, 적어도 결정적이지 않은 행동이 발생했습니다. 유사한 입력 패킷의 여러 "실행"을 구성하는 wireshark 로그의 이미지를 첨부했습니다. 모든 실행은 각 실행마다 증가하는 포트를 통해 실행됩니다. 왜 서버가 비 결정적 행동 않습니다. (존재하지 않았던 세그먼트의 ACK) 잘못된 승인을받지에

client ---- SYN 0 _ ---> server [LISTENING] 
client <- SYN+ACK 0 1 -- server [SYN_RCVD] 

client -- ACK+FIN 1 1 -> server [SYN_RCVD] 
client <--- ACK 1 2 ---- server [CLOSE_WAIT] 

client ---- ACK 1 20 --> server [CLOSE_WAIT] 
client <--- ACK 1 2 ---- server [CLOSE_WAIT] or no_response [CLOSE_WAIT] 

이 사람이 나에게 설명 할 수 : Wireshark capture 이상한 시나리오는 아래의 패턴을 따른다? 즉, ACK + FIN을 위해 보낸 ACK를 재전송하거나 아무것도 보내지 않아도됩니다. 이 문제는 구성 매개 변수로 인해 발생합니까? 우리 셋업에서는 기본 설정을 사용합니다.

BTW, 간단한 서버 코드 :

while (true) { 
    try { 
     Socket socket = server.accept(); 
    } 
    catch (IOException e) {} 
} 

UPDATE

나는 모델을 분석하고 동일한 시퀀스를 실행할 때 윈도우 8, 난 시간 제한을받을.

연결이 설정 동기화 상태 (인 경우 FIN-WAIT-1, FIN-WAIT-2, CLOSE-WAIT, 개폐 LAST이 명시 적으로 그 지정 rfc793 표준에 부합되지 -ACK, TIME-WAIT) 윈도우 시퀀스 넘버 또는 unacceptible 승인 번호 중 허용되지 않는 세그먼트()는 빈 응답 세그먼트 번호 가 예상되는 다음 시퀀스를 나타내는 현재의 전송 시퀀스 번호 및 확인 응답을 포함을 유도해야 수신되고 연결은 동일한 상태로 유지됩니다.

이 문제에 대해 의견을 개진 할 수 있습니까? 프로토콜 구현은 표준에 부합하는지 여부 또는 일정 수준의 비준수를 갖는 것이 일반적입니다. 표준이 때로는 시간 제한을 지정하지 못하기 때문에 그 중 일부는 피할 수없는 것 같지만 여기서 제어 흐름의 비준수에 대해 이야기하고 있습니다.

분명히 내가 뭔가 잘못하고있을 가능성이 있습니다. :)

감사합니다. Paul.

+0

ERR, 버그? 그것은 분명이 보낸 마지막 ACK를 다시해야한다. NB 상태가 CLOSE_WAIT하지 CLOSED_WAIT입니다. 로컬 포트가 닫혀 있지 않습니다 그게 바로 요점이다. 닫히기를 기다리고있다 . – EJP

+0

나의 실수는 실제로 CLOSE_WAIT이고 그렇다. 항구는 닫히지 않는다. 나는 그에 맞게 내 게시물을 업데이트 할 것이다. 그리고 나는 당신에게 동의한다. 이전 ACK 재전송 .Wireshark 없거나 해당 ACK 패킷을 볼 수없는 경우 궁금하다. 우분투 12.04 LT S와 우분투 13.10. – Paul

답변

1

서버가 Java로 작성 되었습니까? 당신이 관찰 한 "비 결정론"은 GC 타이밍 때문인 것으로 명시 적으로 Socket#close()을 호출하거나 InputStream#read()을 기다리면 사라질 수 있습니다.

+0

늦게 응답하여 죄송합니다. close를 호출하여 서버 측에서 FIN + ACK를 트리거합니다. 이 실험의 요점은 서버를 완전히 사후 대응할 수있게하는 것이 었습니다. OS 레벨 구현에 대해 이야기하고 있기 때문에 가비지 수집기가 아무런 영향을 미치지 않는다고 저는 믿습니다. 제대로 종료되지 않는 한 연결은 Java 서버 측의 각 핸들보다 오래 지속됩니다. (이 경우 핸들은 아무 것도 아니 었습니다. 왜냐하면 서버 측에서 우리는 오직 받아들입니다.) – Paul

+0

돌아 보면, 나는 사과해야하고 당신이 올바른 지적을 했어야합니다. 가비지 콜렉션은 열리고 참조되지 않은 소켓 (파일 설명자 제거)을 지 웁니다. – Paul

0

내가 관심을 가진 누구에게, 나는 "문제"를 추적 할 수 있었다고 생각한다. 이것은 수정되어야하는 규격에 대한 약간의 불일치입니다. 수신 된 세그먼트의 수신 번호 처리 코드 (here 가능)를 확인하면 rfc 793rfc 5961에 설정된 ack 번호의 수용 가능성을 확인합니다. 793에서 빌드 RFC 5961에 기초

는 ACK를 참조 만 허용되는 경우 내 ((SND.UNA - MAX.SND.WND) < = SEG.ACK < = SND.NXT). 다른 모든 경우에, 승인 번호는 받아 들일 수없는 것으로 간주되며 ACK가 발행되어야합니다.

코드 자체에서 ACK는 구간 ((SND.UNA- (2^31-1))에 속하는 세그먼트에 대해서만 발행됩니다. < = SEG.ACK < SND.UNA - MAX.SND.WND) . 세그먼트가 ((SND.NXT + 1 < = SEG.ACK < = SND.UNA - 2^31) 내에 있으면, ACK를 다시 전송하지 않고 세그먼트를 버립니다.이 경우 세그먼트도 유효하지 않은 ACK 수. 아래의 코드 스 니펫을 기록했다. 건배.

/* If the ack is older than previous acks 
* then we can probably ignore it. 
*/ 
if (before(ack, prior_snd_una)) { 
     /* RFC 5961 5.2 [Blind Data Injection Attack].[Mitigation] */ 
     if (before(ack, prior_snd_una - tp->max_window)) { 
       tcp_send_challenge_ack(sk); 
       return -1; 
     } 
     goto old_ack; 
} 

/* If the ack includes data we haven't sent yet, discard 
* this segment (RFC793 Section 3.9). 
*/ 
if (after(ack, tp->snd_nxt)) 
     goto invalid_ack;