はじめに
ルーター自作本を読みながら、Dockerネットワーク内でC言語を眺めている
今回は同一ネットワーク内において、PINGとTCPのキャプチャを試す
本の紹介
ネットワークプログラミングの世界へ
連載情報
連載 | 内容 |
---|---|
その1 | 〈実践〉同じセグメント内のPING疎通確認 |
その2 | 〈コード〉イーサネットヘッダの中身をみてみる |
その3 | 〈コード〉ARP,IP,ICMPの中身をみてみる |
その4 | 〈実践〉IP,TCPをキャプチャする |
その5 | 〈実践)ルーターを準備する |
その6 | 〈実践〉別セグメントのWEBへアクセスをする |
関数
- socket() - ソケットの作成
- perror() — エラー・メッセージの出力
- memset() — 値へのバイトの設定
- ioctl() - 装置の制御
- htons() - ネットワーク・バイト・オーダーへの符号なし短整数の変換
- ntohs() - ホスト・バイト・オーダーへの符号なし短整数の変換
Ethernetタイプ
IP, ARP, SNMP・・など2byte
Ethernetタイプ番号 ( Ethernet Type Number )
ether_header構造体
struct ether_header
{
uint8_t ether_dhost[ETH_ALEN]; /* destination eth addr */
uint8_t ether_shost[ETH_ALEN]; /* source ether addr */
uint16_t ether_type; /* packet type ID field */
} __attribute__ ((__packed__));
sockaddr_ll構造体
struct sockaddr_ll
{
unsigned short int sll_family;
unsigned short int sll_protocol;
int sll_ifindex;
unsigned short int sll_hatype;
unsigned char sll_pkttype;
unsigned char sll_halen;
unsigned char sll_addr[8];
};
/* Packet types. */
#define PACKET_HOST 0 /* To us. */
#define PACKET_BROADCAST 1 /* To all. */
#define PACKET_MULTICAST 2 /* To group. */
#define PACKET_OTHERHOST 3 /* To someone else. */
#define PACKET_OUTGOING 4 /* Originated by us . */
本書IPキャプチャを試す
Src/Link/ltest
をroot権限で実行すると、レイヤ3レベルでパケットの中身を監視できる
Pingを打つ
その1で作ったサーバーから、クライアントに対してPINGを打つ
-c 1
で1回だけ打つ
ping -n -I eth0 -c 1 Client1
PINGをクライアントが受けたあとに、クライアント側からARPが続けて送られている
5秒後にARPが実行されるらしい、詳しくは参考の記事へ。
sll_family=17
sll_protocol=8
sll_ifindex=78
sll_hatype=1
sll_pkttype=0
sll_halen=6
sll_addr=02:42:AC:12:00:02
ether_header----------------------------
ether_dhost=02:42:ac:12:00:03
ether_shost=02:42:ac:12:00:02
ether_type=800(IP)
sll_family=17
sll_protocol=8
sll_ifindex=78
sll_hatype=1
sll_pkttype=4
sll_halen=6
sll_addr=02:42:AC:12:00:03
ether_header----------------------------
ether_dhost=02:42:ac:12:00:02
ether_shost=02:42:ac:12:00:03
ether_type=800(IP)
sll_family=17
sll_protocol=1544
sll_ifindex=78
sll_hatype=1
sll_pkttype=4
sll_halen=6
sll_addr=02:42:AC:12:00:03
ether_header----------------------------
ether_dhost=02:42:ac:12:00:02
ether_shost=02:42:ac:12:00:03
ether_type=806(ARP)
sll_family=17
sll_protocol=1544
sll_ifindex=78
sll_hatype=1
sll_pkttype=0
sll_halen=6
sll_addr=02:42:AC:12:00:02
ether_header----------------------------
ether_dhost=02:42:ac:12:00:03
ether_shost=02:42:ac:12:00:02
ether_type=806(ARP)
socket
関数の第3引数をETH_P_ALL
からETH_P_IP
に変更すると、冒頭の受信だけが表示される
sll_family=17
sll_protocol=8
sll_ifindex=78
sll_hatype=1
sll_pkttype=0
sll_halen=6
sll_addr=02:42:AC:12:00:02
ether_header----------------------------
ether_dhost=02:42:ac:12:00:03
ether_shost=02:42:ac:12:00:02
ether_type=800(IP)
本書TCPキャプチャを試す
Src/Pcap/pcap eth0
をroot権限で実行すると、レイヤ4レベルでパケットの中身を監視できる
TCPのチェックサム
TCPのチェックサムの計算をNICが代行する場合がある
送出されるパケットについて
リンクレイヤでキャプチャすると、それはまだNICを出る前のデータであるため
チェックサムが異常であることがある
次章キャプチャ結果にも bad tcp checksum と書かれている
TCP通信テスト
ポート80番へTCP通信テストはnc
コマンドで。
Packet[74bytes]
ether_header----------------------------
ether_dhost=02:42:ac:12:00:03
ether_shost=02:42:ac:12:00:02
ether_type=800(IP)
ip--------------------------------------
version=4,ihl=5,tos=0,tot_len=60,id=28592
frag_off=2,0,ttl=64,protocol=6(TCP),check=e272
saddr=172.18.0.2,daddr=172.18.0.3
bad tcp checksum
Packet[54bytes]
ether_header----------------------------
ether_dhost=02:42:ac:12:00:02
ether_shost=02:42:ac:12:00:03
ether_type=800(IP)
ip--------------------------------------
version=4,ihl=5,tos=0,tot_len=40,id=0
frag_off=2,0,ttl=64,protocol=6(TCP),check=a6e2
saddr=172.18.0.3,daddr=172.18.0.2
tcp-------------------------------------
source=80,dest=35800
seq=0
ack_seq=2265763664
doff=5,urg=0,ack=1,psh=0,rst=1,syn=0,fin=0,th_win=0
th_sum=29985,th_urp=0
Packet[42bytes]
ether_header----------------------------
ether_dhost=02:42:ac:12:00:03
ether_shost=02:42:ac:12:00:02
ether_type=806(ARP)
arp-------------------------------------
arp_hrd=1(Ethernet 10/100Mbps.),arp_pro=2048(IP)
arp_hln=6,arp_pln=4,arp_op=2(ARP reply.)
arp_sha=02:42:ac:12:00:02
arp_spa=172.18.0.2
arp_tha=02:42:ac:12:00:03
arp_tpa=172.18.0.2
参考