尝试整个网络代理 以netstack为代理服务器,想实现网络通信的server调用特殊的api代理,要如何避开内核网络栈呢?

This commit is contained in:
impact-eintr
2022-11-30 18:38:50 +08:00
parent 7b3086540d
commit 3d8ca3c0c8
5 changed files with 273 additions and 100 deletions

215
cmd/netstack/main.go Normal file
View File

@@ -0,0 +1,215 @@
package main
import (
"encoding/binary"
"flag"
"io"
"log"
"net"
"netstack/tcpip"
"netstack/tcpip/header"
"netstack/tcpip/link/fdbased"
"netstack/tcpip/link/tuntap"
"netstack/tcpip/network/arp"
"netstack/tcpip/network/ipv4"
"netstack/tcpip/network/ipv6"
"netstack/tcpip/stack"
"netstack/tcpip/transport/udp"
"netstack/waiter"
"os"
"strings"
)
var mac = flag.String("mac", "01:01:01:01:01:01", "mac address to use in tap device")
func main() {
flag.Parse()
if len(flag.Args()) != 2 {
log.Fatal("Usage: ", os.Args[0], " <tap-device> <listen-address>")
}
log.SetFlags(log.Lshortfile | log.LstdFlags)
tapName := flag.Arg(0)
listeAddr := flag.Arg(1)
log.Printf("tap: %v, listeAddr: %v", tapName, listeAddr)
// Parse the mac address.
maddr, err := net.ParseMAC(*mac)
if err != nil {
log.Fatalf("Bad MAC address: %v", *mac)
}
parsedAddr := net.ParseIP(listeAddr)
// 解析地址ip地址ipv4或者ipv6地址都支持
var addr tcpip.Address
var proto tcpip.NetworkProtocolNumber
if parsedAddr.To4() != nil {
addr = tcpip.Address(parsedAddr.To4())
proto = ipv4.ProtocolNumber
} else if parsedAddr.To16() != nil {
addr = tcpip.Address(parsedAddr.To16())
proto = ipv6.ProtocolNumber
} else {
log.Fatalf("Unknown IP type: %v", parsedAddr)
}
// 虚拟网卡配置
conf := &tuntap.Config{
Name: tapName,
Mode: tuntap.TAP,
}
var fd int
// 新建虚拟网卡
fd, err = tuntap.NewNetDev(conf)
if err != nil {
log.Fatal(err)
}
// 启动tap网卡
_ = tuntap.SetLinkUp(tapName)
// 设置tap网卡IP地址
_ = tuntap.AddIP(tapName, listeAddr)
// 抽象网卡的文件接口
linkID := fdbased.New(&fdbased.Options{
FD: fd,
MTU: 1500,
Address: tcpip.LinkAddress(maddr),
})
// 新建相关协议的协议栈
s := stack.New([]string{ipv4.ProtocolName, arp.ProtocolName},
[]string{ /*tcp.ProtocolName, */ udp.ProtocolName}, stack.Options{})
// 新建抽象的网卡
if err := s.CreateNamedNIC(1, "vnic1", linkID); err != nil {
log.Fatal(err)
}
// 在该协议栈上添加和注册相应的网络层
if err := s.AddAddress(1, proto, addr); err != nil {
log.Fatal(err)
}
// 在该协议栈上添加和注册ARP协议
if err := s.AddAddress(1, arp.ProtocolNumber, arp.ProtocolAddress); err != nil {
log.Fatal(err)
}
// 添加默认路由
s.SetRouteTable([]tcpip.Route{
{
Destination: tcpip.Address(strings.Repeat("\x00", len(addr))),
Mask: tcpip.AddressMask(strings.Repeat("\x00", len(addr))),
Gateway: "",
NIC: 1,
},
})
conn, _ := net.Listen("tcp", "0.0.0.0:9999")
TCPServer(conn, &RCV{s, nil, nil})
// 同时监听tcp和udp localPort端口
//tcpEp := tcpListen(s, proto, localPort)
//udpEp := udpListen(s, proto, localPort)
// 关闭监听服务,此时会释放端口
//tcpEp.Close()
//udpEp.Close()
}
//func tcpListen(s *stack.Stack, proto tcpip.NetworkProtocolNumber, localPort int) tcpip.Endpoint {
// var wq waiter.Queue
// // 新建一个tcp端
// ep, err := s.NewEndpoint(tcp.ProtocolNumber, proto, &wq)
// if err != nil {
// log.Fatal(err)
// }
//
// // 绑定IP和端口这里的IP地址为空表示绑定任何IP
// // 此时就会调用端口管理器
// if err := ep.Bind(tcpip.FullAddress{0, "", uint16(localPort)}, nil); err != nil {
// log.Fatal("Bind failed: ", err)
// }
//
// // 开始监听
// if err := ep.Listen(10); err != nil {
// log.Fatal("Listen failed: ", err)
// }
//
// return ep
//}
func udpListen(s *stack.Stack, proto tcpip.NetworkProtocolNumber, localPort int) tcpip.Endpoint {
var wq waiter.Queue
// 新建一个udp端
ep, err := s.NewEndpoint(udp.ProtocolNumber, proto, &wq)
if err != nil {
log.Fatal(err)
}
// 绑定IP和端口这里的IP地址为空表示绑定任何IP
// 0.0.0.0:9999 这台机器上的所有ip的9999段端口数据都会使用该传输层实现
// 此时就会调用端口管理器
if err := ep.Bind(tcpip.FullAddress{NIC: 0, Addr: "", Port: uint16(localPort)}, nil); err != nil {
log.Fatal("Bind failed: ", err)
}
if err := ep.Connect(tcpip.FullAddress{NIC: 0, Addr: "", Port: uint16(localPort)}); err != nil {
log.Fatal("Conn failed: ", err)
}
// 注意UDP是无连接的它不需要Listen
return ep
}
type RCV struct {
*stack.Stack
ep tcpip.Endpoint
rcvBuf []byte
}
var transportPool = make(map[uint64]tcpip.Endpoint)
func (r *RCV) Handle(conn net.Conn) {
var err error
r.rcvBuf, err = io.ReadAll(conn)
if err != nil && len(r.rcvBuf) < 9 { // proto + ip + port
panic(err)
}
switch string(r.rcvBuf[:3]) {
case "udp":
var wq waiter.Queue
// 新建一个udp端
ep, err := r.NewEndpoint(udp.ProtocolNumber, header.IPv4ProtocolNumber, &wq)
if err != nil {
log.Fatal(err)
}
r.ep = ep
r.Bind()
r.Close()
case "tcp":
default:
return
}
}
func (r *RCV) Bind() {
if len(r.rcvBuf) < 9 { // udp ip port
log.Println("Error: too few arg")
return
}
port := binary.BigEndian.Uint16(r.rcvBuf[7:9])
addr := tcpip.FullAddress{
NIC: 0,
Addr: tcpip.Address(r.rcvBuf[3:7]),
Port: port,
}
r.ep.Bind(addr, nil)
}
func (r *RCV) Close() {
r.ep.Close()
}

