netLayer

package
v1.1.9-alpha.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 25, 2022 License: MIT Imports: 38 Imported by: 0

Documentation

Overview

Package netLayer contains definitions in network layer AND transport layer.

本包有 geoip, geosite, udp, readv, splice, relay, route, dns 等相关功能。

以后如果要添加 kcp 或 raw socket 等底层协议时,或者要控制tcp/udp拨号的细节时,也要在此包里实现.

Index

Constants

View Source
const (
	AtypIP4    byte = 1
	AtypDomain byte = 2
	AtypIP6    byte = 3
)

Atyp, for vless and vmess; 注意与 trojan和socks5的区别,trojan和socks5的相同含义的值是1,3,4

View Source
const (
	TCP uint16 = 1 << iota
	UDP
	UNIX //unix domain socket
	Raw_socket
	KCP
	Quic //quic是一个横跨多个层的协议,这里也算一个,毕竟与kcp类似

)
View Source
const (
	ReadvSingleBufLen = 4096

	DefaultReadvOption = true
)
View Source
const (
	MaxUDP_packetLen = 64 * 1024 // 关于 udp包数据长度,可参考 https://cloud.tencent.com/developer/article/1021196

)
View Source
const SystemCanSplice = runtime.GOARCH != "wasm" && runtime.GOOS != "windows"

Variables

View Source
var (
	ErrMachineCantConnectToIpv6 = errors.New("ErrMachineCanConnectToIpv6")
	ErrTimeout                  = errors.New("timeout")
)
View Source
var ErrRecursion = errors.New("multiple recursion not allowed")
View Source
var (
	GeoipFileName string //若运行程序指定了 geoip 参数,则该值为给定值;否则默认会被init为 GeoLite2-Country.mmdb
)
View Source
var GeositeListMap = make(map[string]*GeositeList)
View Source
var (
	//udp不能无限监听, 否则每一个udp申请都对应打开了一个本地udp端口,一直监听的话时间一长,就会导致 too many open files
	// 因为实际上udp在网页代理中主要用于dns请求, 所以不妨设的小一点。
	// 放心,只要能持续不断地从远程服务器收到数据, 建立的udp连接就会持续地更新Deadline 而续命一段时间.
	UDP_timeout = time.Minute * 3
)
View Source
var (
	UseReadv bool
)

Functions

func ATypeToSocks5Standard

func ATypeToSocks5Standard(atype byte) byte

默认netLayer的 AType (AtypIP4,AtypIP6,AtypDomain) 遵循v2ray标准的定义; 如果需要符合 socks5/trojan标准, 需要用本函数转换一下。 即从 123 转换到 134

func CanSpliceDirectly

func CanSpliceDirectly(r any) bool

这里认为能 splice 或 sendfile的 都算,具体可参考go标准代码的实现, 总之就是tcp和 unix domain socket 可以. 若不是基本Conn,则会试图转换为Splicer并获取底层Conn

func CanSpliceEventually

func CanSpliceEventually(r any) bool

func ClassicCopy

func ClassicCopy(w io.Writer, r io.Reader) (written int64, err error)

拷贝自 io.CopyBuffer。 因为原始的 CopyBuffer会又调用ReadFrom, 如果splice调用的话会产生无限递归。

这里删掉了ReadFrom, 直接进行经典拷贝

func DNSQuery

func DNSQuery(domain string, dns_type uint16, conn *dns.Conn, theMux *sync.Mutex, recursionCount int) (net.IP, error)

domain必须是 dns.Fqdn 函数 包过的, 本函数不检查是否包过。如果不包过就传入,会报错。 dns_type 为 miekg/dns 包中定义的类型, 如 TypeA, TypeAAAA, TypeCNAME. conn是一个建立好的 dns.Conn, 必须非空, 本函数不检查. theMux是与 conn相匹配的mutex, 这是为了防止同时有多个请求导致无法对口;内部若判断为nil,会主动使用一个全局mux. recursionCount 使用者统一填0 即可,用于内部 遇到cname时进一步查询时防止无限递归.

如果从conn中Read后成功返回, 则可能返回如下几种错误 os.ErrNotExist (表示查无此记录), dns.ErrRcode (表示dns返回的 Rcode 不是 dns.RcodeSuccess), ErrRecursion, 如果不是这三个error, 那就是 从 该 conn 读取数据时出错了.

func DialDnsAddr

func DialDnsAddr(addr *Addr) (conn net.Conn, err error)

