-
Notifications
You must be signed in to change notification settings - Fork 0
/
api.go
116 lines (98 loc) · 3.5 KB
/
api.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package gop0f
import (
"bytes"
"encoding/binary"
"fmt"
"net"
"strings"
)
const (
// address types
ipv4Type = 0x04
ipv6Type = 0x06
// status
statusBadQuery = 0x00
statusOk = 0x10
statusNoMatch = 0x20
)
var (
//P0F_QUERY_MAGIC = [...]byte{0x1, 0x46, 0x30, 0x50} //0x50304601
sendMagic = [...]byte{0x1, 0x46, 0x30, 0x50} //0x50304601
recvMagic = [...]byte{0x2, 0x46, 0x30, 0x50} //0x50304602
stringFields = []string{""}
)
type sendPacket struct {
Magic [4]byte // Magic dword (0x50304601)
AddrType byte // Address type byte: 4 for IPv4, 6 for IPv6
Data [16]byte // 16 bytes of address data, network endian. IPv4 addresses should be aligned to the left
}
type recvPacket struct {
Magic [4]byte // Magic dword (0x50304602)
Status [4]byte // Status dword: 0x00 for 'bad query', 0x10 for 'OK', and 0x20 for 'no match'
FirstSeen uint32 // unix time (seconds) of first observation of the host
LastSeen uint32 // unix time (seconds) of most recent traffic
TotalConn uint32 // total number of connections seen
UptimeMin uint32 // calculated system uptime, in minutes. Zero if not known
UpModDays uint32 // uptime wrap-around interval, in days
LastNat [4]byte // time of the most recent detection of IP sharing (NAT, load balancing, proxying). Zero if never detected
LastChg [4]byte // time of the most recent individual OS mismatch (e.g., due to multiboot or IP reuse)
Distance [2]byte // system distance (derived from TTL; -1 if no data)
BadSw byte // p0f thinks the User-Agent or Server strings aren't accurate. The value of 1 means OS difference (possibly due to proxying), while 2 means an outright mismatch
OsMatchQ byte // OS match quality: 0 for a normal match; 1 for fuzzy (e.g., TTL or DF difference); 2 for a generic signature; and 3 for both
OsName [32]byte // NUL-terminated name of the most recent positively matched OS. If OS not known, os_name[0] is NUL
OsFlavor [32]byte // OS version. May be empty if no data
HttpName [32]byte // most recent positively identified HTTP application (e.g. 'Firefox')
HttpFlavor [32]byte // version of the HTTP application, if any
LinkType [32]byte // network link type, if recognized
Language [32]byte // system language, if recognized
}
type hostInfo struct {
OsName string
OsFlavor string
}
func (p *recvPacket) parse(hi *hostInfo) {
hi.OsName = strings.Trim(fmt.Sprintf("%s", p.OsName), "\000")
hi.OsFlavor = strings.Trim(fmt.Sprintf("%s", p.OsFlavor), "\000")
}
func preparePacket(ipv4 string) *sendPacket {
packet := &sendPacket{
Magic: sendMagic,
AddrType: ipv4Type,
}
copy(packet.Data[:], ipv4toBytes(ipv4))
return packet
}
func ipv4toBytes(ipv4 string) []byte {
return net.ParseIP(ipv4).To4()
}
func send(conn net.Conn, packet *sendPacket) (*recvPacket, error) {
// convert sendPacket to bytes array
var buffer bytes.Buffer
if err := binary.Write(&buffer, binary.BigEndian, packet); err != nil {
return nil, err
}
data := buffer.Bytes()
// check data length
// todo
// send data to p0f api
_, err := conn.Write(data)
if err != nil {
return nil, err
}
// receive response data from p0f api
recvData := make([]byte, 1048)
recvLen, err := conn.Read(recvData[:])
if err != nil {
return nil, err
}
// convert recvData to recvPacket
buf := bytes.NewReader(recvData[0:recvLen])
recvPacket := &recvPacket{}
err = binary.Read(buf, binary.BigEndian, recvPacket)
if err != nil {
return nil, err
}
// validate received packet
// todo
return recvPacket, nil
}