dockerfiles/anylink/server/handler/link_tun.go

150 lines
3.3 KiB
Go

package handler
import (
"fmt"
"github.com/bjdgyc/anylink/base"
"github.com/bjdgyc/anylink/sessdata"
"github.com/coreos/go-iptables/iptables"
"github.com/songgao/water"
)
func checkTun() {
// 测试tun
cfg := water.Config{
DeviceType: water.TUN,
}
ifce, err := water.New(cfg)
if err != nil {
base.Fatal("open tun err: ", err)
}
defer ifce.Close()
// 测试ip命令
cmdstr := fmt.Sprintf("ip link set dev %s up mtu %s multicast off", ifce.Name(), "1399")
err = execCmd([]string{cmdstr})
if err != nil {
base.Fatal("testTun err: ", err)
}
//开启服务器转发
if err := execCmd([]string{"sysctl -w net.ipv4.ip_forward=1"}); err != nil {
base.Error(err)
}
if base.Cfg.IptablesNat {
//添加NAT转发规则
ipt, err := iptables.New()
if err != nil {
base.Error(err)
return
}
natRule := []string{"-s", base.Cfg.Ipv4CIDR, "-o", base.Cfg.Ipv4Master, "-j", "MASQUERADE"}
forwardRule := []string{"-j", "ACCEPT"}
if natExists, _ := ipt.Exists("nat", "POSTROUTING", natRule...); !natExists {
ipt.Insert("nat", "POSTROUTING", 1, natRule...)
}
if forwardExists, _ := ipt.Exists("filter", "FORWARD", forwardRule...); !forwardExists {
ipt.Insert("filter", "FORWARD", 1, forwardRule...)
}
base.Info(ipt.List("nat", "POSTROUTING"))
base.Info(ipt.List("filter", "FORWARD"))
}
}
// 创建tun网卡
func LinkTun(cSess *sessdata.ConnSession) error {
cfg := water.Config{
DeviceType: water.TUN,
}
ifce, err := water.New(cfg)
if err != nil {
base.Error(err)
return err
}
// log.Printf("Interface Name: %s\n", ifce.Name())
cSess.SetIfName(ifce.Name())
cmdstr1 := fmt.Sprintf("ip link set dev %s up mtu %d multicast off", ifce.Name(), cSess.Mtu)
cmdstr2 := fmt.Sprintf("ip addr add dev %s local %s peer %s/32",
ifce.Name(), base.Cfg.Ipv4Gateway, cSess.IpAddr)
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 tunRead(ifce, cSess)
go tunWrite(ifce, cSess)
return nil
}
func tunWrite(ifce *water.Interface, cSess *sessdata.ConnSession) {
defer func() {
base.Debug("LinkTun return", cSess.IpAddr)
cSess.Close()
_ = ifce.Close()
}()
var (
err error
pl *sessdata.Payload
)
for {
select {
case pl = <-cSess.PayloadIn:
case <-cSess.CloseChan:
return
}
_, err = ifce.Write(pl.Data)
if err != nil {
base.Error("tun Write err", err)
return
}
putPayloadInBefore(cSess, pl)
}
}
func tunRead(ifce *water.Interface, cSess *sessdata.ConnSession) {
defer func() {
base.Debug("tunRead return", cSess.IpAddr)
_ = ifce.Close()
}()
var (
err error
n int
)
for {
// data := make([]byte, BufferSize)
pl := getPayload()
n, err = ifce.Read(pl.Data)
if err != nil {
base.Error("tun Read err", n, err)
return
}
// 更新数据长度
pl.Data = (pl.Data)[:n]
// data = data[:n]
// ip_src := waterutil.IPv4Source(data)
// ip_dst := waterutil.IPv4Destination(data)
// ip_port := waterutil.IPv4DestinationPort(data)
// fmt.Println("sent:", ip_src, ip_dst, ip_port)
// packet := gopacket.NewPacket(data, layers.LayerTypeIPv4, gopacket.Default)
// fmt.Println("read:", packet)
if payloadOut(cSess, pl) {
return
}
}
}