Proxying implementation finished
This commit is contained in:
parent
711400607d
commit
b7ca59b1bd
@ -8,9 +8,11 @@ const (
|
||||
)
|
||||
|
||||
type NDRequest struct {
|
||||
requestType NDPType
|
||||
//TODO use global unicast for router advertisements
|
||||
srcIP []byte
|
||||
answeringForIP []byte
|
||||
mac []byte
|
||||
requestType NDPType
|
||||
srcIP []byte
|
||||
answeringForIP []byte
|
||||
dstIP []byte
|
||||
mac []byte
|
||||
receivedIfaceMac []byte
|
||||
sourceIface string
|
||||
}
|
||||
|
22
main.go
22
main.go
@ -3,6 +3,8 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func main() {
|
||||
@ -27,8 +29,14 @@ func simpleRespond(iface string) {
|
||||
defer close(requests)
|
||||
go respond(iface, requests, NDP_ADV)
|
||||
go listen(iface, requests, NDP_SOL)
|
||||
select {}
|
||||
//TODO os.signal
|
||||
|
||||
sigCh := make(chan os.Signal)
|
||||
signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM)
|
||||
select {
|
||||
case <-sigCh:
|
||||
fmt.Println("Exit")
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
|
||||
func proxy(iface1, iface2 string) {
|
||||
@ -52,7 +60,11 @@ func proxy(iface1, iface2 string) {
|
||||
go listen(iface2, req_iface2_adv_iface1, NDP_ADV)
|
||||
go respond(iface1, req_iface2_adv_iface1, NDP_ADV)
|
||||
|
||||
select {}
|
||||
// TODO os.signal
|
||||
|
||||
sigCh := make(chan os.Signal)
|
||||
signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM)
|
||||
select {
|
||||
case <-sigCh:
|
||||
fmt.Println("Exit")
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
|
32
packet.go
32
packet.go
@ -2,6 +2,9 @@ package main
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"net"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var emptyIpv6 = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
@ -18,8 +21,11 @@ type IPv6Header struct {
|
||||
payload []byte
|
||||
}
|
||||
|
||||
func newIpv6Header(srcIp []byte, dstIp []byte) *IPv6Header {
|
||||
return &IPv6Header{dstIP: dstIp, srcIP: srcIp, protocol: 0x3a}
|
||||
func newIpv6Header(srcIp []byte, dstIp []byte) (*IPv6Header, error) {
|
||||
if len(dstIp) != 16 || len(srcIp) != 16 {
|
||||
return nil, errors.New("malformed IP")
|
||||
}
|
||||
return &IPv6Header{dstIP: dstIp, srcIP: srcIp, protocol: 0x3a}, nil
|
||||
}
|
||||
|
||||
func (h *IPv6Header) addPayload(payload Payload) {
|
||||
@ -61,23 +67,29 @@ type NdpPayload struct {
|
||||
mac []byte
|
||||
}
|
||||
|
||||
func newNdpPacket(answeringForIP []byte, mac []byte, packetType NDPType) *NdpPayload {
|
||||
func newNdpPacket(answeringForIP []byte, mac []byte, packetType NDPType) (*NdpPayload, error) {
|
||||
if len(answeringForIP) != 16 || len(mac) != 6 {
|
||||
return nil, errors.New("malformed IP")
|
||||
}
|
||||
return &NdpPayload{
|
||||
packetType: packetType,
|
||||
answeringForIP: answeringForIP,
|
||||
mac: mac,
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *NdpPayload) constructPacket() ([]byte, int) {
|
||||
var protocol byte
|
||||
var flags byte
|
||||
var linkType byte
|
||||
if p.packetType == NDP_SOL {
|
||||
protocol = 0x87
|
||||
flags = 0x0
|
||||
linkType = 0x01
|
||||
} else {
|
||||
protocol = 0x88
|
||||
flags = 0x60
|
||||
linkType = 0x02
|
||||
}
|
||||
header := []byte{
|
||||
protocol, // Type: NDPType
|
||||
@ -89,14 +101,11 @@ func (p *NdpPayload) constructPacket() ([]byte, int) {
|
||||
0x0, // Reserved
|
||||
0x0, // Reserved
|
||||
}
|
||||
if len(p.answeringForIP) != 16 {
|
||||
panic("malformed IP")
|
||||
} //TODO check IP lengths on assign everywhere
|
||||
final := append(header, p.answeringForIP...)
|
||||
|
||||
secondHeader := []byte{
|
||||
0x02, // Type: Target link-layer address (2)
|
||||
0x01, // Length: 1 (8 bytes)
|
||||
linkType, // Type
|
||||
0x01, // Length: 1 (8 bytes)
|
||||
}
|
||||
final = append(final, secondHeader...)
|
||||
|
||||
@ -123,3 +132,8 @@ func checksumAddition(b []byte) uint32 {
|
||||
}
|
||||
return sum
|
||||
}
|
||||
|
||||
func IsIPv6(ip string) bool {
|
||||
rip := net.ParseIP(ip)
|
||||
return rip != nil && strings.Contains(ip, ":")
|
||||
}
|
||||
|
18
rawsocket.go
18
rawsocket.go
@ -50,7 +50,6 @@ func listen(iface string, responder chan *NDRequest, requestType NDPType) {
|
||||
Protocol: htons16(syscall.ETH_P_IPV6),
|
||||
Ifindex: niface.Index,
|
||||
}
|
||||
fmt.Println(niface.HardwareAddr)
|
||||
|
||||
fd, err := syscall.Socket(syscall.AF_PACKET, syscall.SOCK_RAW, htons(syscall.ETH_P_IPV6))
|
||||
if err != nil {
|
||||
@ -65,7 +64,7 @@ func listen(iface string, responder chan *NDRequest, requestType NDPType) {
|
||||
|
||||
err = syscall.Bind(fd, tiface)
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
panic(err.Error())
|
||||
}
|
||||
|
||||
var f Filter
|
||||
@ -83,7 +82,7 @@ func listen(iface string, responder chan *NDRequest, requestType NDPType) {
|
||||
bpf.LoadAbsolute{Off: 54, Size: 1},
|
||||
// Jump to the drop packet instruction if Type is not Neighbor Solicitation.
|
||||
bpf.JumpIf{Cond: bpf.JumpNotEqual, Val: 0x87, SkipTrue: 1},
|
||||
// Verdict is "send up to 4k of the packet to userspace."
|
||||
// Verdict is "send up to 4k of the packet to userspace."buf
|
||||
bpf.RetConstant{Val: 4096},
|
||||
// Verdict is "ignore packet."
|
||||
bpf.RetConstant{Val: 0},
|
||||
@ -122,16 +121,21 @@ func listen(iface string, responder chan *NDRequest, requestType NDPType) {
|
||||
}
|
||||
fmt.Println("Source IP:")
|
||||
fmt.Printf("% X\n", buf[:numRead][22:38])
|
||||
fmt.Println("Destination IP:")
|
||||
fmt.Printf("% X\n", buf[:numRead][38:54])
|
||||
fmt.Println("Requested IP:")
|
||||
fmt.Printf("% X\n", buf[:numRead][62:78])
|
||||
fmt.Println("Source MAC")
|
||||
fmt.Printf("% X\n", buf[:numRead][80:86])
|
||||
fmt.Println()
|
||||
responder <- &NDRequest{
|
||||
requestType: requestType,
|
||||
srcIP: buf[:numRead][22:38],
|
||||
answeringForIP: buf[:numRead][62:78],
|
||||
mac: buf[:numRead][80:86],
|
||||
requestType: requestType,
|
||||
srcIP: buf[:numRead][22:38],
|
||||
dstIP: buf[:numRead][38:54],
|
||||
answeringForIP: buf[:numRead][62:78],
|
||||
mac: buf[:numRead][80:86],
|
||||
receivedIfaceMac: niface.HardwareAddr,
|
||||
sourceIface: iface,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
70
responder.go
70
responder.go
@ -1,48 +1,84 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
var fd int
|
||||
var globalFd int
|
||||
|
||||
func respond(iface string, requests chan *NDRequest, respondType NDPType) {
|
||||
fd, _ = syscall.Socket(syscall.AF_INET6, syscall.SOCK_RAW, syscall.IPPROTO_RAW)
|
||||
syscall.BindToDevice(fd, iface)
|
||||
fd, err := syscall.Socket(syscall.AF_INET6, syscall.SOCK_RAW, syscall.IPPROTO_RAW)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer syscall.Close(globalFd)
|
||||
globalFd = fd
|
||||
err = syscall.BindToDevice(fd, iface)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
niface, err := net.InterfaceByName(iface)
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
|
||||
var result = emptyIpv6
|
||||
ifaceaddrs, err := niface.Addrs()
|
||||
|
||||
for _, n := range ifaceaddrs {
|
||||
tip, _, err := net.ParseCIDR(n.String())
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
if IsIPv6(tip.String()) {
|
||||
if tip.IsGlobalUnicast() {
|
||||
result = tip
|
||||
_, tnet, _ := net.ParseCIDR("fc00::/7")
|
||||
if !tnet.Contains(tip) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for {
|
||||
n := <-requests
|
||||
pkt(n.srcIP, n.answeringForIP, niface.HardwareAddr, respondType)
|
||||
if n.sourceIface == iface {
|
||||
pkt(result, n.srcIP, n.answeringForIP, niface.HardwareAddr, respondType)
|
||||
} else {
|
||||
if !bytes.Equal(n.mac, n.receivedIfaceMac) {
|
||||
pkt(n.srcIP, n.dstIP, n.answeringForIP, niface.HardwareAddr, respondType)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func pkt(srcip []byte, tgtip []byte, mac []byte, respondType NDPType) {
|
||||
v6 := newIpv6Header(emptyIpv6, srcip)
|
||||
NDPa := newNdpPacket(tgtip, mac, respondType)
|
||||
func pkt(ownIP []byte, dstIP []byte, tgtip []byte, mac []byte, respondType NDPType) {
|
||||
v6, err := newIpv6Header(ownIP, dstIP)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
NDPa, err := newNdpPacket(tgtip, mac, respondType)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
v6.addPayload(NDPa)
|
||||
response := v6.constructPacket()
|
||||
|
||||
var t [16]byte
|
||||
if respondType == NDP_SOL {
|
||||
copy(t[:], []byte{0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x02})
|
||||
} else {
|
||||
copy(t[:], srcip)
|
||||
}
|
||||
copy(t[:], dstIP)
|
||||
|
||||
d := syscall.SockaddrInet6{
|
||||
Port: 0,
|
||||
Addr: t,
|
||||
}
|
||||
err := syscall.Sendto(fd, response, 0, &d)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println("Sending packet of type", respondType, "to")
|
||||
fmt.Printf("% X\n", t)
|
||||
|
||||
syscall.Close(fd)
|
||||
err = syscall.Sendto(globalFd, response, 0, &d)
|
||||
fmt.Println(err.Error())
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user