| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277 |
- package handler
- import (
- "fmt"
- "io"
- "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 (
- // 网关mac地址
- gatewayHw net.HardwareAddr
- )
- 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)
- if err != nil {
- base.Fatal("testTap err: ", err)
- }
- var ifIp net.IP
- addrs, err := iFace.Addrs()
- 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
- }
- ifIp = ip
- }
- if !sessdata.IpPool.Ipv4IPNet.Contains(ifIp) {
- base.Fatal("tapIp or Ip network err")
- }
- }
- func checkTap() {
- _setGateway()
- _checkTapIp(bridgeName)
- }
- // 创建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
- }
- cSess.SetIfName(ifce.Name())
- cmdstr1 := fmt.Sprintf("ip link set dev %s up mtu %d multicast on", ifce.Name(), cSess.Mtu)
- cmdstr2 := fmt.Sprintf("ip link set dev %s master %s", ifce.Name(), bridgeName)
- err = execCmd([]string{cmdstr1, cmdstr2})
- if err != nil {
- base.Error(err)
- _ = ifce.Close()
- return err
- }
- cmdstr3 := fmt.Sprintf("sysctl -w net.ipv6.conf.%s.disable_ipv6=1", ifce.Name())
- execCmd([]string{cmdstr3})
- go allTapRead(ifce, cSess)
- go allTapWrite(ifce, cSess)
- return nil
- }
- // ========================通用代码===========================
- func allTapWrite(ifce LinkDriver, cSess *sessdata.ConnSession) {
- defer func() {
- base.Debug("LinkTap return", cSess.IpAddr)
- cSess.Close()
- ifce.Close()
- }()
- var (
- err error
- dstHw net.HardwareAddr
- pl *sessdata.Payload
- frame = make(ethernet.Frame, BufferSize)
- ipDst = net.IPv4(1, 2, 3, 4)
- )
- for {
- frame.Resize(BufferSize)
- select {
- case pl = <-cSess.PayloadIn:
- case <-cSess.CloseChan:
- return
- }
- // var frame ethernet.Frame
- switch pl.LType {
- default:
- // log.Println(payload)
- case sessdata.LTypeEthernet:
- copy(frame, pl.Data)
- frame = frame[:len(pl.Data)]
- // packet := gopacket.NewPacket(frame, layers.LayerTypeEthernet, gopacket.Default)
- // fmt.Println("wirteArp:", packet)
- case sessdata.LTypeIPData: // 需要转换成 Ethernet 数据
- ipSrc := waterutil.IPv4Source(pl.Data)
- if !ipSrc.Equal(cSess.IpAddr) {
- // 非分配给客户端ip,直接丢弃
- continue
- }
- if waterutil.IsIPv6(pl.Data) {
- // 过滤掉IPv6的数据
- continue
- }
- // packet := gopacket.NewPacket(pl.Data, layers.LayerTypeIPv4, gopacket.Default)
- // fmt.Println("get:", packet)
- // 手动设置ipv4地址
- ipDst[12] = pl.Data[16]
- ipDst[13] = pl.Data[17]
- ipDst[14] = pl.Data[18]
- ipDst[15] = pl.Data[19]
- dstHw = gatewayHw
- if sessdata.IpPool.Ipv4IPNet.Contains(ipDst) {
- dstAddr := arpdis.Lookup(ipDst, true)
- // fmt.Println("dstAddr", dstAddr)
- if dstAddr != nil {
- dstHw = dstAddr.HardwareAddr
- }
- }
- // fmt.Println("Gateway", ipSrc, ipDst, dstHw)
- frame.Prepare(dstHw, cSess.MacHw, ethernet.NotTagged, ethernet.IPv4, len(pl.Data))
- copy(frame[12+2:], pl.Data)
- }
- // 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
- }
- putPayloadInBefore(cSess, pl)
- }
- }
- func allTapRead(ifce LinkDriver, cSess *sessdata.ConnSession) {
- defer func() {
- base.Debug("tapRead return", cSess.IpAddr)
- ifce.Close()
- }()
- var (
- err error
- n int
- data []byte
- frame = make(ethernet.Frame, BufferSize)
- )
- for {
- frame.Resize(BufferSize)
- 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数据
- data = frame.Payload()
- 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)
- pl := getPayload()
- // 拷贝数据到pl
- copy(pl.Data, data)
- // 更新切片长度
- pl.Data = pl.Data[:len(data)]
- if payloadOut(cSess, pl) {
- return
- }
- case ethernet.ARP:
- // 暂时仅实现了ARP协议
- packet := gopacket.NewPacket(frame, layers.LayerTypeEthernet, gopacket.NoCopy)
- layer := packet.Layer(layers.LayerTypeARP)
- arpReq := layer.(*layers.ARP)
- if !cSess.IpAddr.Equal(arpReq.DstProtAddress) {
- // 过滤非本机地址
- continue
- }
- // fmt.Println("arp", time.Now(), net.IP(arpReq.SourceProtAddress), cSess.IpAddr)
- // fmt.Println(packet)
- // 返回ARP数据
- src := &arpdis.Addr{IP: cSess.IpAddr, HardwareAddr: cSess.MacHw}
- dst := &arpdis.Addr{IP: arpReq.SourceProtAddress, HardwareAddr: arpReq.SourceHwAddress}
- data, err = arpdis.NewARPReply(src, dst)
- if err != nil {
- base.Error(err)
- return
- }
- // 从接受的arp信息添加arp地址
- addr := &arpdis.Addr{
- IP: append([]byte{}, dst.IP...),
- HardwareAddr: append([]byte{}, dst.HardwareAddr...),
- }
- arpdis.Add(addr)
- pl := getPayload()
- // 设置为二层数据类型
- pl.LType = sessdata.LTypeEthernet
- // 拷贝数据到pl
- copy(pl.Data, data)
- // 更新切片长度
- pl.Data = pl.Data[:len(data)]
- if payloadIn(cSess, pl) {
- return
- }
- }
- }
- }
|