建立一个与dns服务器连接, 可为纯udp的dns, 或者 DoT的. 如果是DoT的, 则要求 addr.Network == "tls", 如果是纯udp的,要求 addr.IsUDP() == true

func DownloadCommunity_DomainListFiles

func DownloadCommunity_DomainListFiles(proxyurl string)

DownloadCommunity_DomainListFiles 从 v2fly/domain-list-community 下载数据文件, 并放到 geosite文件夹中。 如果已存在geosite文件夹,return immediately.

该函数适用于系统中没有git的情况, 如果有git我们直接 git clone就行了,而且还能不断pull进行滚动更新

func GetIP_ISO

func GetIP_ISO(ip net.IP) string

使用默认的 geoip文件,会调用 GetIP_ISO_byReader

func GetIP_ISO_byReader

func GetIP_ISO_byReader(db *maxminddb.Reader, ip net.IP) string

返回 iso 3166 字符串, 见 https://dev.maxmind.com/geoip/legacy/codes?lang=en ,大写,两字节

func GetRandLocalAddr

func GetRandLocalAddr(mustValid, isudp bool) string

func GetRandLocalPrivateAddr

func GetRandLocalPrivateAddr(mustValid, isudp bool) string

func GetRawConn

func GetRawConn(reader io.Reader) syscall.RawConn

func HasEmbedGeoip

func HasEmbedGeoip() bool

func HasFullOrSubDomain

func HasFullOrSubDomain(domain string, ds DomainHaser) bool

会以点号分裂domain判断每一个子域名是否被包含,最终会试图匹配整个字符串.

func HasIpv6Interface

func HasIpv6Interface() bool

func IsBasicConn

func IsBasicConn(r interface{}) bool

net.IPConn, net.TCPConn, net.UDPConn, net.UnixConn

func IsConnGoodForReadv

func IsConnGoodForReadv(c net.Conn) (r int, rawReadConn syscall.RawConn, mr utils.MultiReader)

func IsDomainInsideGeosite

func IsDomainInsideGeosite(geositeName string, domain string) bool

func IsStrUDP_network

func IsStrUDP_network(s string) bool

"udp", "udp4", "udp6"

func Is_DNSQuery_returnType_ReadErr

func Is_DNSQuery_returnType_ReadErr(err error) bool

判断 DNSQuery 返回的错误 是否是 Read底层连接 的错误

func Is_DNSQuery_returnType_ReadFatalErr

func Is_DNSQuery_returnType_ReadFatalErr(err error) bool

筛除掉 Is_DNSQuery_returnType_ReadErr 时,err 为 net.Error.Timeout() 的情况

func ListenAndAccept

func ListenAndAccept(network, addr string, sockopt *Sockopt, acceptFunc func(net.Conn)) (listener net.Listener, err error)

ListenAndAccept 试图监听 tcp, udp 和 unix domain socket 这三种传输层协议.

非阻塞,在自己的goroutine中监听.

func LoadGeositeFiles

func LoadGeositeFiles() (err error)

从 geosite/data 文件夹中读取所有文件并加载到 GeositeListMap 中.

该 geosite/data 就是 github.com/v2fly/domain-list-community 项目的 data文件夹.

func LoadMaxmindGeoipFile

func LoadMaxmindGeoipFile(fn string)

将一个外部的文件加载为我们默认的 geoip文件;若fn=="",则会自动使用 GeoipFileName 的值

func LoadRulesForRoutePolicy

func LoadRulesForRoutePolicy(rules []*RuleConf, policy *RoutePolicy)

func ParseStrToAddr

func ParseStrToAddr(s string) (atyp byte, addr []byte, port_uint16 uint16, err error)

ParseAddr 分析字符串,并按照特定方式返回 地址类型 atyp,地址数据 addr []byte,以及端口号,

 如果解析出的地址是ip,则 addr返回 net.IP;
如果解析出的地址是 域名,则第一字节为域名总长度, 剩余字节为域名内容

func Prepare

func Prepare()

做一些网络层的资料准备工作, 可以优化本包其它函数的调用。

func RandPort

func RandPort(mustValid, isudp bool) (p int)

if mustValid is true, a valid port is assured. isudp is used to determine whether you want to use udp

func RandPortStr

func RandPortStr(mustValid, isudp bool) string

func RandPort_andStr

func RandPort_andStr(mustValid, isudp bool) (int, string)

