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
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-02 20:41:35 +08:00
|
|
|
|
putPayload(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
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|