dockerfiles/anylink/server/handler/link_tap.go

278 lines
6.0 KiB
Go
Raw Normal View History

2021-06-08 20:45:26 +08:00
package handler
import (
"fmt"
2021-08-26 23:09:52 +08:00
"io"
2021-06-08 20:45:26 +08:00
"net"
"github.com/bjdgyc/anylink/base"
"github.com/bjdgyc/anylink/pkg/arpdis"
"github.com/bjdgyc/anylink/sessdata"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/songgao/packets/ethernet"
"github.com/songgao/water"
"github.com/songgao/water/waterutil"
)
const bridgeName = "anylink0"
var (
2021-08-26 23:09:52 +08:00
// 网关mac地址
gatewayHw net.HardwareAddr
2021-06-08 20:45:26 +08:00
)
2021-08-26 23:09:52 +08:00
type LinkDriver interface {
io.ReadWriteCloser
Name() string
}
func _setGateway() {
dstAddr := arpdis.Lookup(sessdata.IpPool.Ipv4Gateway, false)
gatewayHw = dstAddr.HardwareAddr
// 设置为静态地址映射
dstAddr.Type = arpdis.TypeStatic
arpdis.Add(dstAddr)
}
func _checkTapIp(ifName string) {
iFace, err := net.InterfaceByName(ifName)
2021-06-08 20:45:26 +08:00
if err != nil {
base.Fatal("testTap err: ", err)
}
2021-08-26 23:09:52 +08:00
var ifIp net.IP
addrs, err := iFace.Addrs()
2021-06-08 20:45:26 +08:00
if err != nil {
base.Fatal("testTap err: ", err)
}
for _, addr := range addrs {
ip, _, err := net.ParseCIDR(addr.String())
if err != nil || ip.To4() == nil {
continue
}
2021-08-26 23:09:52 +08:00
ifIp = ip
2021-06-08 20:45:26 +08:00
}
2021-08-26 23:09:52 +08:00
if !sessdata.IpPool.Ipv4IPNet.Contains(ifIp) {
base.Fatal("tapIp or Ip network err")
2021-06-08 20:45:26 +08:00
}
}
2021-08-26 23:09:52 +08:00
func checkTap() {
_setGateway()
_checkTapIp(bridgeName)
}
2021-06-08 20:45:26 +08:00
// 创建tap网卡
func LinkTap(cSess *sessdata.ConnSession) error {
cfg := water.Config{
DeviceType: water.TAP,
}
ifce, err := water.New(cfg)
if err != nil {
base.Error(err)
return err
}
2021-08-26 23:09:52 +08:00
cSess.SetIfName(ifce.Name())
2021-06-08 20:45:26 +08:00
cmdstr1 := fmt.Sprintf("ip link set dev %s up mtu %d multicast on", ifce.Name(), cSess.Mtu)
2021-08-02 20:41:35 +08:00
cmdstr2 := fmt.Sprintf("ip link set dev %s master %s", ifce.Name(), bridgeName)
err = execCmd([]string{cmdstr1, cmdstr2})
2021-06-08 20:45:26 +08:00
if err != nil {
base.Error(err)
_ = ifce.Close()
return err
}
2021-08-02 20:41:35 +08:00
cmdstr3 := fmt.Sprintf("sysctl -w net.ipv6.conf.%s.disable_ipv6=1", ifce.Name())
execCmd([]string{cmdstr3})
2021-08-26 23:09:52 +08:00
go allTapRead(ifce, cSess)
go allTapWrite(ifce, cSess)
2021-06-08 20:45:26 +08:00
return nil
}
2021-08-26 23:09:52 +08:00
// ========================通用代码===========================
func allTapWrite(ifce LinkDriver, cSess *sessdata.ConnSession) {
2021-06-08 20:45:26 +08:00
defer func() {
base.Debug("LinkTap return", cSess.IpAddr)
cSess.Close()
2021-08-26 23:09:52 +08:00
ifce.Close()
2021-06-08 20:45:26 +08:00
}()
var (
2021-08-02 20:41:35 +08:00
err error
2021-08-26 23:09:52 +08:00
dstHw net.HardwareAddr
2021-08-02 20:41:35 +08:00
pl *sessdata.Payload
2021-08-26 23:09:52 +08:00
frame = make(ethernet.Frame, BufferSize)
ipDst = net.IPv4(1, 2, 3, 4)
2021-06-08 20:45:26 +08:00
)
for {
2021-08-26 23:09:52 +08:00
frame.Resize(BufferSize)
2021-06-08 20:45:26 +08:00
select {
2021-08-02 20:41:35 +08:00
case pl = <-cSess.PayloadIn:
2021-06-08 20:45:26 +08:00
case <-cSess.CloseChan:
return
}
// var frame ethernet.Frame
2021-08-02 20:41:35 +08:00
switch pl.LType {
2021-06-08 20:45:26 +08:00
default:
// log.Println(payload)
case sessdata.LTypeEthernet:
2021-08-02 20:41:35 +08:00
copy(frame, pl.Data)
frame = frame[:len(pl.Data)]
2021-08-26 23:09:52 +08:00
// packet := gopacket.NewPacket(frame, layers.LayerTypeEthernet, gopacket.Default)
// fmt.Println("wirteArp:", packet)
2021-06-08 20:45:26 +08:00
case sessdata.LTypeIPData: // 需要转换成 Ethernet 数据
2021-08-26 23:09:52 +08:00
ipSrc := waterutil.IPv4Source(pl.Data)
if !ipSrc.Equal(cSess.IpAddr) {
2021-06-08 20:45:26 +08:00
// 非分配给客户端ip直接丢弃
continue
}
2021-08-26 23:09:52 +08:00
if waterutil.IsIPv6(pl.Data) {
// 过滤掉IPv6的数据
continue
}
// packet := gopacket.NewPacket(pl.Data, layers.LayerTypeIPv4, gopacket.Default)
2021-06-08 20:45:26 +08:00
// fmt.Println("get:", packet)
2021-08-26 23:09:52 +08:00
// 手动设置ipv4地址
ipDst[12] = pl.Data[16]
ipDst[13] = pl.Data[17]
ipDst[14] = pl.Data[18]
ipDst[15] = pl.Data[19]
2021-06-08 20:45:26 +08:00
2021-08-26 23:09:52 +08:00
dstHw = gatewayHw
if sessdata.IpPool.Ipv4IPNet.Contains(ipDst) {
dstAddr := arpdis.Lookup(ipDst, true)
2021-06-08 20:45:26 +08:00
// fmt.Println("dstAddr", dstAddr)
if dstAddr != nil {
dstHw = dstAddr.HardwareAddr
}
}
2021-08-26 23:09:52 +08:00
// fmt.Println("Gateway", ipSrc, ipDst, dstHw)
2021-08-02 20:41:35 +08:00
frame.Prepare(dstHw, cSess.MacHw, ethernet.NotTagged, ethernet.IPv4, len(pl.Data))
copy(frame[12+2:], pl.Data)
2021-06-08 20:45:26 +08:00
}
// packet := gopacket.NewPacket(frame, layers.LayerTypeEthernet, gopacket.Default)
// fmt.Println("write:", packet)
_, err = ifce.Write(frame)
if err != nil {
base.Error("tap Write err", err)
return
}
2023-04-26 22:17:10 +08:00
putPayloadInBefore(cSess, pl)
2021-06-08 20:45:26 +08:00
}
}
2021-08-26 23:09:52 +08:00
func allTapRead(ifce LinkDriver, cSess *sessdata.ConnSession) {
2021-06-08 20:45:26 +08:00
defer func() {
base.Debug("tapRead return", cSess.IpAddr)
2021-08-26 23:09:52 +08:00
ifce.Close()
2021-06-08 20:45:26 +08:00
}()
var (
err error
n int
2021-08-02 20:41:35 +08:00
data []byte
2021-08-26 23:09:52 +08:00
frame = make(ethernet.Frame, BufferSize)
2021-06-08 20:45:26 +08:00
)
for {
2021-08-26 23:09:52 +08:00
frame.Resize(BufferSize)
2021-06-08 20:45:26 +08:00
n, err = ifce.Read(frame)
if err != nil {
base.Error("tap Read err", n, err)
return
}
frame = frame[:n]
switch frame.Ethertype() {
default:
continue
case ethernet.IPv6:
continue
case ethernet.IPv4:
// 发送IP数据
2021-08-02 20:41:35 +08:00
data = frame.Payload()
2021-06-08 20:45:26 +08:00
ip_dst := waterutil.IPv4Destination(data)
if !ip_dst.Equal(cSess.IpAddr) {
// 过滤非本机地址
// log.Println(ip_dst, sess.Ip)
continue
}
// packet := gopacket.NewPacket(data, layers.LayerTypeIPv4, gopacket.Default)
// fmt.Println("put:", packet)
2021-08-02 20:41:35 +08:00
pl := getPayload()
// 拷贝数据到pl
copy(pl.Data, data)
// 更新切片长度
pl.Data = pl.Data[:len(data)]
if payloadOut(cSess, pl) {
2021-06-08 20:45:26 +08:00
return
}
case ethernet.ARP:
// 暂时仅实现了ARP协议
2021-08-26 23:09:52 +08:00
packet := gopacket.NewPacket(frame, layers.LayerTypeEthernet, gopacket.NoCopy)
2021-06-08 20:45:26 +08:00
layer := packet.Layer(layers.LayerTypeARP)
arpReq := layer.(*layers.ARP)
if !cSess.IpAddr.Equal(arpReq.DstProtAddress) {
// 过滤非本机地址
continue
}
2021-08-26 23:09:52 +08:00
// fmt.Println("arp", time.Now(), net.IP(arpReq.SourceProtAddress), cSess.IpAddr)
2021-06-08 20:45:26 +08:00
// fmt.Println(packet)
// 返回ARP数据
src := &arpdis.Addr{IP: cSess.IpAddr, HardwareAddr: cSess.MacHw}
2021-08-26 23:09:52 +08:00
dst := &arpdis.Addr{IP: arpReq.SourceProtAddress, HardwareAddr: arpReq.SourceHwAddress}
2021-08-02 20:41:35 +08:00
data, err = arpdis.NewARPReply(src, dst)
2021-06-08 20:45:26 +08:00
if err != nil {
base.Error(err)
return
}
// 从接受的arp信息添加arp地址
addr := &arpdis.Addr{
2021-08-26 23:09:52 +08:00
IP: append([]byte{}, dst.IP...),
HardwareAddr: append([]byte{}, dst.HardwareAddr...),
2021-06-08 20:45:26 +08:00
}
arpdis.Add(addr)
2021-08-02 20:41:35 +08:00
pl := getPayload()
// 设置为二层数据类型
pl.LType = sessdata.LTypeEthernet
// 拷贝数据到pl
copy(pl.Data, data)
// 更新切片长度
pl.Data = pl.Data[:len(data)]
if payloadIn(cSess, pl) {
2021-06-08 20:45:26 +08:00
return
}
}
}
}