ポート スキャナー ユーティリティを作成する必要があります。raw ソケットを使用して SYN パケットを送信し、宛先が応答しているかどうかを検出しています。
このraw ソケット ガイドは、特定のビットが設定されたパケットを送信する方法を学ぶのに非常に役立ちました。しかし、recvfrom を使用してパケット応答を受信できません。
私の観察では、探しているもの以外のすべてのパケットを受信しています。
たとえば、1 回の実行の tcp ダンプは次のように表示されます。
22:26:52.962557 IP localhost.3000 > localhost.32000: Flags [S], seq 0:1, win 5840, length 1
22:26:52.962571 IP localhost.32000 > localhost.3000: Flags [S.], seq 262551688, ack 1, win 32792, options [mss 16396], length 0
22:26:52.962576 IP localhost.3000 > localhost.32000: Flags [R], seq 1, win 0, length 0
ただし、私のアプリケーションでは、32000 ポートのパケットを確認できません。
私の受信ロジックは次のとおりです(簡単なテストのためにコードを変更しました。基本コードは上記のリンクと同じです)。
//Send the packet SYN Packet
if (sendto (s, datagram, iph->tot_len , 0, (struct sockaddr *) &sin, sizeof (sin)) < 0)
{
perror("sendto failed");
}
//Data send successfully
else
{
int count = 10;
while(count--)
{
char readbuff[1540] = {0};
struct sockaddr_in receiver = sin;
socklen_t len = sizeof(receiver);
int bread = recvfrom(s, readbuff, sizeof(readbuff), 0, (struct sockaddr*) &receiver, &len);
int port = ntohs(receiver.sin_port);
printf("New Packet( Source: %s, Port: %d)\n", inet_ntoa((struct in_addr)receiver.sin_addr), port);
if(receiver.sin_addr.s_addr == sin.sin_addr.s_addr)
{
if(bread < 0)
{
perror("bread is less than zero");
exit(0);
}
else if(bread == 0 || bread < 40)
{
//again we expect atleast 40 bytes from another party.
//TODO: try again if bread > 0 but < 40. if readbuff[bread] != EOF
//mostly malicious code or trying to get into our head
perror("bread is zero");
exit(0);
}
else
{
//we have a valid data.
//TODO: Do not trust the data coming, and try to validate it.
struct ip *iph2 = (struct ip*) readbuff;
int size = iph2->ip_hl;
//we only want to inspect if source ip of packet matches with original packet dest.
if(iph2->ip_src.s_addr == sin.sin_addr.s_addr)
{
if(iph2->ip_p == IPPROTO_TCP)
{
struct tcphdr *tcph2 = (struct tcphdr *) (readbuff + size);
printf("TCP:source%s,port=%d,dest=%s,port=%d", inet_ntoa(iph2->ip_src), ntohs(tcph2->source), inet_ntoa(iph2->ip_dst), ntohs(tcph2->dest));
if(tcph2->source == sin.sin_port)
{
if(tcph2->syn == 1 && tcph2->ack == 1)
{
//We got a good response. Host will send RST if port is not
//behind firewall. This means port is unfiltered.
printf("Result UNFILTERED\n");
}
else
{
printf("Result FILTERED\n");
}
}
else
{
printf("\nWrong port\n");
}
}
else if(iph2->ip_p == IPPROTO_ICMP)
{
//TODO: write logic to detect that error code is (type 3, code 1, 2, 3, 9, 10 or 13
printf("Result FILTERED\n");
}
}
else
{
printf("\nWrong IP\n");
}
}
}
}
}
私のアプリケーションの出力は次のとおりです
New Packet( Source: 127.0.0.1, Port: 0)
TCP:source127.0.0.1,port=23552,dest=127.0.0.1,port=255
Wrong port
New Packet( Source: 127.0.0.1, Port: 0)
TCP:source127.0.0.1,port=64,dest=127.0.0.1,port=64
Wrong port
New Packet( Source: 127.0.0.1, Port: 0)
TCP:source127.0.0.1,port=64,dest=127.0.0.1,port=64
Wrong port
New Packet( Source: 74.125.142.125, Port: 0)
New Packet( Source: 74.125.225.33, Port: 0)
New Packet( Source: 74.125.225.33, Port: 0)
New Packet( Source: 74.125.225.47, Port: 0)
New Packet( Source: 74.125.225.47, Port: 0)
New Packet( Source: 74.125.225.47, Port: 0)
New Packet( Source: 74.125.225.47, Port: 0)
New Packet( Source: 74.125.225.43, Port: 0)
New Packet( Source: 74.125.225.43, Port: 0)
New Packet( Source: 74.125.225.43, Port: 0)
New Packet( Source: 74.125.225.43, Port: 0)
New Packet( Source: 74.125.225.180, Port: 0)
New Packet( Source: 74.125.225.180, Port: 0)
New Packet( Source: 74.125.225.180, Port: 0)
New Packet( Source: 74.125.225.180, Port: 0)
New Packet( Source: 74.125.142.125, Port: 0)
New Packet( Source: 74.125.142.125, Port: 0)
New Packet( Source: 74.125.142.125, Port: 0)
New Packet( Source: 74.125.142.125, Port: 0)
New Packet( Source: 74.125.142.125, Port: 0)
New Packet( Source: 74.125.142.125, Port: 0)
New Packet( Source: 74.125.142.125, Port: 0)
New Packet( Source: 74.125.225.67, Port: 0)
New Packet( Source: 74.125.225.67, Port: 0)
New Packet( Source: 74.125.225.67, Port: 0)
New Packet( Source: 74.125.142.125, Port: 0)
New Packet( Source: 74.125.225.67, Port: 0)
New Packet( Source: 64.34.119.101, Port: 0)
New Packet( Source: 69.171.241.10, Port: 0)
New Packet( Source: 74.125.133.16, Port: 0)
New Packet( Source: 74.125.133.16, Port: 0)
New Packet( Source: 74.125.133.16, Port: 0)
New Packet( Source: 74.125.133.16, Port: 0)
New Packet( Source: 74.125.133.16, Port: 0)
New Packet( Source: 74.125.133.16, Port: 0)
New Packet( Source: 74.125.133.16, Port: 0)
New Packet( Source: 74.125.133.16, Port: 0)
New Packet( Source: 74.125.142.125, Port: 0)
New Packet( Source: 69.171.241.10, Port: 0)
注: コードをテストする場合は、次のインクルードを追加する必要があります。
#include <arpa/inet.h>
私が間違っていることについての指針はありますか?
更新: コードに間違いが見つかりました。TCP ヘッダーの読み取り中に、長さの計算が正しくありません。正しい計算は次のとおりです。
struct tcphdr *tcph2 = (struct tcphdr *) (readbuff + size*4);
それでも、recvfrom 呼び出しから読み取られた他のすべてのパケットも確認できます。送信元 ip= 元の宛先 ip と送信元ポート = 元の宛先ポートを持つ特定のパケットだけを読み取る方法についてのアイデアはありますか?