mirror of
https://github.com/e1732a364fed/v2ray_simple.git
synced 2025-10-07 09:41:07 +08:00

不再使用 UDP_Putter 等机制去转发udp,而是用一个 netLayer.MsgConn 结构 proxy.Server 和 proxy.Client 接口改动, Client在握手udp时不再使用handshake方法, 而是用新的 EstablishUDPChannel 方法 Server 在 Handshake时会选择性返回两种接口,io.ReadWriteCloser 用于tcp, netLayer.MsgConn 用于 udp 此时vless、socks5、direct 的udp转发都已经成功经过了 go test 验证, 但是 main.go 还未修改。
138 lines
3.0 KiB
Go
138 lines
3.0 KiB
Go
/*
|
||
Package netLayer contains definitions in network layer AND transport layer.
|
||
|
||
本包有 geoip, readv, relay, route, udp, splice 等相关功能。
|
||
|
||
以后如果要添加 kcp 或 raw socket 等底层协议时,或者要控制tcp/udp拨号的细节时,也要在此包里实现.
|
||
|
||
*/
|
||
package netLayer
|
||
|
||
import (
|
||
"io"
|
||
"log"
|
||
"net"
|
||
"syscall"
|
||
|
||
"github.com/hahahrfool/v2ray_simple/utils"
|
||
"go.uber.org/zap"
|
||
)
|
||
|
||
var (
|
||
// 如果机器没有ipv6地址, 就无法联通ipv6, 此时可以在dial时更快拒绝ipv6地址,
|
||
// 避免打印过多错误输出
|
||
machineCanConnectToIpv6 bool
|
||
|
||
ErrMachineCantConnectToIpv6 = utils.NumErr{Prefix: "ErrMachineCanConnectToIpv6"}
|
||
)
|
||
|
||
//做一些网络层的资料准备工作, 可以优化本包其它函数的调用。
|
||
func Prepare() {
|
||
machineCanConnectToIpv6 = HasIpv6Interface()
|
||
}
|
||
|
||
func HasIpv6Interface() bool {
|
||
|
||
if utils.LogLevel == utils.Log_debug {
|
||
log.Println("HasIpv6Interface called")
|
||
}
|
||
|
||
addrs, err := net.InterfaceAddrs()
|
||
if err != nil {
|
||
if utils.ZapLogger != nil {
|
||
if ce := utils.CanLogErr("call net.InterfaceAddrs failed"); ce != nil {
|
||
ce.Write(zap.Error(err))
|
||
}
|
||
} else {
|
||
log.Println("call net.InterfaceAddrs failed", err)
|
||
}
|
||
|
||
return false
|
||
}
|
||
|
||
for _, address := range addrs {
|
||
if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() && !ipnet.IP.IsPrivate() && !ipnet.IP.IsLinkLocalUnicast() {
|
||
// IsLinkLocalUnicast: something starts with fe80:
|
||
// According to godoc, If ip is not an IPv4 address, To4 returns nil.
|
||
// This means it's ipv6
|
||
if ipnet.IP.To4() == nil {
|
||
return true
|
||
}
|
||
}
|
||
}
|
||
return false
|
||
}
|
||
|
||
//net.IPConn, net.TCPConn, net.UDPConn, net.UnixConn
|
||
func IsBasicConn(r interface{}) bool {
|
||
if _, ok := r.(syscall.Conn); ok {
|
||
return true
|
||
}
|
||
|
||
return false
|
||
}
|
||
|
||
func GetRawConn(reader io.Reader) syscall.RawConn {
|
||
if sc, ok := reader.(syscall.Conn); ok {
|
||
rawConn, err := sc.SyscallConn()
|
||
if err != nil {
|
||
if ce := utils.CanLogDebug("can't convert syscall.Conn to syscall.RawConn"); ce != nil {
|
||
ce.Write(zap.Any("reader", reader), zap.Error(err))
|
||
}
|
||
return nil
|
||
}
|
||
return rawConn
|
||
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
//"udp", "udp4", "udp6"
|
||
func IsStrUDP_network(s string) bool {
|
||
switch s {
|
||
case "udp", "udp4", "udp6":
|
||
return true
|
||
}
|
||
return false
|
||
}
|
||
|
||
//使用Addr,是因为有可能申请的是域名,而不是ip
|
||
type MsgConn interface {
|
||
ReadFrom() ([]byte, Addr, error)
|
||
WriteTo([]byte, Addr) error
|
||
}
|
||
|
||
type UDPMsgConnWrapper struct {
|
||
*net.UDPConn
|
||
IsClient bool
|
||
FirstAddr Addr
|
||
}
|
||
|
||
func (u *UDPMsgConnWrapper) ReadFrom() ([]byte, Addr, error) {
|
||
bs := utils.GetPacket()
|
||
n, ad, err := u.UDPConn.ReadFromUDP(bs)
|
||
if err != nil {
|
||
return nil, Addr{}, err
|
||
}
|
||
return bs[:n], NewAddrFromUDPAddr(ad), err
|
||
}
|
||
|
||
func (u *UDPMsgConnWrapper) WriteTo(bs []byte, ad Addr) error {
|
||
|
||
if u.IsClient {
|
||
if ad.GetHashable() == u.FirstAddr.GetHashable() {
|
||
_, err := u.UDPConn.Write(bs)
|
||
return err
|
||
} else {
|
||
|
||
return utils.ErrNotImplemented
|
||
}
|
||
} else {
|
||
_, err := u.UDPConn.WriteTo(bs, ad.ToUDPAddr())
|
||
return err
|
||
|
||
}
|
||
|
||
}
|