mirror of
https://github.com/MetaCubeX/mihomo.git
synced 2026-03-04 12:57:31 +00:00
Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
613becd8ea | ||
|
|
d6b496d3c0 | ||
|
|
5a24efdabf | ||
|
|
9de9f1ef51 | ||
|
|
fbead56ec9 | ||
|
|
1fff34d30e | ||
|
|
a35f712478 | ||
|
|
f805a9f4c6 | ||
|
|
eb985b002e | ||
|
|
462343531e | ||
|
|
671d901ee2 | ||
|
|
80e4eaad14 | ||
|
|
25b3c86d31 | ||
|
|
de19f927e8 | ||
|
|
792f16265e | ||
|
|
215bf0995f | ||
|
|
91d54bdac1 | ||
|
|
ce52c3438b | ||
|
|
d4478dbfa2 | ||
|
|
69454b030e | ||
|
|
e6d1c8cedf | ||
|
|
fabd216c34 | ||
|
|
a86c562852 |
19
.github/workflows/build.yml
vendored
19
.github/workflows/build.yml
vendored
@@ -104,29 +104,22 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
if: ${{ matrix.jobs.goversion == '' && matrix.jobs.goarch != 'loong64' }}
|
if: ${{ matrix.jobs.goversion == '' && matrix.jobs.abi != '1' }}
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: '1.23'
|
go-version: '1.23'
|
||||||
|
|
||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
if: ${{ matrix.jobs.goversion != '' && matrix.jobs.goarch != 'loong64' }}
|
if: ${{ matrix.jobs.goversion != '' && matrix.jobs.abi != '1' }}
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ${{ matrix.jobs.goversion }}
|
go-version: ${{ matrix.jobs.goversion }}
|
||||||
|
|
||||||
- name: Set up Go1.22 loongarch abi1
|
- name: Set up Go1.23 loongarch abi1
|
||||||
if: ${{ matrix.jobs.goarch == 'loong64' && matrix.jobs.abi == '1' }}
|
if: ${{ matrix.jobs.goarch == 'loong64' && matrix.jobs.abi == '1' }}
|
||||||
run: |
|
run: |
|
||||||
wget -q https://github.com/MetaCubeX/loongarch64-golang/releases/download/1.22.4/go1.22.4.linux-amd64-abi1.tar.gz
|
wget -q https://github.com/MetaCubeX/loongarch64-golang/releases/download/1.23.0/go1.23.0.linux-amd64-abi1.tar.gz
|
||||||
sudo tar zxf go1.22.4.linux-amd64-abi1.tar.gz -C /usr/local
|
sudo tar zxf go1.23.0.linux-amd64-abi1.tar.gz -C /usr/local
|
||||||
echo "/usr/local/go/bin" >> $GITHUB_PATH
|
|
||||||
|
|
||||||
- name: Set up Go1.22 loongarch abi2
|
|
||||||
if: ${{ matrix.jobs.goarch == 'loong64' && matrix.jobs.abi == '2' }}
|
|
||||||
run: |
|
|
||||||
wget -q https://github.com/MetaCubeX/loongarch64-golang/releases/download/1.22.4/go1.22.4.linux-amd64-abi2.tar.gz
|
|
||||||
sudo tar zxf go1.22.4.linux-amd64-abi2.tar.gz -C /usr/local
|
|
||||||
echo "/usr/local/go/bin" >> $GITHUB_PATH
|
echo "/usr/local/go/bin" >> $GITHUB_PATH
|
||||||
|
|
||||||
# modify from https://github.com/restic/restic/issues/4636#issuecomment-1896455557
|
# modify from https://github.com/restic/restic/issues/4636#issuecomment-1896455557
|
||||||
@@ -194,7 +187,7 @@ jobs:
|
|||||||
uses: nttld/setup-ndk@v1
|
uses: nttld/setup-ndk@v1
|
||||||
id: setup-ndk
|
id: setup-ndk
|
||||||
with:
|
with:
|
||||||
ndk-version: r27
|
ndk-version: r28-beta1
|
||||||
|
|
||||||
- name: Set NDK path
|
- name: Set NDK path
|
||||||
if: ${{ matrix.jobs.goos == 'android' }}
|
if: ${{ matrix.jobs.goos == 'android' }}
|
||||||
|
|||||||
@@ -163,8 +163,17 @@ func (p *Proxy) MarshalJSON() ([]byte, error) {
|
|||||||
mapping["alive"] = p.alive.Load()
|
mapping["alive"] = p.alive.Load()
|
||||||
mapping["name"] = p.Name()
|
mapping["name"] = p.Name()
|
||||||
mapping["udp"] = p.SupportUDP()
|
mapping["udp"] = p.SupportUDP()
|
||||||
mapping["xudp"] = p.SupportXUDP()
|
mapping["uot"] = p.SupportUOT()
|
||||||
mapping["tfo"] = p.SupportTFO()
|
|
||||||
|
proxyInfo := p.ProxyInfo()
|
||||||
|
mapping["xudp"] = proxyInfo.XUDP
|
||||||
|
mapping["tfo"] = proxyInfo.TFO
|
||||||
|
mapping["mptcp"] = proxyInfo.MPTCP
|
||||||
|
mapping["smux"] = proxyInfo.SMUX
|
||||||
|
mapping["interface"] = proxyInfo.Interface
|
||||||
|
mapping["dialer-proxy"] = proxyInfo.DialerProxy
|
||||||
|
mapping["routing-mark"] = proxyInfo.RoutingMark
|
||||||
|
|
||||||
return json.Marshal(mapping)
|
return json.Marshal(mapping)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,12 +34,5 @@ func SkipAuthRemoteAddress(addr string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func skipAuth(addr netip.Addr) bool {
|
func skipAuth(addr netip.Addr) bool {
|
||||||
if addr.IsValid() {
|
return prefixesContains(skipAuthPrefixes, addr)
|
||||||
for _, prefix := range skipAuthPrefixes {
|
|
||||||
if prefix.Contains(addr.Unmap()) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,27 +31,17 @@ func IsRemoteAddrDisAllowed(addr net.Addr) bool {
|
|||||||
if err := m.SetRemoteAddr(addr); err != nil {
|
if err := m.SetRemoteAddr(addr); err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return isAllowed(m.AddrPort().Addr().Unmap()) && !isDisAllowed(m.AddrPort().Addr().Unmap())
|
ipAddr := m.AddrPort().Addr()
|
||||||
|
if ipAddr.IsValid() {
|
||||||
|
return isAllowed(ipAddr) && !isDisAllowed(ipAddr)
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func isAllowed(addr netip.Addr) bool {
|
func isAllowed(addr netip.Addr) bool {
|
||||||
if addr.IsValid() {
|
return prefixesContains(lanAllowedIPs, addr)
|
||||||
for _, prefix := range lanAllowedIPs {
|
|
||||||
if prefix.Contains(addr) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func isDisAllowed(addr netip.Addr) bool {
|
func isDisAllowed(addr netip.Addr) bool {
|
||||||
if addr.IsValid() {
|
return prefixesContains(lanDisAllowedIPs, addr)
|
||||||
for _, prefix := range lanDisAllowedIPs {
|
|
||||||
if prefix.Contains(addr) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,9 @@ package inbound
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"net/netip"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/metacubex/mihomo/component/keepalive"
|
"github.com/metacubex/mihomo/component/keepalive"
|
||||||
@@ -42,6 +44,27 @@ func MPTCP() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ListenContext(ctx context.Context, network, address string) (net.Listener, error) {
|
func ListenContext(ctx context.Context, network, address string) (net.Listener, error) {
|
||||||
|
switch network { // like net.Resolver.internetAddrList but filter domain to avoid call net.Resolver.lookupIPAddr
|
||||||
|
case "tcp", "tcp4", "tcp6", "udp", "udp4", "udp6", "ip", "ip4", "ip6":
|
||||||
|
if host, port, err := net.SplitHostPort(address); err == nil {
|
||||||
|
switch host {
|
||||||
|
case "localhost":
|
||||||
|
switch network {
|
||||||
|
case "tcp6", "udp6", "ip6":
|
||||||
|
address = net.JoinHostPort("::1", port)
|
||||||
|
default:
|
||||||
|
address = net.JoinHostPort("127.0.0.1", port)
|
||||||
|
}
|
||||||
|
case "": // internetAddrList can handle this special case
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
if _, err := netip.ParseAddr(host); err != nil { // not ip
|
||||||
|
return nil, fmt.Errorf("invalid network address: %s", address)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mutex.RLock()
|
mutex.RLock()
|
||||||
defer mutex.RUnlock()
|
defer mutex.RUnlock()
|
||||||
return lc.Listen(ctx, network, address)
|
return lc.Listen(ctx, network, address)
|
||||||
|
|||||||
@@ -61,3 +61,19 @@ func parseHTTPAddr(request *http.Request) *C.Metadata {
|
|||||||
|
|
||||||
return metadata
|
return metadata
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func prefixesContains(prefixes []netip.Prefix, addr netip.Addr) bool {
|
||||||
|
if len(prefixes) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !addr.IsValid() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
addr = addr.Unmap().WithZone("") // netip.Prefix.Contains returns false if ip has an IPv6 zone
|
||||||
|
for _, prefix := range prefixes {
|
||||||
|
if prefix.Contains(addr) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|||||||
@@ -85,14 +85,15 @@ func (b *Base) SupportUDP() bool {
|
|||||||
return b.udp
|
return b.udp
|
||||||
}
|
}
|
||||||
|
|
||||||
// SupportXUDP implements C.ProxyAdapter
|
// ProxyInfo implements C.ProxyAdapter
|
||||||
func (b *Base) SupportXUDP() bool {
|
func (b *Base) ProxyInfo() (info C.ProxyInfo) {
|
||||||
return b.xudp
|
info.XUDP = b.xudp
|
||||||
}
|
info.TFO = b.tfo
|
||||||
|
info.MPTCP = b.mpTcp
|
||||||
// SupportTFO implements C.ProxyAdapter
|
info.SMUX = false
|
||||||
func (b *Base) SupportTFO() bool {
|
info.Interface = b.iface
|
||||||
return b.tfo
|
info.RoutingMark = b.rmark
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsL3Protocol implements C.ProxyAdapter
|
// IsL3Protocol implements C.ProxyAdapter
|
||||||
|
|||||||
@@ -3,18 +3,12 @@ package outbound
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"os"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/metacubex/mihomo/component/dialer"
|
"github.com/metacubex/mihomo/component/dialer"
|
||||||
"github.com/metacubex/mihomo/component/loopback"
|
"github.com/metacubex/mihomo/component/loopback"
|
||||||
"github.com/metacubex/mihomo/component/resolver"
|
"github.com/metacubex/mihomo/component/resolver"
|
||||||
C "github.com/metacubex/mihomo/constant"
|
C "github.com/metacubex/mihomo/constant"
|
||||||
"github.com/metacubex/mihomo/constant/features"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var DisableLoopBackDetector, _ = strconv.ParseBool(os.Getenv("DISABLE_LOOPBACK_DETECTOR"))
|
|
||||||
|
|
||||||
type Direct struct {
|
type Direct struct {
|
||||||
*Base
|
*Base
|
||||||
loopBack *loopback.Detector
|
loopBack *loopback.Detector
|
||||||
@@ -27,10 +21,8 @@ type DirectOption struct {
|
|||||||
|
|
||||||
// DialContext implements C.ProxyAdapter
|
// DialContext implements C.ProxyAdapter
|
||||||
func (d *Direct) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.Conn, error) {
|
func (d *Direct) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.Conn, error) {
|
||||||
if !features.CMFA && !DisableLoopBackDetector {
|
if err := d.loopBack.CheckConn(metadata); err != nil {
|
||||||
if err := d.loopBack.CheckConn(metadata); err != nil {
|
return nil, err
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
opts = append(opts, dialer.WithResolver(resolver.DirectHostResolver))
|
opts = append(opts, dialer.WithResolver(resolver.DirectHostResolver))
|
||||||
c, err := dialer.DialContext(ctx, "tcp", metadata.RemoteAddress(), d.Base.DialOptions(opts...)...)
|
c, err := dialer.DialContext(ctx, "tcp", metadata.RemoteAddress(), d.Base.DialOptions(opts...)...)
|
||||||
@@ -42,10 +34,8 @@ func (d *Direct) DialContext(ctx context.Context, metadata *C.Metadata, opts ...
|
|||||||
|
|
||||||
// ListenPacketContext implements C.ProxyAdapter
|
// ListenPacketContext implements C.ProxyAdapter
|
||||||
func (d *Direct) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.PacketConn, error) {
|
func (d *Direct) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.PacketConn, error) {
|
||||||
if !features.CMFA && !DisableLoopBackDetector {
|
if err := d.loopBack.CheckPacketConn(metadata); err != nil {
|
||||||
if err := d.loopBack.CheckPacketConn(metadata); err != nil {
|
return nil, err
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// net.UDPConn.WriteTo only working with *net.UDPAddr, so we need a net.UDPAddr
|
// net.UDPConn.WriteTo only working with *net.UDPAddr, so we need a net.UDPAddr
|
||||||
if !metadata.Resolved() {
|
if !metadata.Resolved() {
|
||||||
|
|||||||
@@ -92,6 +92,13 @@ func (h *Http) SupportWithDialer() C.NetWork {
|
|||||||
return C.TCP
|
return C.TCP
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ProxyInfo implements C.ProxyAdapter
|
||||||
|
func (h *Http) ProxyInfo() C.ProxyInfo {
|
||||||
|
info := h.Base.ProxyInfo()
|
||||||
|
info.DialerProxy = h.option.DialerProxy
|
||||||
|
return info
|
||||||
|
}
|
||||||
|
|
||||||
func (h *Http) shakeHand(metadata *C.Metadata, rw io.ReadWriter) error {
|
func (h *Http) shakeHand(metadata *C.Metadata, rw io.ReadWriter) error {
|
||||||
addr := metadata.RemoteAddress()
|
addr := metadata.RemoteAddress()
|
||||||
HeaderString := "CONNECT " + addr + " HTTP/1.1\r\n"
|
HeaderString := "CONNECT " + addr + " HTTP/1.1\r\n"
|
||||||
|
|||||||
@@ -87,6 +87,13 @@ func (h *Hysteria) genHdc(ctx context.Context, opts ...dialer.Option) utils.Pack
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ProxyInfo implements C.ProxyAdapter
|
||||||
|
func (h *Hysteria) ProxyInfo() C.ProxyInfo {
|
||||||
|
info := h.Base.ProxyInfo()
|
||||||
|
info.DialerProxy = h.option.DialerProxy
|
||||||
|
return info
|
||||||
|
}
|
||||||
|
|
||||||
type HysteriaOption struct {
|
type HysteriaOption struct {
|
||||||
BasicOption
|
BasicOption
|
||||||
Name string `proxy:"name"`
|
Name string `proxy:"name"`
|
||||||
|
|||||||
@@ -96,6 +96,13 @@ func closeHysteria2(h *Hysteria2) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ProxyInfo implements C.ProxyAdapter
|
||||||
|
func (h *Hysteria2) ProxyInfo() C.ProxyInfo {
|
||||||
|
info := h.Base.ProxyInfo()
|
||||||
|
info.DialerProxy = h.option.DialerProxy
|
||||||
|
return info
|
||||||
|
}
|
||||||
|
|
||||||
func NewHysteria2(option Hysteria2Option) (*Hysteria2, error) {
|
func NewHysteria2(option Hysteria2Option) (*Hysteria2, error) {
|
||||||
addr := net.JoinHostPort(option.Server, strconv.Itoa(option.Port))
|
addr := net.JoinHostPort(option.Server, strconv.Itoa(option.Port))
|
||||||
var salamanderPassword string
|
var salamanderPassword string
|
||||||
|
|||||||
268
adapter/outbound/mieru.go
Normal file
268
adapter/outbound/mieru.go
Normal file
@@ -0,0 +1,268 @@
|
|||||||
|
package outbound
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"runtime"
|
||||||
|
"strconv"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
mieruclient "github.com/enfein/mieru/v3/apis/client"
|
||||||
|
mierumodel "github.com/enfein/mieru/v3/apis/model"
|
||||||
|
mierupb "github.com/enfein/mieru/v3/pkg/appctl/appctlpb"
|
||||||
|
"github.com/metacubex/mihomo/component/dialer"
|
||||||
|
"github.com/metacubex/mihomo/component/proxydialer"
|
||||||
|
C "github.com/metacubex/mihomo/constant"
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Mieru struct {
|
||||||
|
*Base
|
||||||
|
option *MieruOption
|
||||||
|
client mieruclient.Client
|
||||||
|
mu sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
type MieruOption struct {
|
||||||
|
BasicOption
|
||||||
|
Name string `proxy:"name"`
|
||||||
|
Server string `proxy:"server"`
|
||||||
|
Port int `proxy:"port,omitempty"`
|
||||||
|
PortRange string `proxy:"port-range,omitempty"`
|
||||||
|
Transport string `proxy:"transport"`
|
||||||
|
UserName string `proxy:"username"`
|
||||||
|
Password string `proxy:"password"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DialContext implements C.ProxyAdapter
|
||||||
|
func (m *Mieru) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.Conn, error) {
|
||||||
|
if err := m.ensureClientIsRunning(opts...); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
addr := metadataToMieruNetAddrSpec(metadata)
|
||||||
|
c, err := m.client.DialContext(ctx, addr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("dial to %s failed: %w", addr, err)
|
||||||
|
}
|
||||||
|
return NewConn(c, m), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProxyInfo implements C.ProxyAdapter
|
||||||
|
func (m *Mieru) ProxyInfo() C.ProxyInfo {
|
||||||
|
info := m.Base.ProxyInfo()
|
||||||
|
info.DialerProxy = m.option.DialerProxy
|
||||||
|
return info
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Mieru) ensureClientIsRunning(opts ...dialer.Option) error {
|
||||||
|
m.mu.Lock()
|
||||||
|
defer m.mu.Unlock()
|
||||||
|
|
||||||
|
if m.client.IsRunning() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a dialer and add it to the client config, before starting the client.
|
||||||
|
var dialer C.Dialer = dialer.NewDialer(m.Base.DialOptions(opts...)...)
|
||||||
|
var err error
|
||||||
|
if len(m.option.DialerProxy) > 0 {
|
||||||
|
dialer, err = proxydialer.NewByName(m.option.DialerProxy, dialer)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
config, err := m.client.Load()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
config.Dialer = dialer
|
||||||
|
if err := m.client.Store(config); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := m.client.Start(); err != nil {
|
||||||
|
return fmt.Errorf("failed to start mieru client: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMieru(option MieruOption) (*Mieru, error) {
|
||||||
|
config, err := buildMieruClientConfig(option)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to build mieru client config: %w", err)
|
||||||
|
}
|
||||||
|
c := mieruclient.NewClient()
|
||||||
|
if err := c.Store(config); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to store mieru client config: %w", err)
|
||||||
|
}
|
||||||
|
// Client is started lazily on the first use.
|
||||||
|
|
||||||
|
var addr string
|
||||||
|
if option.Port != 0 {
|
||||||
|
addr = net.JoinHostPort(option.Server, strconv.Itoa(option.Port))
|
||||||
|
} else {
|
||||||
|
beginPort, _, _ := beginAndEndPortFromPortRange(option.PortRange)
|
||||||
|
addr = net.JoinHostPort(option.Server, strconv.Itoa(beginPort))
|
||||||
|
}
|
||||||
|
outbound := &Mieru{
|
||||||
|
Base: &Base{
|
||||||
|
name: option.Name,
|
||||||
|
addr: addr,
|
||||||
|
iface: option.Interface,
|
||||||
|
tp: C.Mieru,
|
||||||
|
udp: false,
|
||||||
|
xudp: false,
|
||||||
|
rmark: option.RoutingMark,
|
||||||
|
prefer: C.NewDNSPrefer(option.IPVersion),
|
||||||
|
},
|
||||||
|
option: &option,
|
||||||
|
client: c,
|
||||||
|
}
|
||||||
|
runtime.SetFinalizer(outbound, closeMieru)
|
||||||
|
return outbound, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func closeMieru(m *Mieru) {
|
||||||
|
m.mu.Lock()
|
||||||
|
defer m.mu.Unlock()
|
||||||
|
if m.client != nil && m.client.IsRunning() {
|
||||||
|
m.client.Stop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func metadataToMieruNetAddrSpec(metadata *C.Metadata) mierumodel.NetAddrSpec {
|
||||||
|
if metadata.Host != "" {
|
||||||
|
return mierumodel.NetAddrSpec{
|
||||||
|
AddrSpec: mierumodel.AddrSpec{
|
||||||
|
FQDN: metadata.Host,
|
||||||
|
Port: int(metadata.DstPort),
|
||||||
|
},
|
||||||
|
Net: "tcp",
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return mierumodel.NetAddrSpec{
|
||||||
|
AddrSpec: mierumodel.AddrSpec{
|
||||||
|
IP: metadata.DstIP.AsSlice(),
|
||||||
|
Port: int(metadata.DstPort),
|
||||||
|
},
|
||||||
|
Net: "tcp",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildMieruClientConfig(option MieruOption) (*mieruclient.ClientConfig, error) {
|
||||||
|
if err := validateMieruOption(option); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to validate mieru option: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
transportProtocol := mierupb.TransportProtocol_TCP.Enum()
|
||||||
|
var server *mierupb.ServerEndpoint
|
||||||
|
if net.ParseIP(option.Server) != nil {
|
||||||
|
// server is an IP address
|
||||||
|
if option.PortRange != "" {
|
||||||
|
server = &mierupb.ServerEndpoint{
|
||||||
|
IpAddress: proto.String(option.Server),
|
||||||
|
PortBindings: []*mierupb.PortBinding{
|
||||||
|
{
|
||||||
|
PortRange: proto.String(option.PortRange),
|
||||||
|
Protocol: transportProtocol,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
server = &mierupb.ServerEndpoint{
|
||||||
|
IpAddress: proto.String(option.Server),
|
||||||
|
PortBindings: []*mierupb.PortBinding{
|
||||||
|
{
|
||||||
|
Port: proto.Int32(int32(option.Port)),
|
||||||
|
Protocol: transportProtocol,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// server is a domain name
|
||||||
|
if option.PortRange != "" {
|
||||||
|
server = &mierupb.ServerEndpoint{
|
||||||
|
DomainName: proto.String(option.Server),
|
||||||
|
PortBindings: []*mierupb.PortBinding{
|
||||||
|
{
|
||||||
|
PortRange: proto.String(option.PortRange),
|
||||||
|
Protocol: transportProtocol,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
server = &mierupb.ServerEndpoint{
|
||||||
|
DomainName: proto.String(option.Server),
|
||||||
|
PortBindings: []*mierupb.PortBinding{
|
||||||
|
{
|
||||||
|
Port: proto.Int32(int32(option.Port)),
|
||||||
|
Protocol: transportProtocol,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &mieruclient.ClientConfig{
|
||||||
|
Profile: &mierupb.ClientProfile{
|
||||||
|
ProfileName: proto.String(option.Name),
|
||||||
|
User: &mierupb.User{
|
||||||
|
Name: proto.String(option.UserName),
|
||||||
|
Password: proto.String(option.Password),
|
||||||
|
},
|
||||||
|
Servers: []*mierupb.ServerEndpoint{server},
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateMieruOption(option MieruOption) error {
|
||||||
|
if option.Name == "" {
|
||||||
|
return fmt.Errorf("name is empty")
|
||||||
|
}
|
||||||
|
if option.Server == "" {
|
||||||
|
return fmt.Errorf("server is empty")
|
||||||
|
}
|
||||||
|
if option.Port == 0 && option.PortRange == "" {
|
||||||
|
return fmt.Errorf("either port or port-range must be set")
|
||||||
|
}
|
||||||
|
if option.Port != 0 && option.PortRange != "" {
|
||||||
|
return fmt.Errorf("port and port-range cannot be set at the same time")
|
||||||
|
}
|
||||||
|
if option.Port != 0 && (option.Port < 1 || option.Port > 65535) {
|
||||||
|
return fmt.Errorf("port must be between 1 and 65535")
|
||||||
|
}
|
||||||
|
if option.PortRange != "" {
|
||||||
|
begin, end, err := beginAndEndPortFromPortRange(option.PortRange)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("invalid port-range format")
|
||||||
|
}
|
||||||
|
if begin < 1 || begin > 65535 {
|
||||||
|
return fmt.Errorf("begin port must be between 1 and 65535")
|
||||||
|
}
|
||||||
|
if end < 1 || end > 65535 {
|
||||||
|
return fmt.Errorf("end port must be between 1 and 65535")
|
||||||
|
}
|
||||||
|
if begin > end {
|
||||||
|
return fmt.Errorf("begin port must be less than or equal to end port")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if option.Transport != "TCP" {
|
||||||
|
return fmt.Errorf("transport must be TCP")
|
||||||
|
}
|
||||||
|
if option.UserName == "" {
|
||||||
|
return fmt.Errorf("username is empty")
|
||||||
|
}
|
||||||
|
if option.Password == "" {
|
||||||
|
return fmt.Errorf("password is empty")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func beginAndEndPortFromPortRange(portRange string) (int, int, error) {
|
||||||
|
var begin, end int
|
||||||
|
_, err := fmt.Sscanf(portRange, "%d-%d", &begin, &end)
|
||||||
|
return begin, end, err
|
||||||
|
}
|
||||||
92
adapter/outbound/mieru_test.go
Normal file
92
adapter/outbound/mieru_test.go
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
package outbound
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestNewMieru(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
option MieruOption
|
||||||
|
wantBaseAddr string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
option: MieruOption{
|
||||||
|
Name: "test",
|
||||||
|
Server: "1.2.3.4",
|
||||||
|
Port: 10000,
|
||||||
|
Transport: "TCP",
|
||||||
|
UserName: "test",
|
||||||
|
Password: "test",
|
||||||
|
},
|
||||||
|
wantBaseAddr: "1.2.3.4:10000",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
option: MieruOption{
|
||||||
|
Name: "test",
|
||||||
|
Server: "2001:db8::1",
|
||||||
|
PortRange: "10001-10002",
|
||||||
|
Transport: "TCP",
|
||||||
|
UserName: "test",
|
||||||
|
Password: "test",
|
||||||
|
},
|
||||||
|
wantBaseAddr: "[2001:db8::1]:10001",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
option: MieruOption{
|
||||||
|
Name: "test",
|
||||||
|
Server: "example.com",
|
||||||
|
Port: 10003,
|
||||||
|
Transport: "TCP",
|
||||||
|
UserName: "test",
|
||||||
|
Password: "test",
|
||||||
|
},
|
||||||
|
wantBaseAddr: "example.com:10003",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
mieru, err := NewMieru(testCase.option)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
if mieru.addr != testCase.wantBaseAddr {
|
||||||
|
t.Errorf("got addr %q, want %q", mieru.addr, testCase.wantBaseAddr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBeginAndEndPortFromPortRange(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
input string
|
||||||
|
begin int
|
||||||
|
end int
|
||||||
|
hasErr bool
|
||||||
|
}{
|
||||||
|
{"1-10", 1, 10, false},
|
||||||
|
{"1000-2000", 1000, 2000, false},
|
||||||
|
{"65535-65535", 65535, 65535, false},
|
||||||
|
{"1", 0, 0, true},
|
||||||
|
{"1-", 0, 0, true},
|
||||||
|
{"-10", 0, 0, true},
|
||||||
|
{"a-b", 0, 0, true},
|
||||||
|
{"1-b", 0, 0, true},
|
||||||
|
{"a-10", 0, 0, true},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
begin, end, err := beginAndEndPortFromPortRange(testCase.input)
|
||||||
|
if testCase.hasErr {
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("beginAndEndPortFromPortRange(%s) should return an error", testCase.input)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("beginAndEndPortFromPortRange(%s) should not return an error, but got %v", testCase.input, err)
|
||||||
|
}
|
||||||
|
if begin != testCase.begin {
|
||||||
|
t.Errorf("beginAndEndPortFromPortRange(%s) begin port mismatch, got %d, want %d", testCase.input, begin, testCase.begin)
|
||||||
|
}
|
||||||
|
if end != testCase.end {
|
||||||
|
t.Errorf("beginAndEndPortFromPortRange(%s) end port mismatch, got %d, want %d", testCase.input, end, testCase.end)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -196,6 +196,13 @@ func (ss *ShadowSocks) SupportWithDialer() C.NetWork {
|
|||||||
return C.ALLNet
|
return C.ALLNet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ProxyInfo implements C.ProxyAdapter
|
||||||
|
func (ss *ShadowSocks) ProxyInfo() C.ProxyInfo {
|
||||||
|
info := ss.Base.ProxyInfo()
|
||||||
|
info.DialerProxy = ss.option.DialerProxy
|
||||||
|
return info
|
||||||
|
}
|
||||||
|
|
||||||
// ListenPacketOnStreamConn implements C.ProxyAdapter
|
// ListenPacketOnStreamConn implements C.ProxyAdapter
|
||||||
func (ss *ShadowSocks) ListenPacketOnStreamConn(ctx context.Context, c net.Conn, metadata *C.Metadata) (_ C.PacketConn, err error) {
|
func (ss *ShadowSocks) ListenPacketOnStreamConn(ctx context.Context, c net.Conn, metadata *C.Metadata) (_ C.PacketConn, err error) {
|
||||||
if ss.option.UDPOverTCP {
|
if ss.option.UDPOverTCP {
|
||||||
|
|||||||
@@ -122,6 +122,13 @@ func (ssr *ShadowSocksR) SupportWithDialer() C.NetWork {
|
|||||||
return C.ALLNet
|
return C.ALLNet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ProxyInfo implements C.ProxyAdapter
|
||||||
|
func (ssr *ShadowSocksR) ProxyInfo() C.ProxyInfo {
|
||||||
|
info := ssr.Base.ProxyInfo()
|
||||||
|
info.DialerProxy = ssr.option.DialerProxy
|
||||||
|
return info
|
||||||
|
}
|
||||||
|
|
||||||
func NewShadowSocksR(option ShadowSocksROption) (*ShadowSocksR, error) {
|
func NewShadowSocksR(option ShadowSocksROption) (*ShadowSocksR, error) {
|
||||||
// SSR protocol compatibility
|
// SSR protocol compatibility
|
||||||
// https://github.com/metacubex/mihomo/pull/2056
|
// https://github.com/metacubex/mihomo/pull/2056
|
||||||
|
|||||||
@@ -97,6 +97,12 @@ func (s *SingMux) SupportUOT() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *SingMux) ProxyInfo() C.ProxyInfo {
|
||||||
|
info := s.ProxyAdapter.ProxyInfo()
|
||||||
|
info.SMUX = true
|
||||||
|
return info
|
||||||
|
}
|
||||||
|
|
||||||
func closeSingMux(s *SingMux) {
|
func closeSingMux(s *SingMux) {
|
||||||
_ = s.client.Close()
|
_ = s.client.Close()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -141,6 +141,13 @@ func (s *Snell) SupportUOT() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ProxyInfo implements C.ProxyAdapter
|
||||||
|
func (s *Snell) ProxyInfo() C.ProxyInfo {
|
||||||
|
info := s.Base.ProxyInfo()
|
||||||
|
info.DialerProxy = s.option.DialerProxy
|
||||||
|
return info
|
||||||
|
}
|
||||||
|
|
||||||
func NewSnell(option SnellOption) (*Snell, error) {
|
func NewSnell(option SnellOption) (*Snell, error) {
|
||||||
addr := net.JoinHostPort(option.Server, strconv.Itoa(option.Port))
|
addr := net.JoinHostPort(option.Server, strconv.Itoa(option.Port))
|
||||||
psk := []byte(option.Psk)
|
psk := []byte(option.Psk)
|
||||||
|
|||||||
@@ -171,6 +171,13 @@ func (ss *Socks5) ListenPacketContext(ctx context.Context, metadata *C.Metadata,
|
|||||||
return newPacketConn(&socksPacketConn{PacketConn: pc, rAddr: bindUDPAddr, tcpConn: c}, ss), nil
|
return newPacketConn(&socksPacketConn{PacketConn: pc, rAddr: bindUDPAddr, tcpConn: c}, ss), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ProxyInfo implements C.ProxyAdapter
|
||||||
|
func (ss *Socks5) ProxyInfo() C.ProxyInfo {
|
||||||
|
info := ss.Base.ProxyInfo()
|
||||||
|
info.DialerProxy = ss.option.DialerProxy
|
||||||
|
return info
|
||||||
|
}
|
||||||
|
|
||||||
func NewSocks5(option Socks5Option) (*Socks5, error) {
|
func NewSocks5(option Socks5Option) (*Socks5, error) {
|
||||||
var tlsConfig *tls.Config
|
var tlsConfig *tls.Config
|
||||||
if option.TLS {
|
if option.TLS {
|
||||||
|
|||||||
@@ -121,6 +121,13 @@ func closeSsh(s *Ssh) {
|
|||||||
_ = s.client.Close()
|
_ = s.client.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ProxyInfo implements C.ProxyAdapter
|
||||||
|
func (s *Ssh) ProxyInfo() C.ProxyInfo {
|
||||||
|
info := s.Base.ProxyInfo()
|
||||||
|
info.DialerProxy = s.option.DialerProxy
|
||||||
|
return info
|
||||||
|
}
|
||||||
|
|
||||||
func NewSsh(option SshOption) (*Ssh, error) {
|
func NewSsh(option SshOption) (*Ssh, error) {
|
||||||
addr := net.JoinHostPort(option.Server, strconv.Itoa(option.Port))
|
addr := net.JoinHostPort(option.Server, strconv.Itoa(option.Port))
|
||||||
|
|
||||||
|
|||||||
@@ -244,6 +244,13 @@ func (t *Trojan) SupportUOT() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ProxyInfo implements C.ProxyAdapter
|
||||||
|
func (t *Trojan) ProxyInfo() C.ProxyInfo {
|
||||||
|
info := t.Base.ProxyInfo()
|
||||||
|
info.DialerProxy = t.option.DialerProxy
|
||||||
|
return info
|
||||||
|
}
|
||||||
|
|
||||||
func NewTrojan(option TrojanOption) (*Trojan, error) {
|
func NewTrojan(option TrojanOption) (*Trojan, error) {
|
||||||
addr := net.JoinHostPort(option.Server, strconv.Itoa(option.Port))
|
addr := net.JoinHostPort(option.Server, strconv.Itoa(option.Port))
|
||||||
|
|
||||||
|
|||||||
@@ -146,6 +146,13 @@ func (t *Tuic) dialWithDialer(ctx context.Context, dialer C.Dialer) (transport *
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ProxyInfo implements C.ProxyAdapter
|
||||||
|
func (t *Tuic) ProxyInfo() C.ProxyInfo {
|
||||||
|
info := t.Base.ProxyInfo()
|
||||||
|
info.DialerProxy = t.option.DialerProxy
|
||||||
|
return info
|
||||||
|
}
|
||||||
|
|
||||||
func NewTuic(option TuicOption) (*Tuic, error) {
|
func NewTuic(option TuicOption) (*Tuic, error) {
|
||||||
addr := net.JoinHostPort(option.Server, strconv.Itoa(option.Port))
|
addr := net.JoinHostPort(option.Server, strconv.Itoa(option.Port))
|
||||||
serverName := option.Server
|
serverName := option.Server
|
||||||
|
|||||||
@@ -379,6 +379,13 @@ func (v *Vless) SupportUOT() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ProxyInfo implements C.ProxyAdapter
|
||||||
|
func (v *Vless) ProxyInfo() C.ProxyInfo {
|
||||||
|
info := v.Base.ProxyInfo()
|
||||||
|
info.DialerProxy = v.option.DialerProxy
|
||||||
|
return info
|
||||||
|
}
|
||||||
|
|
||||||
func parseVlessAddr(metadata *C.Metadata, xudp bool) *vless.DstAddr {
|
func parseVlessAddr(metadata *C.Metadata, xudp bool) *vless.DstAddr {
|
||||||
var addrType byte
|
var addrType byte
|
||||||
var addr []byte
|
var addr []byte
|
||||||
|
|||||||
@@ -388,6 +388,13 @@ func (v *Vmess) SupportWithDialer() C.NetWork {
|
|||||||
return C.ALLNet
|
return C.ALLNet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ProxyInfo implements C.ProxyAdapter
|
||||||
|
func (v *Vmess) ProxyInfo() C.ProxyInfo {
|
||||||
|
info := v.Base.ProxyInfo()
|
||||||
|
info.DialerProxy = v.option.DialerProxy
|
||||||
|
return info
|
||||||
|
}
|
||||||
|
|
||||||
// ListenPacketOnStreamConn implements C.ProxyAdapter
|
// ListenPacketOnStreamConn implements C.ProxyAdapter
|
||||||
func (v *Vmess) ListenPacketOnStreamConn(ctx context.Context, c net.Conn, metadata *C.Metadata) (_ C.PacketConn, err error) {
|
func (v *Vmess) ListenPacketOnStreamConn(ctx context.Context, c net.Conn, metadata *C.Metadata) (_ C.PacketConn, err error) {
|
||||||
// vmess use stream-oriented udp with a special address, so we need a net.UDPAddr
|
// vmess use stream-oriented udp with a special address, so we need a net.UDPAddr
|
||||||
|
|||||||
@@ -611,18 +611,11 @@ func (r *refProxyAdapter) SupportUDP() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *refProxyAdapter) SupportXUDP() bool {
|
func (r *refProxyAdapter) ProxyInfo() C.ProxyInfo {
|
||||||
if r.proxyAdapter != nil {
|
if r.proxyAdapter != nil {
|
||||||
return r.proxyAdapter.SupportXUDP()
|
return r.proxyAdapter.ProxyInfo()
|
||||||
}
|
}
|
||||||
return false
|
return C.ProxyInfo{}
|
||||||
}
|
|
||||||
|
|
||||||
func (r *refProxyAdapter) SupportTFO() bool {
|
|
||||||
if r.proxyAdapter != nil {
|
|
||||||
return r.proxyAdapter.SupportTFO()
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *refProxyAdapter) MarshalJSON() ([]byte, error) {
|
func (r *refProxyAdapter) MarshalJSON() ([]byte, error) {
|
||||||
|
|||||||
@@ -141,6 +141,13 @@ func ParseProxy(mapping map[string]any) (C.Proxy, error) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
proxy, err = outbound.NewSsh(*sshOption)
|
proxy, err = outbound.NewSsh(*sshOption)
|
||||||
|
case "mieru":
|
||||||
|
mieruOption := &outbound.MieruOption{}
|
||||||
|
err = decoder.Decode(mapping, mieruOption)
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
proxy, err = outbound.NewMieru(*mieruOption)
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("unsupport proxy type: %s", proxyType)
|
return nil, fmt.Errorf("unsupport proxy type: %s", proxyType)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ type proxyProviderSchema struct {
|
|||||||
ExcludeFilter string `provider:"exclude-filter,omitempty"`
|
ExcludeFilter string `provider:"exclude-filter,omitempty"`
|
||||||
ExcludeType string `provider:"exclude-type,omitempty"`
|
ExcludeType string `provider:"exclude-type,omitempty"`
|
||||||
DialerProxy string `provider:"dialer-proxy,omitempty"`
|
DialerProxy string `provider:"dialer-proxy,omitempty"`
|
||||||
|
SizeLimit int64 `provider:"size-limit,omitempty"`
|
||||||
|
|
||||||
HealthCheck healthCheckSchema `provider:"health-check,omitempty"`
|
HealthCheck healthCheckSchema `provider:"health-check,omitempty"`
|
||||||
Override OverrideSchema `provider:"override,omitempty"`
|
Override OverrideSchema `provider:"override,omitempty"`
|
||||||
@@ -111,7 +112,7 @@ func ParseProxyProvider(name string, mapping map[string]any) (types.ProxyProvide
|
|||||||
return nil, fmt.Errorf("%w: %s", errSubPath, path)
|
return nil, fmt.Errorf("%w: %s", errSubPath, path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vehicle = resource.NewHTTPVehicle(schema.URL, path, schema.Proxy, schema.Header, resource.DefaultHttpTimeout)
|
vehicle = resource.NewHTTPVehicle(schema.URL, path, schema.Proxy, schema.Header, resource.DefaultHttpTimeout, schema.SizeLimit)
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("%w: %s", errVehicleType, schema.Type)
|
return nil, fmt.Errorf("%w: %s", errVehicleType, schema.Type)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ type Interface struct {
|
|||||||
Name string
|
Name string
|
||||||
Addresses []netip.Prefix
|
Addresses []netip.Prefix
|
||||||
HardwareAddr net.HardwareAddr
|
HardwareAddr net.HardwareAddr
|
||||||
|
Flags net.Flags
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -66,6 +67,7 @@ func Interfaces() (map[string]*Interface, error) {
|
|||||||
Name: iface.Name,
|
Name: iface.Name,
|
||||||
Addresses: ipNets,
|
Addresses: ipNets,
|
||||||
HardwareAddr: iface.HardwareAddr,
|
HardwareAddr: iface.HardwareAddr,
|
||||||
|
Flags: iface.Flags,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ func KeepAliveInterval() time.Duration {
|
|||||||
|
|
||||||
func SetDisableKeepAlive(disable bool) {
|
func SetDisableKeepAlive(disable bool) {
|
||||||
if runtime.GOOS == "android" {
|
if runtime.GOOS == "android" {
|
||||||
setDisableKeepAlive(false)
|
setDisableKeepAlive(true)
|
||||||
} else {
|
} else {
|
||||||
setDisableKeepAlive(disable)
|
setDisableKeepAlive(disable)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,14 +4,25 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"github.com/metacubex/mihomo/common/callback"
|
"github.com/metacubex/mihomo/common/callback"
|
||||||
"github.com/metacubex/mihomo/component/iface"
|
"github.com/metacubex/mihomo/component/iface"
|
||||||
C "github.com/metacubex/mihomo/constant"
|
C "github.com/metacubex/mihomo/constant"
|
||||||
|
"github.com/metacubex/mihomo/constant/features"
|
||||||
|
|
||||||
"github.com/puzpuzpuz/xsync/v3"
|
"github.com/puzpuzpuz/xsync/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var disableLoopBackDetector, _ = strconv.ParseBool(os.Getenv("DISABLE_LOOPBACK_DETECTOR"))
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
if features.CMFA {
|
||||||
|
disableLoopBackDetector = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var ErrReject = errors.New("reject loopback connection")
|
var ErrReject = errors.New("reject loopback connection")
|
||||||
|
|
||||||
type Detector struct {
|
type Detector struct {
|
||||||
@@ -20,6 +31,9 @@ type Detector struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewDetector() *Detector {
|
func NewDetector() *Detector {
|
||||||
|
if disableLoopBackDetector {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return &Detector{
|
return &Detector{
|
||||||
connMap: xsync.NewMapOf[netip.AddrPort, struct{}](),
|
connMap: xsync.NewMapOf[netip.AddrPort, struct{}](),
|
||||||
packetConnMap: xsync.NewMapOf[uint16, struct{}](),
|
packetConnMap: xsync.NewMapOf[uint16, struct{}](),
|
||||||
@@ -27,6 +41,9 @@ func NewDetector() *Detector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l *Detector) NewConn(conn C.Conn) C.Conn {
|
func (l *Detector) NewConn(conn C.Conn) C.Conn {
|
||||||
|
if l == nil || l.connMap == nil {
|
||||||
|
return conn
|
||||||
|
}
|
||||||
metadata := C.Metadata{}
|
metadata := C.Metadata{}
|
||||||
if metadata.SetRemoteAddr(conn.LocalAddr()) != nil {
|
if metadata.SetRemoteAddr(conn.LocalAddr()) != nil {
|
||||||
return conn
|
return conn
|
||||||
@@ -42,6 +59,9 @@ func (l *Detector) NewConn(conn C.Conn) C.Conn {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l *Detector) NewPacketConn(conn C.PacketConn) C.PacketConn {
|
func (l *Detector) NewPacketConn(conn C.PacketConn) C.PacketConn {
|
||||||
|
if l == nil || l.packetConnMap == nil {
|
||||||
|
return conn
|
||||||
|
}
|
||||||
metadata := C.Metadata{}
|
metadata := C.Metadata{}
|
||||||
if metadata.SetRemoteAddr(conn.LocalAddr()) != nil {
|
if metadata.SetRemoteAddr(conn.LocalAddr()) != nil {
|
||||||
return conn
|
return conn
|
||||||
@@ -58,6 +78,9 @@ func (l *Detector) NewPacketConn(conn C.PacketConn) C.PacketConn {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l *Detector) CheckConn(metadata *C.Metadata) error {
|
func (l *Detector) CheckConn(metadata *C.Metadata) error {
|
||||||
|
if l == nil || l.connMap == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
connAddr := metadata.SourceAddrPort()
|
connAddr := metadata.SourceAddrPort()
|
||||||
if !connAddr.IsValid() {
|
if !connAddr.IsValid() {
|
||||||
return nil
|
return nil
|
||||||
@@ -69,6 +92,9 @@ func (l *Detector) CheckConn(metadata *C.Metadata) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l *Detector) CheckPacketConn(metadata *C.Metadata) error {
|
func (l *Detector) CheckPacketConn(metadata *C.Metadata) error {
|
||||||
|
if l == nil || l.packetConnMap == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
connAddr := metadata.SourceAddrPort()
|
connAddr := metadata.SourceAddrPort()
|
||||||
if !connAddr.IsValid() {
|
if !connAddr.IsValid() {
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/metacubex/mihomo/log"
|
||||||
"github.com/oschwald/maxminddb-golang"
|
"github.com/oschwald/maxminddb-golang"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -23,11 +24,16 @@ type ASNReader struct {
|
|||||||
*maxminddb.Reader
|
*maxminddb.Reader
|
||||||
}
|
}
|
||||||
|
|
||||||
type ASNResult struct {
|
type GeoLite2 struct {
|
||||||
AutonomousSystemNumber uint32 `maxminddb:"autonomous_system_number"`
|
AutonomousSystemNumber uint32 `maxminddb:"autonomous_system_number"`
|
||||||
AutonomousSystemOrganization string `maxminddb:"autonomous_system_organization"`
|
AutonomousSystemOrganization string `maxminddb:"autonomous_system_organization"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type IPInfo struct {
|
||||||
|
ASN string `maxminddb:"asn"`
|
||||||
|
Name string `maxminddb:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
func (r IPReader) LookupCode(ipAddress net.IP) []string {
|
func (r IPReader) LookupCode(ipAddress net.IP) []string {
|
||||||
switch r.databaseType {
|
switch r.databaseType {
|
||||||
case typeMaxmind:
|
case typeMaxmind:
|
||||||
@@ -66,8 +72,18 @@ func (r IPReader) LookupCode(ipAddress net.IP) []string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r ASNReader) LookupASN(ip net.IP) ASNResult {
|
func (r ASNReader) LookupASN(ip net.IP) (string, string) {
|
||||||
var result ASNResult
|
switch r.Metadata.DatabaseType {
|
||||||
r.Lookup(ip, &result)
|
case "GeoLite2-ASN", "DBIP-ASN-Lite (compat=GeoLite2-ASN)":
|
||||||
return result
|
var result GeoLite2
|
||||||
|
_ = r.Lookup(ip, &result)
|
||||||
|
return fmt.Sprint(result.AutonomousSystemNumber), result.AutonomousSystemOrganization
|
||||||
|
case "ipinfo generic_asn_free.mmdb":
|
||||||
|
var result IPInfo
|
||||||
|
_ = r.Lookup(ip, &result)
|
||||||
|
return result.ASN[2:], result.Name
|
||||||
|
default:
|
||||||
|
log.Warnln("Unsupported ASN type: %s", r.Metadata.DatabaseType)
|
||||||
|
}
|
||||||
|
return "", ""
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ func newSearcher(isV4, isTCP bool) *searcher {
|
|||||||
func getTransportTable(fn uintptr, family int, class int) ([]byte, error) {
|
func getTransportTable(fn uintptr, family int, class int) ([]byte, error) {
|
||||||
for size, buf := uint32(8), make([]byte, 8); ; {
|
for size, buf := uint32(8), make([]byte, 8); ; {
|
||||||
ptr := unsafe.Pointer(&buf[0])
|
ptr := unsafe.Pointer(&buf[0])
|
||||||
err, _, _ := syscall.SyscallN(fn, uintptr(ptr), uintptr(unsafe.Pointer(&size)), 0, uintptr(family), uintptr(class), 0)
|
err, _, _ := syscall.Syscall6(fn, 6, uintptr(ptr), uintptr(unsafe.Pointer(&size)), 0, uintptr(family), uintptr(class), 0)
|
||||||
|
|
||||||
switch err {
|
switch err {
|
||||||
case 0:
|
case 0:
|
||||||
@@ -215,13 +215,13 @@ func getExecPathFromPID(pid uint32) (string, error) {
|
|||||||
|
|
||||||
buf := make([]uint16, syscall.MAX_LONG_PATH)
|
buf := make([]uint16, syscall.MAX_LONG_PATH)
|
||||||
size := uint32(len(buf))
|
size := uint32(len(buf))
|
||||||
r1, _, err := syscall.SyscallN(
|
r1, _, err := syscall.Syscall6(
|
||||||
queryProcName,
|
queryProcName, 4,
|
||||||
uintptr(h),
|
uintptr(h),
|
||||||
uintptr(0),
|
uintptr(0),
|
||||||
uintptr(unsafe.Pointer(&buf[0])),
|
uintptr(unsafe.Pointer(&buf[0])),
|
||||||
uintptr(unsafe.Pointer(&size)),
|
uintptr(unsafe.Pointer(&size)),
|
||||||
)
|
0, 0)
|
||||||
if r1 == 0 {
|
if r1 == 0 {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,12 +84,13 @@ func NewFileVehicle(path string) *FileVehicle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type HTTPVehicle struct {
|
type HTTPVehicle struct {
|
||||||
url string
|
url string
|
||||||
path string
|
path string
|
||||||
proxy string
|
proxy string
|
||||||
header http.Header
|
header http.Header
|
||||||
timeout time.Duration
|
timeout time.Duration
|
||||||
provider types.ProxyProvider
|
sizeLimit int64
|
||||||
|
provider types.ProxyProvider
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *HTTPVehicle) Url() string {
|
func (h *HTTPVehicle) Url() string {
|
||||||
@@ -151,7 +152,11 @@ func (h *HTTPVehicle) Read(ctx context.Context, oldHash utils.HashType) (buf []b
|
|||||||
err = errors.New(resp.Status)
|
err = errors.New(resp.Status)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
buf, err = io.ReadAll(resp.Body)
|
var reader io.Reader = resp.Body
|
||||||
|
if h.sizeLimit > 0 {
|
||||||
|
reader = io.LimitReader(reader, h.sizeLimit)
|
||||||
|
}
|
||||||
|
buf, err = io.ReadAll(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -166,12 +171,13 @@ func (h *HTTPVehicle) Read(ctx context.Context, oldHash utils.HashType) (buf []b
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHTTPVehicle(url string, path string, proxy string, header http.Header, timeout time.Duration) *HTTPVehicle {
|
func NewHTTPVehicle(url string, path string, proxy string, header http.Header, timeout time.Duration, sizeLimit int64) *HTTPVehicle {
|
||||||
return &HTTPVehicle{
|
return &HTTPVehicle{
|
||||||
url: url,
|
url: url,
|
||||||
path: path,
|
path: path,
|
||||||
proxy: proxy,
|
proxy: proxy,
|
||||||
header: header,
|
header: header,
|
||||||
timeout: timeout,
|
timeout: timeout,
|
||||||
|
sizeLimit: sizeLimit,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ func SetGeoUpdateInterval(newGeoUpdateInterval int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func UpdateMMDB() (err error) {
|
func UpdateMMDB() (err error) {
|
||||||
vehicle := resource.NewHTTPVehicle(geodata.MmdbUrl(), C.Path.MMDB(), "", nil, defaultHttpTimeout)
|
vehicle := resource.NewHTTPVehicle(geodata.MmdbUrl(), C.Path.MMDB(), "", nil, defaultHttpTimeout, 0)
|
||||||
var oldHash utils.HashType
|
var oldHash utils.HashType
|
||||||
if buf, err := os.ReadFile(vehicle.Path()); err == nil {
|
if buf, err := os.ReadFile(vehicle.Path()); err == nil {
|
||||||
oldHash = utils.MakeHash(buf)
|
oldHash = utils.MakeHash(buf)
|
||||||
@@ -76,7 +76,7 @@ func UpdateMMDB() (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func UpdateASN() (err error) {
|
func UpdateASN() (err error) {
|
||||||
vehicle := resource.NewHTTPVehicle(geodata.ASNUrl(), C.Path.ASN(), "", nil, defaultHttpTimeout)
|
vehicle := resource.NewHTTPVehicle(geodata.ASNUrl(), C.Path.ASN(), "", nil, defaultHttpTimeout, 0)
|
||||||
var oldHash utils.HashType
|
var oldHash utils.HashType
|
||||||
if buf, err := os.ReadFile(vehicle.Path()); err == nil {
|
if buf, err := os.ReadFile(vehicle.Path()); err == nil {
|
||||||
oldHash = utils.MakeHash(buf)
|
oldHash = utils.MakeHash(buf)
|
||||||
@@ -109,7 +109,7 @@ func UpdateASN() (err error) {
|
|||||||
func UpdateGeoIp() (err error) {
|
func UpdateGeoIp() (err error) {
|
||||||
geoLoader, err := geodata.GetGeoDataLoader("standard")
|
geoLoader, err := geodata.GetGeoDataLoader("standard")
|
||||||
|
|
||||||
vehicle := resource.NewHTTPVehicle(geodata.GeoIpUrl(), C.Path.GeoIP(), "", nil, defaultHttpTimeout)
|
vehicle := resource.NewHTTPVehicle(geodata.GeoIpUrl(), C.Path.GeoIP(), "", nil, defaultHttpTimeout, 0)
|
||||||
var oldHash utils.HashType
|
var oldHash utils.HashType
|
||||||
if buf, err := os.ReadFile(vehicle.Path()); err == nil {
|
if buf, err := os.ReadFile(vehicle.Path()); err == nil {
|
||||||
oldHash = utils.MakeHash(buf)
|
oldHash = utils.MakeHash(buf)
|
||||||
@@ -139,7 +139,7 @@ func UpdateGeoIp() (err error) {
|
|||||||
func UpdateGeoSite() (err error) {
|
func UpdateGeoSite() (err error) {
|
||||||
geoLoader, err := geodata.GetGeoDataLoader("standard")
|
geoLoader, err := geodata.GetGeoDataLoader("standard")
|
||||||
|
|
||||||
vehicle := resource.NewHTTPVehicle(geodata.GeoSiteUrl(), C.Path.GeoSite(), "", nil, defaultHttpTimeout)
|
vehicle := resource.NewHTTPVehicle(geodata.GeoSiteUrl(), C.Path.GeoSite(), "", nil, defaultHttpTimeout, 0)
|
||||||
var oldHash utils.HashType
|
var oldHash utils.HashType
|
||||||
if buf, err := os.ReadFile(vehicle.Path()); err == nil {
|
if buf, err := os.ReadFile(vehicle.Path()); err == nil {
|
||||||
oldHash = utils.MakeHash(buf)
|
oldHash = utils.MakeHash(buf)
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ const (
|
|||||||
WireGuard
|
WireGuard
|
||||||
Tuic
|
Tuic
|
||||||
Ssh
|
Ssh
|
||||||
|
Mieru
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -99,13 +100,24 @@ type Dialer interface {
|
|||||||
ListenPacket(ctx context.Context, network, address string, rAddrPort netip.AddrPort) (net.PacketConn, error)
|
ListenPacket(ctx context.Context, network, address string, rAddrPort netip.AddrPort) (net.PacketConn, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ProxyInfo struct {
|
||||||
|
XUDP bool
|
||||||
|
TFO bool
|
||||||
|
MPTCP bool
|
||||||
|
SMUX bool
|
||||||
|
Interface string
|
||||||
|
RoutingMark int
|
||||||
|
DialerProxy string
|
||||||
|
}
|
||||||
|
|
||||||
type ProxyAdapter interface {
|
type ProxyAdapter interface {
|
||||||
Name() string
|
Name() string
|
||||||
Type() AdapterType
|
Type() AdapterType
|
||||||
Addr() string
|
Addr() string
|
||||||
SupportUDP() bool
|
SupportUDP() bool
|
||||||
SupportXUDP() bool
|
|
||||||
SupportTFO() bool
|
// ProxyInfo contains some extra information maybe useful for MarshalJSON
|
||||||
|
ProxyInfo() ProxyInfo
|
||||||
MarshalJSON() ([]byte, error)
|
MarshalJSON() ([]byte, error)
|
||||||
|
|
||||||
// Deprecated: use DialContextWithDialer and ListenPacketWithDialer instead.
|
// Deprecated: use DialContextWithDialer and ListenPacketWithDialer instead.
|
||||||
@@ -215,7 +227,8 @@ func (at AdapterType) String() string {
|
|||||||
return "Tuic"
|
return "Tuic"
|
||||||
case Ssh:
|
case Ssh:
|
||||||
return "Ssh"
|
return "Ssh"
|
||||||
|
case Mieru:
|
||||||
|
return "Mieru"
|
||||||
case Relay:
|
case Relay:
|
||||||
return "Relay"
|
return "Relay"
|
||||||
case Selector:
|
case Selector:
|
||||||
|
|||||||
@@ -846,6 +846,16 @@ proxies: # socks5
|
|||||||
password: password
|
password: password
|
||||||
privateKey: path
|
privateKey: path
|
||||||
|
|
||||||
|
# mieru
|
||||||
|
- name: mieru
|
||||||
|
type: mieru
|
||||||
|
server: 1.2.3.4
|
||||||
|
port: 2999
|
||||||
|
# port-range: 2090-2099 #(不可同时填写 port 和 port-range)
|
||||||
|
transport: TCP # 只支持 TCP
|
||||||
|
username: user
|
||||||
|
password: password
|
||||||
|
|
||||||
# dns 出站会将请求劫持到内部 dns 模块,所有请求均在内部处理
|
# dns 出站会将请求劫持到内部 dns 模块,所有请求均在内部处理
|
||||||
- name: "dns-out"
|
- name: "dns-out"
|
||||||
type: dns
|
type: dns
|
||||||
@@ -930,6 +940,7 @@ proxy-providers:
|
|||||||
interval: 3600
|
interval: 3600
|
||||||
path: ./provider1.yaml # 默认只允许存储在 mihomo 的 Home Dir,如果想存储到任意位置,添加环境变量 SKIP_SAFE_PATH_CHECK=1
|
path: ./provider1.yaml # 默认只允许存储在 mihomo 的 Home Dir,如果想存储到任意位置,添加环境变量 SKIP_SAFE_PATH_CHECK=1
|
||||||
proxy: DIRECT
|
proxy: DIRECT
|
||||||
|
# size-limit: 10240 # 限制下载文件最大为10kb,默认为0即不限制文件大小
|
||||||
header:
|
header:
|
||||||
User-Agent:
|
User-Agent:
|
||||||
- "Clash/v1.18.0"
|
- "Clash/v1.18.0"
|
||||||
@@ -977,6 +988,7 @@ rule-providers:
|
|||||||
type: http # http 的 path 可空置,默认储存路径为 homedir 的 rules 文件夹,文件名为 url 的 md5
|
type: http # http 的 path 可空置,默认储存路径为 homedir 的 rules 文件夹,文件名为 url 的 md5
|
||||||
url: "url"
|
url: "url"
|
||||||
proxy: DIRECT
|
proxy: DIRECT
|
||||||
|
# size-limit: 10240 # 限制下载文件最大为10kb,默认为0即不限制文件大小
|
||||||
rule2:
|
rule2:
|
||||||
behavior: classical
|
behavior: classical
|
||||||
interval: 259200
|
interval: 259200
|
||||||
|
|||||||
29
go.mod
29
go.mod
@@ -7,6 +7,7 @@ require (
|
|||||||
github.com/bahlo/generic-list-go v0.2.0
|
github.com/bahlo/generic-list-go v0.2.0
|
||||||
github.com/coreos/go-iptables v0.8.0
|
github.com/coreos/go-iptables v0.8.0
|
||||||
github.com/dlclark/regexp2 v1.11.4
|
github.com/dlclark/regexp2 v1.11.4
|
||||||
|
github.com/enfein/mieru/v3 v3.8.3
|
||||||
github.com/go-chi/chi/v5 v5.1.0
|
github.com/go-chi/chi/v5 v5.1.0
|
||||||
github.com/go-chi/render v1.0.3
|
github.com/go-chi/render v1.0.3
|
||||||
github.com/gobwas/ws v1.4.0
|
github.com/gobwas/ws v1.4.0
|
||||||
@@ -20,14 +21,14 @@ require (
|
|||||||
github.com/metacubex/bbolt v0.0.0-20240822011022-aed6d4850399
|
github.com/metacubex/bbolt v0.0.0-20240822011022-aed6d4850399
|
||||||
github.com/metacubex/chacha v0.1.0
|
github.com/metacubex/chacha v0.1.0
|
||||||
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759
|
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759
|
||||||
github.com/metacubex/quic-go v0.48.1-0.20241021013658-51ca987e0174
|
github.com/metacubex/quic-go v0.48.3-0.20241126053724-b69fea3888da
|
||||||
github.com/metacubex/randv2 v0.2.0
|
github.com/metacubex/randv2 v0.2.0
|
||||||
github.com/metacubex/sing-quic v0.0.0-20240827003841-cd97758ed8b4
|
github.com/metacubex/sing-quic v0.0.0-20240827003841-cd97758ed8b4
|
||||||
github.com/metacubex/sing-shadowsocks v0.2.8
|
github.com/metacubex/sing-shadowsocks v0.2.8
|
||||||
github.com/metacubex/sing-shadowsocks2 v0.2.2
|
github.com/metacubex/sing-shadowsocks2 v0.2.2
|
||||||
github.com/metacubex/sing-tun v0.2.7-0.20241021011113-857bcd6ee47c
|
github.com/metacubex/sing-tun v0.4.2
|
||||||
github.com/metacubex/sing-vmess v0.1.9-0.20240719134745-1df6fb20bbf9
|
github.com/metacubex/sing-vmess v0.1.9-0.20240719134745-1df6fb20bbf9
|
||||||
github.com/metacubex/sing-wireguard v0.0.0-20240924052438-b0976fc59ea3
|
github.com/metacubex/sing-wireguard v0.0.0-20241126021510-0827d417b589
|
||||||
github.com/metacubex/tfo-go v0.0.0-20241006021335-daedaf0ca7aa
|
github.com/metacubex/tfo-go v0.0.0-20241006021335-daedaf0ca7aa
|
||||||
github.com/metacubex/utls v1.6.6
|
github.com/metacubex/utls v1.6.6
|
||||||
github.com/metacubex/wireguard-go v0.0.0-20240922131502-c182e7471181
|
github.com/metacubex/wireguard-go v0.0.0-20240922131502-c182e7471181
|
||||||
@@ -39,7 +40,7 @@ require (
|
|||||||
github.com/sagernet/cors v1.2.1
|
github.com/sagernet/cors v1.2.1
|
||||||
github.com/sagernet/fswatch v0.1.1
|
github.com/sagernet/fswatch v0.1.1
|
||||||
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a
|
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a
|
||||||
github.com/sagernet/sing v0.5.0-rc.4
|
github.com/sagernet/sing v0.5.1
|
||||||
github.com/sagernet/sing-mux v0.2.1-0.20240124034317-9bfb33698bb6
|
github.com/sagernet/sing-mux v0.2.1-0.20240124034317-9bfb33698bb6
|
||||||
github.com/sagernet/sing-shadowtls v0.1.4
|
github.com/sagernet/sing-shadowtls v0.1.4
|
||||||
github.com/samber/lo v1.47.0
|
github.com/samber/lo v1.47.0
|
||||||
@@ -51,10 +52,10 @@ require (
|
|||||||
gitlab.com/go-extension/aes-ccm v0.0.0-20230221065045-e58665ef23c7
|
gitlab.com/go-extension/aes-ccm v0.0.0-20230221065045-e58665ef23c7
|
||||||
go.uber.org/automaxprocs v1.6.0
|
go.uber.org/automaxprocs v1.6.0
|
||||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
|
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
|
||||||
golang.org/x/crypto v0.28.0
|
golang.org/x/crypto v0.29.0
|
||||||
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e // lastest version compatible with golang1.20
|
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e // lastest version compatible with golang1.20
|
||||||
golang.org/x/net v0.30.0
|
golang.org/x/net v0.31.0
|
||||||
golang.org/x/sys v0.26.0
|
golang.org/x/sys v0.27.0
|
||||||
google.golang.org/protobuf v1.34.2
|
google.golang.org/protobuf v1.34.2
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
lukechampine.com/blake3 v1.3.0
|
lukechampine.com/blake3 v1.3.0
|
||||||
@@ -78,7 +79,7 @@ require (
|
|||||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
||||||
github.com/gobwas/httphead v0.1.0 // indirect
|
github.com/gobwas/httphead v0.1.0 // indirect
|
||||||
github.com/gobwas/pool v0.2.1 // indirect
|
github.com/gobwas/pool v0.2.1 // indirect
|
||||||
github.com/google/btree v1.1.2 // indirect
|
github.com/google/btree v1.1.3 // indirect
|
||||||
github.com/google/go-cmp v0.6.0 // indirect
|
github.com/google/go-cmp v0.6.0 // indirect
|
||||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
|
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
|
||||||
github.com/hashicorp/yamux v0.1.1 // indirect
|
github.com/hashicorp/yamux v0.1.1 // indirect
|
||||||
@@ -87,7 +88,7 @@ require (
|
|||||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
||||||
github.com/mailru/easyjson v0.7.7 // indirect
|
github.com/mailru/easyjson v0.7.7 // indirect
|
||||||
github.com/mdlayher/socket v0.4.1 // indirect
|
github.com/mdlayher/socket v0.4.1 // indirect
|
||||||
github.com/metacubex/gvisor v0.0.0-20240320004321-933faba989ec // indirect
|
github.com/metacubex/gvisor v0.0.0-20241126021258-5b028898cc5a // indirect
|
||||||
github.com/oasisprotocol/deoxysii v0.0.0-20220228165953-2091330c22b7 // indirect
|
github.com/oasisprotocol/deoxysii v0.0.0-20220228165953-2091330c22b7 // indirect
|
||||||
github.com/onsi/ginkgo/v2 v2.9.5 // indirect
|
github.com/onsi/ginkgo/v2 v2.9.5 // indirect
|
||||||
github.com/pierrec/lz4/v4 v4.1.14 // indirect
|
github.com/pierrec/lz4/v4 v4.1.14 // indirect
|
||||||
@@ -110,10 +111,12 @@ require (
|
|||||||
gitlab.com/yawning/bsaes.git v0.0.0-20190805113838-0a714cd429ec // indirect
|
gitlab.com/yawning/bsaes.git v0.0.0-20190805113838-0a714cd429ec // indirect
|
||||||
go.uber.org/mock v0.4.0 // indirect
|
go.uber.org/mock v0.4.0 // indirect
|
||||||
golang.org/x/mod v0.20.0 // indirect
|
golang.org/x/mod v0.20.0 // indirect
|
||||||
golang.org/x/sync v0.8.0 // indirect
|
golang.org/x/sync v0.9.0 // indirect
|
||||||
golang.org/x/text v0.19.0 // indirect
|
golang.org/x/text v0.20.0 // indirect
|
||||||
golang.org/x/time v0.5.0 // indirect
|
golang.org/x/time v0.7.0 // indirect
|
||||||
golang.org/x/tools v0.24.0 // indirect
|
golang.org/x/tools v0.24.0 // indirect
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240610135401-a8a62080eff3 // indirect
|
||||||
|
google.golang.org/grpc v1.64.1 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
replace github.com/sagernet/sing => github.com/metacubex/sing v0.0.0-20241021005542-18b67490300a
|
replace github.com/sagernet/sing => github.com/metacubex/sing v0.0.0-20241121030428-33b6ebc52000
|
||||||
|
|||||||
58
go.sum
58
go.sum
@@ -27,6 +27,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
|||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/dlclark/regexp2 v1.11.4 h1:rPYF9/LECdNymJufQKmri9gV604RvvABwgOA8un7yAo=
|
github.com/dlclark/regexp2 v1.11.4 h1:rPYF9/LECdNymJufQKmri9gV604RvvABwgOA8un7yAo=
|
||||||
github.com/dlclark/regexp2 v1.11.4/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
github.com/dlclark/regexp2 v1.11.4/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||||
|
github.com/enfein/mieru/v3 v3.8.3 h1:s4K0hMFDg6LHltokR8/nBTVCq15XnnxPsvc1LrHwpoo=
|
||||||
|
github.com/enfein/mieru/v3 v3.8.3/go.mod h1:YtU00qjAEt54mCBQu4WZPCey6cBdB1BUtXjvrHLEUNQ=
|
||||||
github.com/ericlagergren/aegis v0.0.0-20230312195928-b4ce538b56f9 h1:/5RkVc9Rc81XmMyVqawCiDyrBHZbLAZgTTCqou4mwj8=
|
github.com/ericlagergren/aegis v0.0.0-20230312195928-b4ce538b56f9 h1:/5RkVc9Rc81XmMyVqawCiDyrBHZbLAZgTTCqou4mwj8=
|
||||||
github.com/ericlagergren/aegis v0.0.0-20230312195928-b4ce538b56f9/go.mod h1:hkIFzoiIPZYxdFOOLyDho59b7SrDfo+w3h+yWdlg45I=
|
github.com/ericlagergren/aegis v0.0.0-20230312195928-b4ce538b56f9/go.mod h1:hkIFzoiIPZYxdFOOLyDho59b7SrDfo+w3h+yWdlg45I=
|
||||||
github.com/ericlagergren/polyval v0.0.0-20220411101811-e25bc10ba391 h1:8j2RH289RJplhA6WfdaPqzg1MjH2K8wX5e0uhAxrw2g=
|
github.com/ericlagergren/polyval v0.0.0-20220411101811-e25bc10ba391 h1:8j2RH289RJplhA6WfdaPqzg1MjH2K8wX5e0uhAxrw2g=
|
||||||
@@ -59,9 +61,9 @@ github.com/gobwas/ws v1.4.0/go.mod h1:G3gNqMNtPppf5XUz7O4shetPpcZ1VJ7zt18dlUeakr
|
|||||||
github.com/gofrs/uuid/v5 v5.3.0 h1:m0mUMr+oVYUdxpMLgSYCZiXe7PuVPnI94+OMeVBNedk=
|
github.com/gofrs/uuid/v5 v5.3.0 h1:m0mUMr+oVYUdxpMLgSYCZiXe7PuVPnI94+OMeVBNedk=
|
||||||
github.com/gofrs/uuid/v5 v5.3.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8=
|
github.com/gofrs/uuid/v5 v5.3.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8=
|
||||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||||
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
|
github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
|
||||||
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
||||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
@@ -102,26 +104,26 @@ github.com/metacubex/chacha v0.1.0 h1:tg9RSJ18NvL38cCWNyYH1eiG6qDCyyXIaTLQthon0s
|
|||||||
github.com/metacubex/chacha v0.1.0/go.mod h1:Djn9bPZxLTXbJFSeyo0/qzEzQI+gUSSzttuzZM75GH8=
|
github.com/metacubex/chacha v0.1.0/go.mod h1:Djn9bPZxLTXbJFSeyo0/qzEzQI+gUSSzttuzZM75GH8=
|
||||||
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 h1:cjd4biTvOzK9ubNCCkQ+ldc4YSH/rILn53l/xGBFHHI=
|
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 h1:cjd4biTvOzK9ubNCCkQ+ldc4YSH/rILn53l/xGBFHHI=
|
||||||
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759/go.mod h1:UHOv2xu+RIgLwpXca7TLrXleEd4oR3sPatW6IF8wU88=
|
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759/go.mod h1:UHOv2xu+RIgLwpXca7TLrXleEd4oR3sPatW6IF8wU88=
|
||||||
github.com/metacubex/gvisor v0.0.0-20240320004321-933faba989ec h1:HxreOiFTUrJXJautEo8rnE1uKTVGY8wtZepY1Tii/Nc=
|
github.com/metacubex/gvisor v0.0.0-20241126021258-5b028898cc5a h1:cZ6oNVrsmsi3SNlnSnRio4zOgtQq+/XidwsaNgKICcg=
|
||||||
github.com/metacubex/gvisor v0.0.0-20240320004321-933faba989ec/go.mod h1:8BVmQ+3cxjqzWElafm24rb2Ae4jRI6vAXNXWqWjfrXw=
|
github.com/metacubex/gvisor v0.0.0-20241126021258-5b028898cc5a/go.mod h1:xBw/SYJPgUMPQ1tklV/brGn2nxhfr3BnvBzNlyi4Nic=
|
||||||
github.com/metacubex/quic-go v0.48.1-0.20241021013658-51ca987e0174 h1:GvigRPEU+cbnzdLWne47cxLrc28Abohl3ECtVdnrbq0=
|
github.com/metacubex/quic-go v0.48.3-0.20241126053724-b69fea3888da h1:Mq6cbHbPTLLTUfA9scrwBmOGkvl6y99E3WmtMIMqo30=
|
||||||
github.com/metacubex/quic-go v0.48.1-0.20241021013658-51ca987e0174/go.mod h1:AiZ+UPgrkO1DTnmiAX4b+kRoV1Vfc65UkYD7RbFlIZA=
|
github.com/metacubex/quic-go v0.48.3-0.20241126053724-b69fea3888da/go.mod h1:AiZ+UPgrkO1DTnmiAX4b+kRoV1Vfc65UkYD7RbFlIZA=
|
||||||
github.com/metacubex/randv2 v0.2.0 h1:uP38uBvV2SxYfLj53kuvAjbND4RUDfFJjwr4UigMiLs=
|
github.com/metacubex/randv2 v0.2.0 h1:uP38uBvV2SxYfLj53kuvAjbND4RUDfFJjwr4UigMiLs=
|
||||||
github.com/metacubex/randv2 v0.2.0/go.mod h1:kFi2SzrQ5WuneuoLLCMkABtiBu6VRrMrWFqSPyj2cxY=
|
github.com/metacubex/randv2 v0.2.0/go.mod h1:kFi2SzrQ5WuneuoLLCMkABtiBu6VRrMrWFqSPyj2cxY=
|
||||||
github.com/metacubex/sing v0.0.0-20241021005542-18b67490300a h1:JuR0/7RDxQtlZp/GOzrdqNq04HplTxavPRHrek8ouJk=
|
github.com/metacubex/sing v0.0.0-20241121030428-33b6ebc52000 h1:gUbMXcQXhXGj0vCpCVFTUyIH7TMpD1dpTcNv/MCS+ok=
|
||||||
github.com/metacubex/sing v0.0.0-20241021005542-18b67490300a/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
|
github.com/metacubex/sing v0.0.0-20241121030428-33b6ebc52000/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
|
||||||
github.com/metacubex/sing-quic v0.0.0-20240827003841-cd97758ed8b4 h1:HobpULaPK6OoxrHMmgcwLkwwIduXVmwdcznwUfH1GQM=
|
github.com/metacubex/sing-quic v0.0.0-20240827003841-cd97758ed8b4 h1:HobpULaPK6OoxrHMmgcwLkwwIduXVmwdcznwUfH1GQM=
|
||||||
github.com/metacubex/sing-quic v0.0.0-20240827003841-cd97758ed8b4/go.mod h1:g7Mxj7b7zm7YVqD975mk/hSmrb0A0G4bVvIMr2MMzn8=
|
github.com/metacubex/sing-quic v0.0.0-20240827003841-cd97758ed8b4/go.mod h1:g7Mxj7b7zm7YVqD975mk/hSmrb0A0G4bVvIMr2MMzn8=
|
||||||
github.com/metacubex/sing-shadowsocks v0.2.8 h1:wIhlaigswzjPw4hej75sEvWte3QR0+AJRafgwBHO5B4=
|
github.com/metacubex/sing-shadowsocks v0.2.8 h1:wIhlaigswzjPw4hej75sEvWte3QR0+AJRafgwBHO5B4=
|
||||||
github.com/metacubex/sing-shadowsocks v0.2.8/go.mod h1:X3x88XtJpBxG0W0/ECOJL6Ib0SJ3xdniAkU/6/RMWU0=
|
github.com/metacubex/sing-shadowsocks v0.2.8/go.mod h1:X3x88XtJpBxG0W0/ECOJL6Ib0SJ3xdniAkU/6/RMWU0=
|
||||||
github.com/metacubex/sing-shadowsocks2 v0.2.2 h1:eaf42uVx4Lr21S6MDYs0ZdTvGA0GEhDpb9no4+gdXPo=
|
github.com/metacubex/sing-shadowsocks2 v0.2.2 h1:eaf42uVx4Lr21S6MDYs0ZdTvGA0GEhDpb9no4+gdXPo=
|
||||||
github.com/metacubex/sing-shadowsocks2 v0.2.2/go.mod h1:BhOug03a/RbI7y6hp6q+6ITM1dXjnLTmeWBHSTwvv2Q=
|
github.com/metacubex/sing-shadowsocks2 v0.2.2/go.mod h1:BhOug03a/RbI7y6hp6q+6ITM1dXjnLTmeWBHSTwvv2Q=
|
||||||
github.com/metacubex/sing-tun v0.2.7-0.20241021011113-857bcd6ee47c h1:qfUZ8xBrViOCZamvcC8CyV7Ii8sAUrn7RqZxFGn56tQ=
|
github.com/metacubex/sing-tun v0.4.2 h1:fwrQp3P536Pswu6gR1FJ+8GH55e+t2+B8LHIjwRtWbc=
|
||||||
github.com/metacubex/sing-tun v0.2.7-0.20241021011113-857bcd6ee47c/go.mod h1:lCrP0AW7ieKnXG1JEeZLW+9h99QzjuOX0MfCQfz6TgE=
|
github.com/metacubex/sing-tun v0.4.2/go.mod h1:V0N4rr0dWPBEE20ESkTXdbtx2riQYcb6YtwC5w/9wl0=
|
||||||
github.com/metacubex/sing-vmess v0.1.9-0.20240719134745-1df6fb20bbf9 h1:OAXiCosqY8xKDp3pqTW3qbrCprZ1l6WkrXSFSCwyY4I=
|
github.com/metacubex/sing-vmess v0.1.9-0.20240719134745-1df6fb20bbf9 h1:OAXiCosqY8xKDp3pqTW3qbrCprZ1l6WkrXSFSCwyY4I=
|
||||||
github.com/metacubex/sing-vmess v0.1.9-0.20240719134745-1df6fb20bbf9/go.mod h1:olVkD4FChQ5gKMHG4ZzuD7+fMkJY1G8vwOKpRehjrmY=
|
github.com/metacubex/sing-vmess v0.1.9-0.20240719134745-1df6fb20bbf9/go.mod h1:olVkD4FChQ5gKMHG4ZzuD7+fMkJY1G8vwOKpRehjrmY=
|
||||||
github.com/metacubex/sing-wireguard v0.0.0-20240924052438-b0976fc59ea3 h1:xg71VmzLS6ByAzi/57phwDvjE+dLLs+ozH00k4DnOns=
|
github.com/metacubex/sing-wireguard v0.0.0-20241126021510-0827d417b589 h1:Z6bNy0HLTjx6BKIkV48sV/yia/GP8Bnyb5JQuGgSGzg=
|
||||||
github.com/metacubex/sing-wireguard v0.0.0-20240924052438-b0976fc59ea3/go.mod h1:6nitcmzPDL3MXnLdhu6Hm126Zk4S1fBbX3P7jxUxSFw=
|
github.com/metacubex/sing-wireguard v0.0.0-20241126021510-0827d417b589/go.mod h1:4NclTLIZuk+QkHVCGrP87rHi/y8YjgPytxTgApJNMhc=
|
||||||
github.com/metacubex/tfo-go v0.0.0-20241006021335-daedaf0ca7aa h1:9mcjV+RGZVC3reJBNDjjNPyS8PmFG97zq56X7WNaFO4=
|
github.com/metacubex/tfo-go v0.0.0-20241006021335-daedaf0ca7aa h1:9mcjV+RGZVC3reJBNDjjNPyS8PmFG97zq56X7WNaFO4=
|
||||||
github.com/metacubex/tfo-go v0.0.0-20241006021335-daedaf0ca7aa/go.mod h1:4tLB5c8U0CxpkFM+AJJB77jEaVDbLH5XQvy42vAGsWw=
|
github.com/metacubex/tfo-go v0.0.0-20241006021335-daedaf0ca7aa/go.mod h1:4tLB5c8U0CxpkFM+AJJB77jEaVDbLH5XQvy42vAGsWw=
|
||||||
github.com/metacubex/utls v1.6.6 h1:3D12YKHTf2Z41UPhQU2dWerNWJ5TVQD9gKoQ+H+iLC8=
|
github.com/metacubex/utls v1.6.6 h1:3D12YKHTf2Z41UPhQU2dWerNWJ5TVQD9gKoQ+H+iLC8=
|
||||||
@@ -230,8 +232,8 @@ go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBs
|
|||||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
|
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
|
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
|
||||||
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
|
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
|
||||||
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e h1:I88y4caeGeuDQxgdoFPUq097j7kNfw6uvuiNxUBfcBk=
|
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e h1:I88y4caeGeuDQxgdoFPUq097j7kNfw6uvuiNxUBfcBk=
|
||||||
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ=
|
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ=
|
||||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
@@ -240,11 +242,11 @@ golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0=
|
|||||||
golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
|
golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo=
|
||||||
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
|
golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
|
||||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -261,19 +263,23 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|||||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
|
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
|
||||||
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24=
|
golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
|
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
|
||||||
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
|
||||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
|
||||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
|
golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
|
||||||
golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
|
golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240610135401-a8a62080eff3 h1:9Xyg6I9IWQZhRVfCWjKK+l6kI0jHcPesVlMnT//aHNo=
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240610135401-a8a62080eff3/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0=
|
||||||
|
google.golang.org/grpc v1.64.1 h1:LKtvyfbX3UGVPFcGqJ9ItpVWW6oN/2XqTxfAnwRRXiA=
|
||||||
|
google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0=
|
||||||
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
|||||||
@@ -127,10 +127,10 @@ func router(isDebug bool, secret string, dohServer string, cors Cors) *chi.Mux {
|
|||||||
r.Mount("/providers/rules", ruleProviderRouter())
|
r.Mount("/providers/rules", ruleProviderRouter())
|
||||||
r.Mount("/cache", cacheRouter())
|
r.Mount("/cache", cacheRouter())
|
||||||
r.Mount("/dns", dnsRouter())
|
r.Mount("/dns", dnsRouter())
|
||||||
if !embedMode { // disallow restart and upgrade in embed mode
|
if !embedMode { // disallow restart in embed mode
|
||||||
r.Mount("/restart", restartRouter())
|
r.Mount("/restart", restartRouter())
|
||||||
r.Mount("/upgrade", upgradeRouter())
|
|
||||||
}
|
}
|
||||||
|
r.Mount("/upgrade", upgradeRouter())
|
||||||
addExternalRouters(r)
|
addExternalRouters(r)
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -14,9 +14,11 @@ import (
|
|||||||
|
|
||||||
func upgradeRouter() http.Handler {
|
func upgradeRouter() http.Handler {
|
||||||
r := chi.NewRouter()
|
r := chi.NewRouter()
|
||||||
r.Post("/", upgradeCore)
|
|
||||||
r.Post("/ui", updateUI)
|
r.Post("/ui", updateUI)
|
||||||
r.Post("/geo", updateGeoDatabases)
|
if !embedMode { // disallow upgrade core/geo in embed mode
|
||||||
|
r.Post("/", upgradeCore)
|
||||||
|
r.Post("/geo", updateGeoDatabases)
|
||||||
|
}
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -279,7 +279,11 @@ func New(options LC.Tun, tunnel C.Tunnel, additions ...inbound.Addition) (l *Lis
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultInterfaceMonitor, err = tun.NewDefaultInterfaceMonitor(networkUpdateMonitor, log.SingLogger, tun.DefaultInterfaceMonitorOptions{InterfaceFinder: interfaceFinder, OverrideAndroidVPN: true})
|
overrideAndroidVPN := true
|
||||||
|
if disable, _ := strconv.ParseBool(os.Getenv("DISABLE_OVERRIDE_ANDROID_VPN")); disable {
|
||||||
|
overrideAndroidVPN = false
|
||||||
|
}
|
||||||
|
defaultInterfaceMonitor, err = tun.NewDefaultInterfaceMonitor(networkUpdateMonitor, log.SingLogger, tun.DefaultInterfaceMonitorOptions{InterfaceFinder: interfaceFinder, OverrideAndroidVPN: overrideAndroidVPN})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = E.Cause(err, "create DefaultInterfaceMonitor")
|
err = E.Cause(err, "create DefaultInterfaceMonitor")
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/metacubex/mihomo/component/geodata"
|
"github.com/metacubex/mihomo/component/geodata"
|
||||||
"github.com/metacubex/mihomo/component/mmdb"
|
"github.com/metacubex/mihomo/component/mmdb"
|
||||||
C "github.com/metacubex/mihomo/constant"
|
C "github.com/metacubex/mihomo/constant"
|
||||||
@@ -26,17 +24,14 @@ func (a *ASN) Match(metadata *C.Metadata) (bool, string) {
|
|||||||
return false, ""
|
return false, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
result := mmdb.ASNInstance().LookupASN(ip.AsSlice())
|
asn, aso := mmdb.ASNInstance().LookupASN(ip.AsSlice())
|
||||||
asnNumber := strconv.FormatUint(uint64(result.AutonomousSystemNumber), 10)
|
|
||||||
ipASN := asnNumber + " " + result.AutonomousSystemOrganization
|
|
||||||
if a.isSourceIP {
|
if a.isSourceIP {
|
||||||
metadata.SrcIPASN = ipASN
|
metadata.SrcIPASN = asn + " " + aso
|
||||||
} else {
|
} else {
|
||||||
metadata.DstIPASN = ipASN
|
metadata.DstIPASN = asn + " " + aso
|
||||||
}
|
}
|
||||||
|
|
||||||
match := a.asn == asnNumber
|
return a.asn == asn, a.adapter
|
||||||
return match, a.adapter
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ASN) RuleType() C.RuleType {
|
func (a *ASN) RuleType() C.RuleType {
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ func (i *IPCIDR) Match(metadata *C.Metadata) (bool, string) {
|
|||||||
if i.isSourceIP {
|
if i.isSourceIP {
|
||||||
ip = metadata.SrcIP
|
ip = metadata.SrcIP
|
||||||
}
|
}
|
||||||
return ip.IsValid() && i.ipnet.Contains(ip), i.adapter
|
return ip.IsValid() && i.ipnet.Contains(ip.WithZone("")), i.adapter
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *IPCIDR) Adapter() string {
|
func (i *IPCIDR) Adapter() string {
|
||||||
|
|||||||
@@ -16,13 +16,14 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type ruleProviderSchema struct {
|
type ruleProviderSchema struct {
|
||||||
Type string `provider:"type"`
|
Type string `provider:"type"`
|
||||||
Behavior string `provider:"behavior"`
|
Behavior string `provider:"behavior"`
|
||||||
Path string `provider:"path,omitempty"`
|
Path string `provider:"path,omitempty"`
|
||||||
URL string `provider:"url,omitempty"`
|
URL string `provider:"url,omitempty"`
|
||||||
Proxy string `provider:"proxy,omitempty"`
|
Proxy string `provider:"proxy,omitempty"`
|
||||||
Format string `provider:"format,omitempty"`
|
Format string `provider:"format,omitempty"`
|
||||||
Interval int `provider:"interval,omitempty"`
|
Interval int `provider:"interval,omitempty"`
|
||||||
|
SizeLimit int64 `provider:"size-limit,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseRuleProvider(name string, mapping map[string]interface{}, parse func(tp, payload, target string, params []string, subRules map[string][]C.Rule) (parsed C.Rule, parseErr error)) (P.RuleProvider, error) {
|
func ParseRuleProvider(name string, mapping map[string]interface{}, parse func(tp, payload, target string, params []string, subRules map[string][]C.Rule) (parsed C.Rule, parseErr error)) (P.RuleProvider, error) {
|
||||||
@@ -53,7 +54,7 @@ func ParseRuleProvider(name string, mapping map[string]interface{}, parse func(t
|
|||||||
return nil, fmt.Errorf("%w: %s", errSubPath, path)
|
return nil, fmt.Errorf("%w: %s", errSubPath, path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vehicle = resource.NewHTTPVehicle(schema.URL, path, schema.Proxy, nil, resource.DefaultHttpTimeout)
|
vehicle = resource.NewHTTPVehicle(schema.URL, path, schema.Proxy, nil, resource.DefaultHttpTimeout, schema.SizeLimit)
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("unsupported vehicle type: %s", schema.Type)
|
return nil, fmt.Errorf("unsupported vehicle type: %s", schema.Type)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,24 +117,19 @@ func (tt *tcpTracker) Upstream() any {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func parseRemoteDestination(addr net.Addr, conn C.Connection) string {
|
func parseRemoteDestination(addr net.Addr, conn C.Connection) string {
|
||||||
if addr == nil && conn != nil {
|
if addr != nil {
|
||||||
return conn.RemoteDestination()
|
if addrPort, err := netip.ParseAddrPort(addr.String()); err == nil && addrPort.Addr().IsValid() {
|
||||||
}
|
return addrPort.Addr().String()
|
||||||
if addrPort, err := netip.ParseAddrPort(addr.String()); err == nil && addrPort.Addr().IsValid() {
|
|
||||||
return addrPort.Addr().String()
|
|
||||||
} else {
|
|
||||||
if conn != nil {
|
|
||||||
return conn.RemoteDestination()
|
|
||||||
} else {
|
|
||||||
return ""
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if conn != nil {
|
||||||
|
return conn.RemoteDestination()
|
||||||
|
}
|
||||||
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTCPTracker(conn C.Conn, manager *Manager, metadata *C.Metadata, rule C.Rule, uploadTotal int64, downloadTotal int64, pushToManager bool) *tcpTracker {
|
func NewTCPTracker(conn C.Conn, manager *Manager, metadata *C.Metadata, rule C.Rule, uploadTotal int64, downloadTotal int64, pushToManager bool) *tcpTracker {
|
||||||
if conn != nil {
|
metadata.RemoteDst = parseRemoteDestination(conn.RemoteAddr(), conn)
|
||||||
metadata.RemoteDst = parseRemoteDestination(conn.RemoteAddr(), conn)
|
|
||||||
}
|
|
||||||
|
|
||||||
t := &tcpTracker{
|
t := &tcpTracker{
|
||||||
Conn: conn,
|
Conn: conn,
|
||||||
|
|||||||
Reference in New Issue
Block a user