mirror of
https://github.com/impact-eintr/netstack.git
synced 2025-10-06 13:26:49 +08:00
尝试整个网络代理 以netstack为代理服务器,想实现网络通信的server调用特殊的api代理,要如何避开内核网络栈呢?
This commit is contained in:
215
cmd/netstack/main.go
Normal file
215
cmd/netstack/main.go
Normal 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()
|
||||||
|
}
|
38
cmd/netstack/tcp_server.go
Normal file
38
cmd/netstack/tcp_server.go
Normal 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
|
||||||
|
}
|
110
cmd/udp/main.go
110
cmd/udp/main.go
@@ -5,120 +5,32 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"netstack/tcpip"
|
"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/stack"
|
||||||
"netstack/tcpip/transport/udp"
|
"netstack/tcpip/transport/udp"
|
||||||
"netstack/waiter"
|
"netstack/waiter"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var mac = flag.String("mac", "01:01:01:01:01:01", "mac address to use in tap device")
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
if len(flag.Args()) != 3 {
|
if len(flag.Args()) != 2 {
|
||||||
log.Fatal("Usage: ", os.Args[0], " <tap-device> <listen-address> port")
|
log.Fatal("Usage: ", os.Args[0], "<listen-address> port")
|
||||||
}
|
}
|
||||||
|
|
||||||
log.SetFlags(log.Lshortfile | log.LstdFlags)
|
log.SetFlags(log.Lshortfile | log.LstdFlags)
|
||||||
tapName := flag.Arg(0)
|
listeAddr := flag.Arg(0)
|
||||||
listeAddr := flag.Arg(1)
|
portName := flag.Arg(1)
|
||||||
portName := flag.Arg(2)
|
|
||||||
|
|
||||||
log.Printf("tap: %v, listeAddr: %v, portName: %v", tapName, listeAddr, portName)
|
Socket(listeAddr + ":" + portName)
|
||||||
|
}
|
||||||
|
|
||||||
// Parse the mac address.
|
func Socket(addr string) {
|
||||||
maddr, err := net.ParseMAC(*mac)
|
conn, err := net.Dial("tcp", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Bad MAC address: %v", *mac)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
conn.Write([]byte("udp\xc0\xa8\x01\x01\x27\x0f")) // bind udp 192.168.1.1 9999
|
||||||
parsedAddr := net.ParseIP(listeAddr)
|
conn.Close()
|
||||||
|
|
||||||
// 解析地址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()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//func tcpListen(s *stack.Stack, proto tcpip.NetworkProtocolNumber, localPort int) tcpip.Endpoint {
|
//func tcpListen(s *stack.Stack, proto tcpip.NetworkProtocolNumber, localPort int) tcpip.Endpoint {
|
||||||
|
@@ -76,6 +76,7 @@ type Options struct {
|
|||||||
Stats tcpip.Stats
|
Stats tcpip.Stats
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// New 新建一个网络协议栈
|
||||||
func New(network []string, transport []string, opts Options) *Stack {
|
func New(network []string, transport []string, opts Options) *Stack {
|
||||||
clock := opts.Clock
|
clock := opts.Clock
|
||||||
if clock == nil {
|
if clock == nil {
|
||||||
@@ -115,7 +116,9 @@ func New(network []string, transport []string, opts Options) *Stack {
|
|||||||
proto: transProto,
|
proto: transProto,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO 添加传输层分流器
|
// 添加传输层分流器
|
||||||
|
s.demux = newTransportDemuxer(s)
|
||||||
|
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -21,3 +21,8 @@ type transportEndpoints struct {
|
|||||||
type transportDemuxer struct {
|
type transportDemuxer struct {
|
||||||
protocol map[protocolIDs]*transportEndpoints
|
protocol map[protocolIDs]*transportEndpoints
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 新建一个分流器
|
||||||
|
func newTransportDemuxer(stacl *Stack) *transportDemuxer {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user