func ReadBuffersFrom

func ReadBuffersFrom(c io.Reader, rawReadConn syscall.RawConn, mr utils.MultiReader) (buffers [][]byte, err error)

依次试图使用 readv、ReadBuffers 以及 原始 Read 读取数据

func Relay

func Relay(realTargetAddr *Addr, rc, lc io.ReadWriteCloser, downloadByteCount, uploadByteCount *uint64) int64

从 rc 读取 写入到 lc ,并同时从 lc 读取写入 rc. 阻塞. rc是指 remoteConn, lc 是指localConn; 一般lc由自己监听的Accept产生, rc 由自己拨号产生. UseReadv==true 时 内部使用 TryCopy 进行拷贝, 会自动优选 splice,readv,不行则使用经典拷贝.

拷贝完成后会主动关闭双方连接. 返回从 rc读取到的总字节长度(即下载流量). 如果 downloadByteCount, uploadByteCount 给出, 则会 分别原子更新 上传和下载的总字节数

func RelayUDP

func RelayUDP(rc, lc MsgConn, downloadByteCount, uploadByteCount *uint64) uint64

阻塞. 返回从 rc 下载的总字节数. 拷贝完成后自动关闭双端连接.

func RelayUDP_separate

func RelayUDP_separate(rc, lc MsgConn, firstAddr *Addr, downloadByteCount, uploadByteCount *uint64, dialfunc func(raddr Addr) MsgConn) uint64

RelayUDP_separate 对 lc 读到的每一个新raddr地址 都新拨号一个rc. 这样就避开了经典的udp多路复用转发的效率低下问题. separate含义就是 【分离信道】。随着时间推移, 会创建多个rc。 分离信道法还有个好处,就是fullcone时,不必一直保留某连接, 如果超时/读取错误, 可以断开单个rc连接, 释放占用的端口资源. 不过分离信道只能用于代理,不能用于 direct, 因为direct为了实现fullcone, 对所有rc连接都用的同一个udp端口。 阻塞. 返回从 rc 下载的总字节数. 拷贝完成后自动关闭双端连接.

func SetSockOpt

func SetSockOpt(fd int, sockopt *Sockopt, isudp bool, isipv6 bool)

func SetSockOptForListener

func SetSockOptForListener(tcplistener ListenerWithFile, sockopt *Sockopt, isudp bool, isipv6 bool)

func StrToTransportProtocol

func StrToTransportProtocol(s string) uint16

func TryCopy

func TryCopy(writeConn io.Writer, readConn io.Reader) (allnum int64, err error)

TryCopy 尝试 循环 从 readConn 读取数据并写入 writeConn, 直到错误发生。 会接连尝试 splice、循环readv 以及 原始Copy方法

func TryCopyOnce

func TryCopyOnce(writeConn io.Writer, readConn io.Reader) (allnum int64, err error)

类似TryCopy,但是只会读写一次; 因为只读写一次,所以没办法splice

func TryReadFrom_withSplice

func TryReadFrom_withSplice(classicWriter io.Writer, maySpliceConn net.Conn, r io.Reader, canDirectFunc func() bool) (written int64, err error)

从r读取数据,写入 maySpliceConn 或者 classicWriter, 在条件合适时会使用splice进行加速。 本函数主要应用于裸奔时,一端是socks5/直连,另一端是vless/vless+ws的情况, 因为vless等协议就算裸奔也是要处理一下数据头等情况的, 所以需要进行处理才可裸奔.

注意,splice只有在 maySpliceConn【本身是】或者【变成】 basicConn, 且 r 也是 basicConn时,才会发生。 如果r本身就不是 basicConn,则调用本函数没有意义, 因为既然拿不到basicConn那就不是裸奔,也就不可能splice。

func UDPAddr2AddrPort

func UDPAddr2AddrPort(ua *net.UDPAddr) netip.AddrPort

func UDPAddr_v4_to_Bytes

func UDPAddr_v4_to_Bytes(addr *net.UDPAddr) [6]byte

Types

type Addr

type Addr struct {
	Network string
	Name    string // domain name, 或者 unix domain socket 的 文件路径
	IP      net.IP
	Port    int
}

Addr represents a address that you want to access by proxy. Either Name or IP is used exclusively. Addr完整地表示了一个 传输层的目标,同时用 Network 字段 来记录网络层协议名 Addr 还可以用Dial 方法直接进行拨号

func NewAddr

