go test: add ICMP ping
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
parent
1f349aa101
commit
35a61c32fa
|
@ -12,6 +12,8 @@ import (
|
||||||
|
|
||||||
"github.com/dchest/blake2s"
|
"github.com/dchest/blake2s"
|
||||||
"github.com/titanous/noise"
|
"github.com/titanous/noise"
|
||||||
|
"golang.org/x/net/icmp"
|
||||||
|
"golang.org/x/net/ipv4"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@ -36,6 +38,7 @@ func main() {
|
||||||
}
|
}
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
|
// write handshake initiation packet
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
tai64n := make([]byte, 12)
|
tai64n := make([]byte, 12)
|
||||||
binary.BigEndian.PutUint64(tai64n[:], uint64(now.Unix()))
|
binary.BigEndian.PutUint64(tai64n[:], uint64(now.Unix()))
|
||||||
|
@ -53,6 +56,7 @@ func main() {
|
||||||
log.Fatalf("error writing initiation packet: %s", err)
|
log.Fatalf("error writing initiation packet: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// read handshake response packet
|
||||||
responsePacket := make([]byte, 89)
|
responsePacket := make([]byte, 89)
|
||||||
n, err := conn.Read(responsePacket)
|
n, err := conn.Read(responsePacket)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -69,7 +73,7 @@ func main() {
|
||||||
if ourIndex != 28 {
|
if ourIndex != 28 {
|
||||||
log.Fatalf("response packet index wrong: want %d, got %d", 28, ourIndex)
|
log.Fatalf("response packet index wrong: want %d, got %d", 28, ourIndex)
|
||||||
}
|
}
|
||||||
payload, sendCipher, _, err := hs.ReadMessage(nil, responsePacket[9:57])
|
payload, sendCipher, receiveCipher, err := hs.ReadMessage(nil, responsePacket[9:57])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("error reading handshake message: %s", err)
|
log.Fatalf("error reading handshake message: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -77,12 +81,64 @@ func main() {
|
||||||
log.Fatalf("unexpected payload: %x", payload)
|
log.Fatalf("unexpected payload: %x", payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
keepalivePacket := make([]byte, 13)
|
// write ICMP Echo packet
|
||||||
keepalivePacket[0] = 4 // Type: Data
|
pingMessage, _ := (&icmp.Message{
|
||||||
binary.LittleEndian.PutUint32(keepalivePacket[1:], theirIndex)
|
Type: ipv4.ICMPTypeEcho,
|
||||||
binary.LittleEndian.PutUint64(keepalivePacket[5:], 0) // Nonce
|
Body: &icmp.Echo{
|
||||||
keepalivePacket = sendCipher.Encrypt(keepalivePacket, nil, nil)
|
ID: 1,
|
||||||
if _, err := conn.Write(keepalivePacket); err != nil {
|
Seq: 1,
|
||||||
log.Fatalf("error writing keepalive packet: %s", err)
|
Data: []byte("WireGuard"),
|
||||||
|
},
|
||||||
|
}).Marshal(nil)
|
||||||
|
pingHeader, err := (&ipv4.Header{
|
||||||
|
Version: ipv4.Version,
|
||||||
|
Len: ipv4.HeaderLen,
|
||||||
|
TotalLen: ipv4.HeaderLen + len(pingMessage),
|
||||||
|
Protocol: 1, // ICMP
|
||||||
|
TTL: 2,
|
||||||
|
Checksum: 0xa15b, // the packet is always the same, hard-code checksum
|
||||||
|
Src: net.IPv4(10, 189, 129, 2),
|
||||||
|
Dst: net.IPv4(10, 189, 129, 1),
|
||||||
|
}).Marshal()
|
||||||
|
binary.BigEndian.PutUint16(pingHeader[2:], uint16(ipv4.HeaderLen+len(pingMessage))) // fix the length endianness on BSDs
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
pingPacket := make([]byte, 13)
|
||||||
|
pingPacket[0] = 4 // Type: Data
|
||||||
|
binary.LittleEndian.PutUint32(pingPacket[1:], theirIndex)
|
||||||
|
binary.LittleEndian.PutUint64(pingPacket[5:], 0) // Nonce
|
||||||
|
pingPacket = sendCipher.Encrypt(pingPacket, nil, append(pingHeader, pingMessage...))
|
||||||
|
if _, err := conn.Write(pingPacket); err != nil {
|
||||||
|
log.Fatalf("error writing ping message: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// read ICMP Echo Reply packet
|
||||||
|
replyPacket := make([]byte, 128)
|
||||||
|
n, err = conn.Read(replyPacket)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("error reading ping reply message: %s", err)
|
||||||
|
}
|
||||||
|
replyPacket = replyPacket[:n]
|
||||||
|
if replyPacket[0] != 4 { // Type: Data
|
||||||
|
log.Fatalf("unexpected reply packet type: %d", replyPacket[0])
|
||||||
|
}
|
||||||
|
replyPacket, err = receiveCipher.Decrypt(nil, nil, replyPacket[13:])
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("error decrypting reply packet: %s", err)
|
||||||
|
}
|
||||||
|
replyHeaderLen := int(replyPacket[0]&0x0f) << 2
|
||||||
|
replyLen := binary.BigEndian.Uint16(replyPacket[2:])
|
||||||
|
replyMessage, err := icmp.ParseMessage(1, replyPacket[replyHeaderLen:replyLen])
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("error parsing echo: %s", err)
|
||||||
|
}
|
||||||
|
echo, ok := replyMessage.Body.(*icmp.Echo)
|
||||||
|
if !ok {
|
||||||
|
log.Fatalf("unexpected reply body type %T", replyMessage.Body)
|
||||||
|
}
|
||||||
|
|
||||||
|
if echo.ID != 1 || echo.Seq != 1 || string(echo.Data) != "WireGuard" {
|
||||||
|
log.Fatalf("incorrect echo response: %#v", echo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Reference in New Issue