View File

@@ -0,0 +1,38 @@
package main
import (
"fmt"
"log"
"net"
"runtime"
"strings"
)
type TCPHandler interface {
Handle(net.Conn)
}
func TCPServer(listener net.Listener, handler TCPHandler) error {
log.Printf("netstack 网络解析地址: %s", listener.Addr())
for {
clientConn, err := listener.Accept()
if err != nil {
if nerr, ok := err.(net.Error); ok && nerr.Temporary() {
log.Printf("temporary Accept() failure - %s", err)
runtime.Gosched()
continue
}
// theres no direct way to detect this error because it is not exposed
if !strings.Contains(err.Error(), "use of closed network connection") {
return fmt.Errorf("listener.Accept() error - %s", err)
}
break
}
go handler.Handle(clientConn)
}
log.Printf("TCP: closing %s", listener.Addr())
return nil
}

View File

@@ -5,120 +5,32 @@ import (
"log"
"net"
"netstack/tcpip"
"netstack/tcpip/link/fdbased"
"netstack/tcpip/link/tuntap"
"netstack/tcpip/network/arp"
"netstack/tcpip/network/ipv4"
"netstack/tcpip/network/ipv6"
"netstack/tcpip/stack"
"netstack/tcpip/transport/udp"
"netstack/waiter"
"os"
"strconv"
"strings"
)
var mac = flag.String("mac", "01:01:01:01:01:01", "mac address to use in tap device")
func main() {
flag.Parse()
if len(flag.Args()) != 3 {
log.Fatal("Usage: ", os.Args[0], " <tap-device> <listen-address> port")
if len(flag.Args()) != 2 {
log.Fatal("Usage: ", os.Args[0], "<listen-address> port")
}
log.SetFlags(log.Lshortfile | log.LstdFlags)
tapName := flag.Arg(0)
listeAddr := flag.Arg(1)
portName := flag.Arg(2)
listeAddr := flag.Arg(0)
portName := flag.Arg(1)
log.Printf("tap: %v, listeAddr: %v, portName: %v", tapName, listeAddr, portName)
Socket(listeAddr + ":" + portName)
}
// Parse the mac address.
maddr, err := net.ParseMAC(*mac)
func Socket(addr string) {
conn, err := net.Dial("tcp", addr)
if err != nil {
log.Fatalf("Bad MAC address: %v", *mac)
panic(err)
}
parsedAddr := net.ParseIP(listeAddr)
// 解析地址ip地址ipv4或者ipv6地址都支持
var addr tcpip.Address
var proto tcpip.NetworkProtocolNumber
if parsedAddr.To4() != nil {
addr = tcpip.Address(parsedAddr.To4())
proto = ipv4.ProtocolNumber
} else if parsedAddr.To16() != nil {
addr = tcpip.Address(parsedAddr.To16())
proto = ipv6.ProtocolNumber
} else {
log.Fatalf("Unknown IP type: %v", parsedAddr)
}
localPort, err := strconv.Atoi(portName)
if err != nil {
log.Fatalf("Unable to convert port %v: %v", portName, err)
}
// 虚拟网卡配置
conf := &tuntap.Config{
Name: tapName,
Mode: tuntap.TAP,
}
var fd int
// 新建虚拟网卡
fd, err = tuntap.NewNetDev(conf)
if err != nil {
log.Fatal(err)
}
// 启动tap网卡
_ = tuntap.SetLinkUp(tapName)
// 设置tap网卡IP地址
_ = tuntap.AddIP(tapName, listeAddr)
// 抽象网卡的文件接口
linkID := fdbased.New(&fdbased.Options{
FD: fd,
MTU: 1500,
Address: tcpip.LinkAddress(maddr),
})
// 新建相关协议的协议栈
s := stack.New([]string{ipv4.ProtocolName, arp.ProtocolName},
[]string{ /*tcp.ProtocolName, */ udp.ProtocolName}, stack.Options{})
// 新建抽象的网卡
if err := s.CreateNamedNIC(1, "vnic1", linkID); err != nil {
log.Fatal(err)
}
// 在该协议栈上添加和注册相应的网络层
if err := s.AddAddress(1, proto, addr); err != nil {
log.Fatal(err)
}
// 在该协议栈上添加和注册ARP协议
if err := s.AddAddress(1, arp.ProtocolNumber, arp.ProtocolAddress); err != nil {
log.Fatal(err)
}
// 添加默认路由
s.SetRouteTable([]tcpip.Route{
{
Destination: tcpip.Address(strings.Repeat("\x00", len(addr))),
Mask: tcpip.AddressMask(strings.Repeat("\x00", len(addr))),
Gateway: "",
NIC: 1,
},
})
// 同时监听tcp和udp localPort端口
//tcpEp := tcpListen(s, proto, localPort)
udpEp := udpListen(s, proto, localPort)
// 关闭监听服务,此时会释放端口
//tcpEp.Close()
udpEp.Close()
conn.Write([]byte("udp\xc0\xa8\x01\x01\x27\x0f")) // bind udp 192.168.1.1 9999
conn.Close()
}
//func tcpListen(s *stack.Stack, proto tcpip.NetworkProtocolNumber, localPort int) tcpip.Endpoint {

View File

@@ -76,6 +76,7 @@ type Options struct {
Stats tcpip.Stats
}
// New 新建一个网络协议栈
func New(network []string, transport []string, opts Options) *Stack {
clock := opts.Clock
if clock == nil {
@@ -115,7 +116,9 @@ func New(network []string, transport []string, opts Options) *Stack {
proto: transProto,
}
}
// TODO 添加传输层分流器
// 添加传输层分流器
s.demux = newTransportDemuxer(s)
return s
}

View File

@@ -21,3 +21,8 @@ type transportEndpoints struct {
type transportDemuxer struct {
protocol map[protocolIDs]*transportEndpoints
}
// 新建一个分流器
func newTransportDemuxer(stacl *Stack) *transportDemuxer {
return nil
}