func NewAddr(addrStr string) (Addr, error)

addrStr格式一般为 host:port ;如果不含冒号,将直接认为该字符串是域名或文件名

func NewAddrByHostPort

func NewAddrByHostPort(hostPortStr string) (Addr, error)

hostPortStr格式 必须为 host:port,本函数不对此检查

func NewAddrByURL

func NewAddrByURL(addrStr string) (Addr, error)

如 tcp://127.0.0.1:443 , tcp://google.com:443 ; 不支持unix domain socket, 因为它是文件路径, / 还需要转义,太麻烦;不是我们代码麻烦, 而是怕用户嫌麻烦

func NewAddrFromAny

func NewAddrFromAny(thing any) (addr Addr, err error)

会根据thing的类型 生成实际addr; 可以为数字端口,或者带冒号的字符串,或者一个 文件路径(unix domain socket)

func NewAddrFromUDPAddr

func NewAddrFromUDPAddr(addr *net.UDPAddr) Addr

func (*Addr) AddressBytes

func (a *Addr) AddressBytes() (addr []byte, atyp byte)

如果a的ip不为空,则会返回 AtypIP4 或 AtypIP6, 否则会返回 AtypDomain Return address bytes and type 如果atyp类型是 域名,则 第一字节为该域名的总长度, 其余字节为域名内容。 如果类型是ip,则会拷贝出该ip的数据的副本。

func (*Addr) Dial

func (addr *Addr) Dial() (net.Conn, error)

func (Addr) DialWithOpt

func (addr Addr) DialWithOpt(sockopt *Sockopt) (net.Conn, error)

func (*Addr) GetHashable

func (a *Addr) GetHashable() (ha HashableAddr)

func (*Addr) GetNetIPAddr

func (a *Addr) GetNetIPAddr() (na netip.Addr)

func (*Addr) HostStr

func (a *Addr) HostStr() string

Returned host string

func (*Addr) IsEmpty

func (a *Addr) IsEmpty() bool

func (*Addr) IsIpv6

func (a *Addr) IsIpv6() bool

func (*Addr) IsUDP

func (a *Addr) IsUDP() bool

a.Network == "udp", "udp4", "udp6"

func (Addr) ListenUDP_withOpt

func (addr Addr) ListenUDP_withOpt(sockopt *Sockopt) (net.PacketConn, error)

func (*Addr) String

func (a *Addr) String() string

Return host:port string. 若网络为unix,直接返回 a.Name. 若有Name而没有ip,则返回 a.Name:a.Port . 否则返回 a.IP: a.Port;

func (*Addr) ToTCPAddr

func (a *Addr) ToTCPAddr() *net.TCPAddr

func (*Addr) ToUDPAddr

func (a *Addr) ToUDPAddr() *net.UDPAddr

如果a里只含有域名,则会自动解析域名为IP。

func (*Addr) UrlString

func (a *Addr) UrlString() string

返回以url表示的 地址. unix的话文件名若带斜杠则会被转义

type AddrData

type AddrData struct {
	Addr Addr
	Data []byte
}

type ConnWithFile

type ConnWithFile interface {
	net.Conn
	File() (f *os.File, err error)
}

net.UnixConn, net.UDPConn, net.TCPConn, net.IPConn

type DNSMachine

type DNSMachine struct {
	TypeStrategy int64 // 0, 4, 6, 40, 60

	SpecialIPPollicy map[string][]netip.Addr

	SpecialServerPollicy map[string]string //domain -> dns server name
	// contains filtered or unexported fields
}

dns machine维持与多个dns服务器的连接(最好是udp这种无状态的),并可以发起dns请求。 会缓存dns记录; 该设施是一个状态机, 所以叫 DNSMachine SpecialIPPollicy 用于指定特殊的 域名-ip映射,这样遇到这种域名时,不经过dns查询,直接返回预设ip SpecialServerPollicy 用于为特殊的 域名指定特殊的 dns服务器,这样遇到这种域名时,会通过该特定服务器查询

func LoadDnsMachine

func LoadDnsMachine(conf *DnsConf) *DNSMachine

func (*DNSMachine) AddNewServer

func (dm *DNSMachine) AddNewServer(name string, addr *Addr) error

添加一个 特定的DNS服务器 , name为该dns服务器的名称. 若第一次调用, 则会设为 dm.DefaultConn

func (*DNSMachine) Query

func (dm *DNSMachine) Query(domain string) (ip net.IP)

