mirror of
https://github.com/hbahadorzadeh/stunning.git
synced 2025-12-24 13:38:08 +08:00
157 lines
3.1 KiB
Go
157 lines
3.1 KiB
Go
package tun
|
|
|
|
import (
|
|
"github.com/songgao/water"
|
|
"gitlab.com/h.bahadorzadeh/stunning/common"
|
|
icommon "gitlab.com/h.bahadorzadeh/stunning/interface/common"
|
|
tcommon "gitlab.com/h.bahadorzadeh/stunning/tunnel/common"
|
|
"log"
|
|
"net"
|
|
"os"
|
|
"os/exec"
|
|
"time"
|
|
)
|
|
|
|
type TunInterface struct {
|
|
icommon.TunnelInterfaceServer
|
|
icommon.TunnelInterfaceClient
|
|
conf TunConfig
|
|
iface *water.Interface
|
|
stopped bool
|
|
}
|
|
|
|
type TunInterfaceClient struct {
|
|
TunInterface
|
|
address string
|
|
dialer tcommon.TunnelDialer
|
|
}
|
|
|
|
type TunConfig struct {
|
|
DevType water.DeviceType
|
|
Address string
|
|
Name string
|
|
MTU string
|
|
}
|
|
|
|
func GetTunIface(config TunConfig) TunInterface {
|
|
ifce, err := water.New(water.Config{
|
|
DeviceType: config.DevType,
|
|
})
|
|
|
|
runIP("link", "set", "dev", ifce.Name(), "mtu", config.MTU)
|
|
runIP("addr", "add", config.Address, "dev", ifce.Name())
|
|
runIP("link", "set", "dev", ifce.Name(), "up")
|
|
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
iface := TunInterface{
|
|
iface: ifce,
|
|
conf: config,
|
|
stopped: false,
|
|
}
|
|
return iface
|
|
}
|
|
|
|
func GetTunIfaceClient(config TunConfig, addr string, d tcommon.TunnelDialer) TunInterfaceClient {
|
|
ifce, err := water.New(water.Config{
|
|
DeviceType: config.DevType,
|
|
})
|
|
|
|
runIP("link", "set", "dev", ifce.Name(), "mtu", config.MTU)
|
|
runIP("addr", "add", config.Address, "dev", ifce.Name())
|
|
runIP("link", "set", "dev", ifce.Name(), "up")
|
|
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
iface := TunInterfaceClient{
|
|
address: addr,
|
|
dialer: d,
|
|
}
|
|
iface.iface = ifce
|
|
iface.conf = config
|
|
return iface
|
|
}
|
|
|
|
func (t TunInterface) HandleConnection(conn net.Conn) error {
|
|
log.Printf("Tun iface %s handling new connection \n", t.iface.Name())
|
|
go t.reader(conn)
|
|
t.writer(conn)
|
|
return nil
|
|
}
|
|
|
|
func (t TunInterface) reader(conn net.Conn) {
|
|
var frame common.Frame
|
|
|
|
for {
|
|
frame.Resize(1500)
|
|
n, err := t.iface.Read([]byte(frame))
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
frame = frame[:n]
|
|
if len(frame) == 0 {
|
|
continue
|
|
}
|
|
wn, werr := conn.Write(frame)
|
|
if werr != nil || wn != len(frame) {
|
|
log.Panicln(werr)
|
|
log.Printf("wn : %d, n: %d \n", wn, n)
|
|
}
|
|
log.Printf("%d bytes wrote to socket", wn)
|
|
}
|
|
}
|
|
|
|
func (t TunInterface) writer(conn net.Conn) {
|
|
var frame common.Frame
|
|
for {
|
|
frame.Resize(1500)
|
|
n, err := conn.Read([]byte(frame))
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
frame = frame[:n]
|
|
if len(frame) == 0 {
|
|
continue
|
|
}
|
|
wn, werr := t.iface.Write(frame)
|
|
if err != nil || wn != len(frame) {
|
|
log.Panicln(werr)
|
|
log.Printf("wn : %d, n: %d \n", wn, n)
|
|
}
|
|
log.Printf("%d bytes wrote to iface", wn)
|
|
}
|
|
}
|
|
|
|
func runIP(args ...string) {
|
|
cmd := exec.Command("/sbin/ip", args...)
|
|
cmd.Stderr = os.Stderr
|
|
cmd.Stdout = os.Stdout
|
|
cmd.Stdin = os.Stdin
|
|
err := cmd.Run()
|
|
if nil != err {
|
|
log.Fatalln("Error running /sbin/ip:", err)
|
|
}
|
|
}
|
|
|
|
func (t TunInterfaceClient) WaitingForConnection() {
|
|
conn, err := t.dialer.Dial(t.dialer.Protocol().String(), t.address)
|
|
if err == nil {
|
|
t.HandleConnection(conn)
|
|
}
|
|
}
|
|
|
|
func (t TunInterface) WaitingForConnection() {
|
|
for !t.stopped{
|
|
time.Sleep(time.Second)
|
|
}
|
|
}
|
|
|
|
|
|
func (t TunInterface) Close() error {
|
|
t.stopped = true
|
|
return nil
|
|
} |