802.1.x认证

802.1.x认证

十月 04, 2020

公司的上网验证使用802.1.x,但是使用的是私有的客户端(只有mac和win),而且还有很多限制。
为了在linux平台上使用,开始了该项目。
由于不清楚密码如何加密的,但是确定加密与次数和时间没有关系,可以抓包获取认证的密钥。生成password.bin用于其他机器的认证。

在已安装客户端的机器上运行

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
package main

import (
"flag"
"fmt"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/google/gopacket/pcap"
"io/ioutil"
)

var iface = flag.String("i", "\\Device\\NPF_{540078E3-B5F2-4E7A-9D21-}", "Interface to read packets from")

func main() {
flag.Parse()
filterStr := fmt.Sprintf("(ether proto 0x888e)")
fmt.Println(*iface)
handle, err := pcap.OpenLive(*iface, 65536, true, pcap.BlockForever)
if err != nil {
panic(err)
}
err = handle.SetBPFFilter(filterStr)
if err != nil {
panic(err)
}
defer handle.Close()

var userName, passWord []byte
for userName == nil || passWord == nil {
data, _, err := handle.ReadPacketData()
if err == pcap.NextErrorTimeoutExpired {
continue
} else if err != nil {
panic(err)
}
packet := gopacket.NewPacket(data, layers.LayerTypeEthernet, gopacket.NoCopy)
if eapLayer := packet.Layer(layers.LayerTypeEAP); eapLayer != nil {
eap := eapLayer.(*layers.EAP)
switch eap.Code {
case layers.EAPCodeResponse:
switch eap.Type {
case layers.EAPTypeIdentity:
userName = eap.TypeData
fmt.Printf("%s", string(userName))
case 0x66:
passWord = eap.TypeData
fmt.Println()
fmt.Printf("%x", passWord)
default:
fmt.Println("unknown eap type:", eap.Type)
}
case layers.EAPCodeSuccess:
case layers.EAPCodeFailure:
return
default:
fmt.Println("unknown epa code:", eap.Code)
}
}
}

userName = append(userName, 0xff)
userName = append(userName, passWord...)
e := ioutil.WriteFile("password.bin", userName, 0644)
if e != nil {
panic(e)
}
}

在其他需要认证的机器上运行

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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
package main

import (
"flag"
"fmt"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/google/gopacket/pcap"
"io/ioutil"
"net"
"sync"
"time"
)

var (
interfaceName string
localMac string
)

func init() {
flag.StringVar(&interfaceName, "interface", "", "interface name")
flag.StringVar(&localMac, "mac", "", "mac address")
}

//https://github.com/google/gopacket/issues/456
func main() {
flag.Parse()
authentication(interfaceName, localMac)

}

func authentication(interfaceName string, localMac string) {

filterStr := fmt.Sprintf(
"(ether proto 0x888e) and (ether dst host %s)", localMac)
handle, err := pcap.OpenLive(interfaceName, 65536, true, pcap.BlockForever)
if err != nil {
panic(err)
}
err = handle.SetBPFFilter(filterStr)
if err != nil {
panic(err)
}
defer handle.Close()

stop := make(chan int)
hwAddr, err := net.ParseMAC(localMac)
if err != nil {
panic(err)
}

data, err := ioutil.ReadFile("password.bin")
if err != nil {
panic(err)
}
var index int
for i, v := range data {
if v == byte(0xff) {
index = i
}
}
username := string(data[0:index])
passwd := data[index+1:]

go readEap(handle, hwAddr, stop, username, passwd)
defer close(stop)

time.Sleep(3000)
go broadcast(handle, hwAddr)

var wg sync.WaitGroup
wg.Add(1)
wg.Wait()
}

func readEap(handle *pcap.Handle, localMac net.HardwareAddr, stop chan int, username string, password []byte) {
src := gopacket.NewPacketSource(handle, layers.LayerTypeEthernet)
in := src.Packets()
for {
var packet gopacket.Packet
select {
case <-stop:
return
case packet = <-in:
ethLayer := packet.Layer(layers.LayerTypeEthernet)
if ethLayer == nil {
return
}
eth := ethLayer.(*layers.Ethernet)
srcMac := eth.SrcMAC

eapLayer := packet.Layer(layers.LayerTypeEAP)
if eapLayer == nil {
continue
}
eap := eapLayer.(*layers.EAP)
fmt.Println("eap data: ", eap)

switch eap.Code {
case layers.EAPCodeRequest:
switch eap.Type {
case layers.EAPTypeIdentity:
sendUserName(handle, localMac, srcMac, eap.Id, username)
case 0x66:
sendPassword(handle, localMac, srcMac, eap.Id, password)
default:
fmt.Println("unknown eap type:", eap.Type)
}
case layers.EAPCodeSuccess:
stop <- 1
fmt.Println("epa success")
case layers.EAPCodeFailure:
fmt.Println("eap failure")
default:
fmt.Println("unknown epa code:", eap.Code)
}
}
}
}

func broadcast(handle *pcap.Handle, localMac net.HardwareAddr) error {
eth := layers.Ethernet{
SrcMAC: localMac,
DstMAC: net.HardwareAddr{0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
EthernetType: 0x888e,
}
eaPol := layers.EAPOL{
Version: 0x01,
Type: layers.EAPOLTypeStart,
Length: 0x00,
}

buf := gopacket.NewSerializeBuffer()
opts := gopacket.SerializeOptions{
FixLengths: true,
ComputeChecksums: true,
}
gopacket.SerializeLayers(buf, opts, &eth, &eaPol)
fmt.Println("broadcast ")
if err := handle.WritePacketData(buf.Bytes()); err != nil {
return err
}
return nil
}

func sendUserName(handle *pcap.Handle, srcMac net.HardwareAddr, destAddr net.HardwareAddr, id uint8, username string) error {
eth := layers.Ethernet{
SrcMAC: srcMac,
DstMAC: destAddr,
EthernetType: 0x888e,
}
eap := layers.EAP{
Code: layers.EAPCodeResponse,
Id: id,
Length: uint16(len([]byte(username))),
Type: layers.EAPTypeIdentity,
TypeData: []byte(username),
}

buf := gopacket.NewSerializeBuffer()
opts := gopacket.SerializeOptions{
FixLengths: true,
ComputeChecksums: true,
}
gopacket.SerializeLayers(buf, opts, &eth, &eap)
fmt.Println("send username ", username)
if err := handle.WritePacketData(buf.Bytes()); err != nil {
return err
}
return nil

}

func sendPassword(handle *pcap.Handle, srcMac net.HardwareAddr, destAddr net.HardwareAddr, id uint8, password []byte) error {
eth := layers.Ethernet{
SrcMAC: srcMac,
DstMAC: destAddr,
EthernetType: 0x888e,
}

eap := layers.EAP{
Code: layers.EAPCodeResponse,
Id: id,
Length: uint16(len(password)),
Type: layers.EAPTypeIdentity,
TypeData: password,
}

buf := gopacket.NewSerializeBuffer()
opts := gopacket.SerializeOptions{
FixLengths: true,
ComputeChecksums: true,
}
gopacket.SerializeLayers(buf, opts, &eth, &eap)
if err := handle.WritePacketData(buf.Bytes()); err != nil {
return err
}
return nil
}