func (*DNSMachine) QueryType

func (dm *DNSMachine) QueryType(domain string, dns_type uint16) (ip net.IP)

传入的domain必须是不带尾缀点号的domain, 即没有包过 Fqdn

func (*DNSMachine) SetDefaultConn

func (dm *DNSMachine) SetDefaultConn(c net.Conn, addr *Addr)

type DnsConf

type DnsConf struct {
	Strategy int64          `toml:"strategy"` //0表示默认(和4含义相同), 4表示先查ip4后查ip6, 6表示先查6后查4; 40表示只查ipv4, 60 表示只查ipv6
	Hosts    map[string]any `toml:"hosts"`    //用于强制指定哪些域名会被解析为哪些具体的ip;可以为一个ip字符串,或者一个 []string 数组, 数组内可以是A,AAAA或CNAME
	Servers  []any          `toml:"servers"`  //可以为一个地址url字符串,或者为 SpecialDnsServerConf; 如果第一个元素是url字符串形式,则此第一个元素将会被用作默认dns服务器
}

type DnsConn

type DnsConn struct {
	*dns.Conn
	Name string //我们这里惯例,直接使用配置文件中配置的url字符串作为Name
	// contains filtered or unexported fields
}

给 miekg/dns.Conn 加一个互斥锁, 可保证同一时间仅有一个请求发生 这样就不会造成并发时的混乱

func (*DnsConn) Dial

func (c *DnsConn) Dial() error

Dial通过 c 内部设置好的地址进行拨号,并将 c.Conn.Conn 设为 新建立好的连接

type DomainHaser

type DomainHaser interface {
	HasDomain(string) bool
}

用于 HasFullOrSubDomain函数

type GeositeAttr

type GeositeAttr struct {
	Key   string
	Value any //bool or int64
}

type GeositeDomain

type GeositeDomain struct {
	Type  string //domain, regexp, full
	Value string
	Attrs []GeositeAttr
}

type GeositeList

type GeositeList struct {
	//Name实际上就是v2fly Community的protobuf里的 CountryCode. Geosite本意是给一个国家的域名分类, 但是实际上功能越来越多,绝大部分Name现在实际上都是网站名称,只有 CN, GEOLOCATION-CN 的是国家名. 其它的还有很多分类名称,比如 CATEGORY-ECOMMERCE
	// 在parse过后,可以发现所有的Name都被转换成了大写字符的形式
	Name string

	FullDomains  map[string]GeositeDomain
	Domains      map[string]GeositeDomain
	RegexDomains []*regexp.Regexp
}

GeositeList 用于内存中匹配使用

type GeositeRawList

type GeositeRawList struct {
	Name    string
	Domains []GeositeDomain
}

GeositeRawList 用于序列化

func LoadGeositeFile

func LoadGeositeFile(path string) (*GeositeRawList, error)

func ParseGeositeList

func ParseGeositeList(list *GeositeRawList, ref map[string]*GeositeRawList) (*GeositeRawList, error)

这里从v2fly改动了一些. 因为我发现 Inclusion最终不会被用到

func (*GeositeRawList) ToGeositeList

func (grl *GeositeRawList) ToGeositeList() (gl *GeositeList)

type HashableAddr

type HashableAddr struct {
	Network, Name string
	netip.AddrPort
}

type ListenerWithFile

type ListenerWithFile interface {
	net.Listener
	File() (f *os.File, err error)
}

net.TCPListener, net.UnixListener

type MapDomainHaser

type MapDomainHaser map[string]bool

func (MapDomainHaser) HasDomain

func (mdh MapDomainHaser) HasDomain(d string) bool

type MapGeositeDomainHaser

type MapGeositeDomainHaser map[string]GeositeDomain

func (MapGeositeDomainHaser) HasDomain

func (mdh MapGeositeDomainHaser) HasDomain(d string) bool

type MsgConn

type MsgConn interface {
	ReadMsgFrom() ([]byte, Addr, error)
	WriteMsgTo([]byte, Addr) error
	CloseConnWithRaddr(raddr Addr) error //关闭特定连接
	Close() error                        //关闭所有连接
	Fullcone() bool                      //若Fullcone, 则在转发因另一端关闭而结束后, RelayUDP函数不会Close它.
}

MsgConn一般用于 udp. 是一种类似 net.PacketConn 的包装. 实现 MsgConn接口 的类型 可以被用于 RelayUDP 进行转发。

ReadMsgFrom直接返回数据, 这样可以尽量避免多次数据拷贝。

使用Addr,是因为有可能请求地址是个域名,而不是ip; 而且通过Addr, MsgConn实际上有可能支持通用的情况, 即可以用于 客户端 一会 请求tcp,一会又请求udp,一会又请求什么其它网络层 这种奇葩情况.

type PipeDeadline

type PipeDeadline struct {
	// contains filtered or unexported fields
}

PipeDeadline is an abstraction for handling timeouts. copied from golang standard package net

func MakePipeDeadline

func MakePipeDeadline() PipeDeadline

func (*PipeDeadline) Set

func (d *PipeDeadline) Set(t time.Time)

set sets the point in time when the deadline will time out. A timeout event is signaled by closing the channel returned by waiter. Once a timeout has occurred, the deadline can be refreshed by specifying a t value in the future.

A zero value for t prevents timeout.

func (*PipeDeadline) Wait

func (d *PipeDeadline) Wait() chan struct{}

wait returns a channel that is closed when the deadline is exceeded.

type ReadWrapper

type ReadWrapper struct {
	net.Conn
	OptionalReader    io.Reader
	RemainFirstBufLen int
}

选择性从 OptionalReader读取, 直到 RemainFirstBufLen 小于等于0 为止; 一般用于与 io.MultiReader 配合

func (*ReadWrapper) Read

func (mc *ReadWrapper) Read(p []byte) (n int, err error)

func (*ReadWrapper) WriteBuffers

func (c *ReadWrapper) WriteBuffers(buffers [][]byte) (int64, error)

type RoutePolicy

type RoutePolicy struct {
	List []*RouteSet
}

一个完整的 所有RouteSet的列表,进行路由时,直接遍历即可 所谓的路由实际上就是分流。

func NewRoutePolicy

func NewRoutePolicy() *RoutePolicy

func (*RoutePolicy) AddRouteSet

func (rp *RoutePolicy) AddRouteSet(rs *RouteSet)

func (*RoutePolicy) GetOutTag

func (rp *RoutePolicy) GetOutTag(td *TargetDescription) string

返回一个 proxy.Client 的 tag 默认情况下,始终具有direct这个tag以及 proxy这个tag,无需用户额外在配置文件中指定 默认如果不匹配任何值的话,就会流向 "proxy" tag,也就是客户设置的 remoteClient的值

type RouteSet

type RouteSet struct {
	//网络层
	NetRanger cidranger.Ranger    //一个范围
	IPs       map[netip.Addr]bool //一个确定值

	//Match 匹配任意字符串
	//Domains匹配子域名,当此域名是目标域名或其子域名时,该规则生效
	//Full只匹配完整域名
	Domains, Full, InTags, Countries map[string]bool // Countries 使用 ISO 3166 字符串 作为key

	//Regex是正则匹配域名
	Regex           []*regexp.Regexp
	Match, Geosites []string

	//传输层
	AllowedTransportLayerProtocols uint16

	OutTag  string   //目标
	OutTags []string //目标列表

}

Set 是 “集合” 的意思, 是一组相同类型的数据放到一起。

这里的相同点,就是它们同属于 将发往一个方向, 即同属一个路由策略

任意一个参数匹配后,都将发往相同的方向,由该方向OutTag 指定 RouteSet 只负责把一些属性相同的 “网络层/传输层 特征” 放到一起

func LoadRuleForRouteSet

func LoadRuleForRouteSet(rule *RuleConf) (rs *RouteSet)

func NewFullRouteSet

func NewFullRouteSet() *RouteSet

func NewRouteSetForMyCountry

func NewRouteSetForMyCountry(iso string) *RouteSet

func (*RouteSet) IsAddrIn

func (sg *RouteSet) IsAddrIn(a Addr) bool

func (*RouteSet) IsAddrNetworkAllowed

func (sg *RouteSet) IsAddrNetworkAllowed(a Addr) bool

func (*RouteSet) IsIn

func (sg *RouteSet) IsIn(td *TargetDescription) bool

func (*RouteSet) IsTCPAllowed

func (sg *RouteSet) IsTCPAllowed() bool

func (*RouteSet) IsTransportProtocolAllowed

func (sg *RouteSet) IsTransportProtocolAllowed(p uint16) bool

func (*RouteSet) IsUDPAllowed

func (sg *RouteSet) IsUDPAllowed() bool

type RuleConf

type RuleConf struct {
	DialTag any `toml:"dialTag"`

	InTags []string `toml:"inTag"`

	Countries []string `toml:"country"` // 如果类似 !CN, 则意味着专门匹配不为CN 的国家(目前还未实现)
	IPs       []string `toml:"ip"`
	Domains   []string `toml:"domain"`
	Network   []string `toml:"network"`
}

type Sockopt

type Sockopt struct {
	TProxy bool   `toml:"tproxy"`
	Somark int    `toml:"mark"`
	Device string `toml:"device"`
}

用于 listen和 dial 配置一些底层参数.

type SpecialDnsServerConf

type SpecialDnsServerConf struct {
	AddrUrlStr string   `toml:"addr"`   //必须为 udp://1.1.1.1:53 这种格式
	Domains    []string `toml:"domain"` //指定哪些域名需要通过 该dns服务器进行查询
}

type Splicer

type Splicer interface {
	EverPossibleToSplice() bool  //是否有机会splice, 如果这个返回false,则永远无法splice; 主要审视自己能否向裸连接写入数据; 读不用splicer担心。
	CanSplice() (bool, net.Conn) //当前状态是否可以splice
}

type TargetDescription

type TargetDescription struct {
	Addr Addr
	Tag  string
}

TargetDescription 可以完整地描述一个网络层/传输层上的一个特定目标, 一般来说,一个具体的监听配置就会分配一个tag

type UDPAddrData

type UDPAddrData struct {
	Addr net.UDPAddr
	Data []byte
}

type UDPConn

type UDPConn struct {
	// contains filtered or unexported fields
}

UDPConn 将一个udp连接包装成一个 向单一目标发送数据的 连接。 UDPConn 主要服务于 UDPListener。如果有udp客户端需求, 最好使用 UDPMsgConn, 以更好地支持 fullcone或symmetric.

UDPConn 也有能力接收来自其它目标的数据,以及向其它目标发送数据。然而, 本结构并没有记录链接端口, 所以无法实现 symmetric. 如果用 DialUDP 函数初始化的 UDPConn, 则无法使用 WriteMsgTo方法向其它地址发消息.

UDPConn 实现了 net.Conn , net.PacketConn , MsgConn

func DialUDP

func DialUDP(raddr *net.UDPAddr) (*UDPConn, error)

我们这里为了保证udp连接不会一直滞留导致 too many open files的情况, 主动设置了 内层udp连接的 read的 timeout为 UDP_timeout。 你依然可以设置 DialUDP 所返回的 net.Conn 的 Deadline, 这属于外层的Deadline, 不会影响底层 udp所强制设置的 deadline.

func NewUDPConn

func NewUDPConn(raddr *net.UDPAddr, conn *net.UDPConn, isClient bool) *UDPConn

如果isClient为true,则本函数返回后,必须要调用一次 Write,才能在Read读到数据. 这是udp的原理所决定的。 在客户端没有Write之前,该udp连接实际上根本没有被建立, Read也就不可能/不应该 读到任何东西.

func (*UDPConn) Close

func (uc *UDPConn) Close() error

func (*UDPConn) CloseConnWithRaddr

func (u *UDPConn) CloseConnWithRaddr(_ Addr) error

func (*UDPConn) CloseMsgChan

func (uc *UDPConn) CloseMsgChan()

func (*UDPConn) GetReadChan

func (uc *UDPConn) GetReadChan() chan UDPAddrData

func (*UDPConn) LocalAddr

func (b *UDPConn) LocalAddr() net.Addr

func (*UDPConn) Read

func (uc *UDPConn) Read(buf []byte) (n int, err error)

func (*UDPConn) ReadFrom

func (uc *UDPConn) ReadFrom(p []byte) (n int, addr net.Addr, err error)

实现 net.PacketConn, 可以与 miekg/dns 配合。返回的 addr 只可能为 之前预先配置的远程目标地址

func (*UDPConn) ReadMsg

func (uc *UDPConn) ReadMsg() (b []byte, err error)

func (*UDPConn) ReadMsgFrom

func (uc *UDPConn) ReadMsgFrom() ([]byte, Addr, error)

func (*UDPConn) RemoteAddr

func (b *UDPConn) RemoteAddr() net.Addr

func (*UDPConn) RemoteUDPAddr

func (b *UDPConn) RemoteUDPAddr() *net.UDPAddr

func (*UDPConn) SetDeadline

func (b *UDPConn) SetDeadline(t time.Time) error

func (*UDPConn) SetReadDeadline

func (b *UDPConn) SetReadDeadline(t time.Time) error

func (*UDPConn) SetWriteDeadline

func (b *UDPConn) SetWriteDeadline(t time.Time) error

func (*UDPConn) Write

func (uc *UDPConn) Write(buf []byte) (n int, err error)

func (*UDPConn) WriteMsgTo

func (uc *UDPConn) WriteMsgTo(buf []byte, addr Addr) error

func (*UDPConn) WriteTo

func (uc *UDPConn) WriteTo(p []byte, _ net.Addr) (n int, err error)

实现 net.PacketConn, 可以与 miekg/dns 配合。会无视传入的地址, 而使用 之前预先配置的远程目标地址

type UDPListener

type UDPListener struct {
	// contains filtered or unexported fields
}

UDPListener 实现了 net.Listener. UDPListener 监听 UDPAddr,不断读取请求,对新远程地址 创建 新UDPConn并提供给 Accept;

记录遇到过的所有地址 以及 对应的 UDPConn.

将读到的信息缓存到 UDPConn 的 chan 中,让它能在Read时读到.

UDPListener can also dial a remote host by calling NewConn.

func NewUDPListener

func NewUDPListener(laddr *net.UDPAddr) (*UDPListener, error)

NewUDPListener 返回一个 *UDPListener, 该Listener实现了 net.Listener

func NewUDPListenerConn

func NewUDPListenerConn(conn *net.UDPConn) (*UDPListener, error)

func (*UDPListener) Accept

func (ul *UDPListener) Accept() (net.Conn, error)

func (*UDPListener) Addr

func (ul *UDPListener) Addr() net.Addr

func (*UDPListener) Close

func (ul *UDPListener) Close() error

Once closed, it cannot be used again. it calls ul.CloseClients()

func (*UDPListener) DeleteConn

func (ul *UDPListener) DeleteConn(addrport netip.AddrPort)

func (*UDPListener) NewConn

func (ul *UDPListener) NewConn(raddr *net.UDPAddr) *UDPConn

It can be used to dial a remote udp

type UDPMsgConn

type UDPMsgConn struct {
	IsServer bool
	// contains filtered or unexported fields
}

UDPMsgConn 实现 MsgConn。 可满足fullcone/symmetric. 在proxy/direct 被用到.

func NewUDPMsgConn

func NewUDPMsgConn(laddr *net.UDPAddr, fullcone bool, isserver bool) (*UDPMsgConn, error)

NewUDPMsgConn 创建一个 UDPMsgConn 并使用传入的 laddr 监听udp; 若未给出laddr, 将使用一个随机可用的端口监听. 如果是普通的单目标的客户端,用 (nil,false,false) 即可.

满足fullcone/symmetric, 由 fullcone 的值决定.

func (*UDPMsgConn) Close

func (u *UDPMsgConn) Close() error

func (*UDPMsgConn) CloseConnWithRaddr

func (u *UDPMsgConn) CloseConnWithRaddr(raddr Addr) error

func (*UDPMsgConn) Fullcone

func (u *UDPMsgConn) Fullcone() bool

func (*UDPMsgConn) ReadMsgFrom

func (u *UDPMsgConn) ReadMsgFrom() ([]byte, Addr, error)

func (*UDPMsgConn) WriteMsgTo

func (u *UDPMsgConn) WriteMsgTo(bs []byte, raddr Addr) error

type UniTargetMsgConn

type UniTargetMsgConn struct {
	net.Conn
	Target Addr
}

symmetric, proxy/dokodemo 有用到. 实现 MsgConn

func (UniTargetMsgConn) Close

func (u UniTargetMsgConn) Close() error

func (UniTargetMsgConn) CloseConnWithRaddr

func (u UniTargetMsgConn) CloseConnWithRaddr(raddr Addr) error

func (UniTargetMsgConn) Fullcone

func (u UniTargetMsgConn) Fullcone() bool

func (UniTargetMsgConn) ReadMsgFrom

func (u UniTargetMsgConn) ReadMsgFrom() ([]byte, Addr, error)

func (UniTargetMsgConn) WriteMsgTo

func (u UniTargetMsgConn) WriteMsgTo(bs []byte, _ Addr) error

Directories

Path Synopsis
Package tproxy implements tproxy.
Package tproxy implements tproxy.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL