Skip to content

Commit

Permalink
Merge branch 'MetaCubeX:Alpha' into Alpha
Browse files Browse the repository at this point in the history
  • Loading branch information
xishang0128 authored Mar 11, 2024
2 parents 8c6c981 + 44d8a14 commit b2d2d3e
Show file tree
Hide file tree
Showing 47 changed files with 1,082 additions and 212 deletions.
27 changes: 13 additions & 14 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ jobs:
if: ${{ matrix.jobs.goos == 'linux' && !contains(matrix.jobs.goarch, 'mips') }}
run: |
sudo apt-get install dpkg
if [ "${{matrix.jobs.goarch}}" = "loong64" ]; then
if [ "${{matrix.jobs.abi}}" = "1" ]; then
ARCH=loongarch64
else
ARCH=${{matrix.jobs.goarch}}
Expand Down Expand Up @@ -204,18 +204,18 @@ jobs:
alien --to-rpm --scripts mihomo-${{matrix.jobs.goos}}-${{matrix.jobs.output}}-${VERSION}.deb
mv mihomo*.rpm mihomo-${{matrix.jobs.goos}}-${{matrix.jobs.output}}-${VERSION}.rpm
- name: Convert DEB to PKG
if: ${{ matrix.jobs.goos == 'linux' && !contains(matrix.jobs.goarch, 'mips') && !contains(matrix.jobs.goarch, 'loong64') }}
run: |
docker pull archlinux
docker run --rm -v ./:/mnt archlinux bash -c "
pacman -Syu pkgfile base-devel --noconfirm
curl -L https://github.com/helixarch/debtap/raw/master/debtap > /usr/bin/debtap
chmod 755 /usr/bin/debtap
debtap -u
debtap -Q /mnt/mihomo-${{matrix.jobs.goos}}-${{matrix.jobs.output}}-${VERSION}.deb
"
mv mihomo*.pkg.tar.zst mihomo-${{matrix.jobs.goos}}-${{matrix.jobs.output}}-${VERSION}.pkg.tar.zst
# - name: Convert DEB to PKG
# if: ${{ matrix.jobs.goos == 'linux' && !contains(matrix.jobs.goarch, 'mips') && !contains(matrix.jobs.goarch, 'loong64') }}
# run: |
# docker pull archlinux
# docker run --rm -v ./:/mnt archlinux bash -c "
# pacman -Syu pkgfile base-devel --noconfirm
# curl -L https://github.com/helixarch/debtap/raw/master/debtap > /usr/bin/debtap
# chmod 755 /usr/bin/debtap
# debtap -u
# debtap -Q /mnt/mihomo-${{matrix.jobs.goos}}-${{matrix.jobs.output}}-${VERSION}.deb
# "
# mv mihomo*.pkg.tar.zst mihomo-${{matrix.jobs.goos}}-${{matrix.jobs.output}}-${VERSION}.pkg.tar.zst

- name: Save version
run: |
Expand All @@ -230,7 +230,6 @@ jobs:
mihomo*.gz
mihomo*.deb
mihomo*.rpm
mihomo*.pkg.tar.zst
mihomo*.zip
version.txt
Expand Down
2 changes: 1 addition & 1 deletion adapter/inbound/listen.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"context"
"net"

"github.com/sagernet/tfo-go"
"github.com/metacubex/tfo-go"
)

var (
Expand Down
159 changes: 159 additions & 0 deletions adapter/outbound/dns.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
package outbound

import (
"context"
"net"
"time"

N "github.com/metacubex/mihomo/common/net"
"github.com/metacubex/mihomo/common/pool"
"github.com/metacubex/mihomo/component/dialer"
"github.com/metacubex/mihomo/component/resolver"
C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/log"
)

type Dns struct {
*Base
}

type DnsOption struct {
BasicOption
Name string `proxy:"name"`
}

// DialContext implements C.ProxyAdapter
func (d *Dns) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.Conn, error) {
left, right := N.Pipe()
go resolver.RelayDnsConn(context.Background(), right, 0)
return NewConn(left, d), nil
}

// ListenPacketContext implements C.ProxyAdapter
func (d *Dns) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.PacketConn, error) {
log.Debugln("[DNS] hijack udp:%s from %s", metadata.RemoteAddress(), metadata.SourceAddrPort())

ctx, cancel := context.WithCancel(context.Background())

return newPacketConn(&dnsPacketConn{
response: make(chan dnsPacket, 1),
ctx: ctx,
cancel: cancel,
}, d), nil
}

type dnsPacket struct {
data []byte
put func()
addr net.Addr
}

// dnsPacketConn implements net.PacketConn
type dnsPacketConn struct {
response chan dnsPacket
ctx context.Context
cancel context.CancelFunc
}

func (d *dnsPacketConn) WaitReadFrom() (data []byte, put func(), addr net.Addr, err error) {
select {
case packet := <-d.response:
return packet.data, packet.put, packet.addr, nil
case <-d.ctx.Done():
return nil, nil, nil, net.ErrClosed
}
}

func (d *dnsPacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
select {
case packet := <-d.response:
n = copy(p, packet.data)
if packet.put != nil {
packet.put()
}
return n, packet.addr, nil
case <-d.ctx.Done():
return 0, nil, net.ErrClosed
}
}

func (d *dnsPacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
select {
case <-d.ctx.Done():
return 0, net.ErrClosed
default:
}

if len(p) > resolver.SafeDnsPacketSize {
// wtf???
return len(p), nil
}

ctx, cancel := context.WithTimeout(d.ctx, resolver.DefaultDnsRelayTimeout)
defer cancel()

buf := pool.Get(resolver.SafeDnsPacketSize)
put := func() { _ = pool.Put(buf) }
copy(buf, p) // avoid p be changed after WriteTo returned

go func() { // don't block the WriteTo function
buf, err = resolver.RelayDnsPacket(ctx, buf[:len(p)], buf)
if err != nil {
put()
return
}

packet := dnsPacket{
data: buf,
put: put,
addr: addr,
}
select {
case d.response <- packet:
break
case <-d.ctx.Done():
put()
}
}()
return len(p), nil
}

func (d *dnsPacketConn) Close() error {
d.cancel()
return nil
}

func (*dnsPacketConn) LocalAddr() net.Addr {
return &net.UDPAddr{
IP: net.IPv4(127, 0, 0, 1),
Port: 53,
Zone: "",
}
}

func (*dnsPacketConn) SetDeadline(t time.Time) error {
return nil
}

func (*dnsPacketConn) SetReadDeadline(t time.Time) error {
return nil
}

func (*dnsPacketConn) SetWriteDeadline(t time.Time) error {
return nil
}

func NewDnsWithOption(option DnsOption) *Dns {
return &Dns{
Base: &Base{
name: option.Name,
tp: C.Dns,
udp: true,
tfo: option.TFO,
mpTcp: option.MPTCP,
iface: option.Interface,
rmark: option.RoutingMark,
prefer: C.NewDNSPrefer(option.IPVersion),
},
}
}
69 changes: 68 additions & 1 deletion adapter/outbound/hysteria2.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,30 @@ import (
"net"
"runtime"
"strconv"
"strings"
"time"

CN "github.com/metacubex/mihomo/common/net"
"github.com/metacubex/mihomo/component/ca"
"github.com/metacubex/mihomo/component/dialer"
"github.com/metacubex/mihomo/component/proxydialer"
C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/log"
tuicCommon "github.com/metacubex/mihomo/transport/tuic/common"

"github.com/metacubex/sing-quic/hysteria2"

M "github.com/sagernet/sing/common/metadata"
"github.com/zhangyunhao116/fastrand"
)

func init() {
hysteria2.SetCongestionController = tuicCommon.SetCongestionController
}

const minHopInterval = 5
const defaultHopInterval = 30

type Hysteria2 struct {
*Base

Expand All @@ -38,6 +45,8 @@ type Hysteria2Option struct {
Name string `proxy:"name"`
Server string `proxy:"server"`
Port int `proxy:"port"`
Ports string `proxy:"ports,omitempty"`
HopInterval int `proxy:"hop-interval,omitempty"`
Up string `proxy:"up,omitempty"`
Down string `proxy:"down,omitempty"`
Password string `proxy:"password,omitempty"`
Expand Down Expand Up @@ -82,6 +91,41 @@ func closeHysteria2(h *Hysteria2) {
}
}

func parsePorts(portStr string) (ports []uint16) {
portStrs := strings.Split(portStr, ",")
for _, portStr := range portStrs {
if strings.Contains(portStr, "-") {
// Port range
portRange := strings.Split(portStr, "-")
if len(portRange) != 2 {
return nil
}
start, err := strconv.ParseUint(portRange[0], 10, 16)
if err != nil {
return nil
}
end, err := strconv.ParseUint(portRange[1], 10, 16)
if err != nil {
return nil
}
if start > end {
start, end = end, start
}
for i := start; i <= end; i++ {
ports = append(ports, uint16(i))
}
} else {
// Single port
port, err := strconv.ParseUint(portStr, 10, 16)
if err != nil {
return nil
}
ports = append(ports, uint16(port))
}
}
return ports
}

func NewHysteria2(option Hysteria2Option) (*Hysteria2, error) {
addr := net.JoinHostPort(option.Server, strconv.Itoa(option.Port))
var salamanderPassword string
Expand Down Expand Up @@ -129,7 +173,7 @@ func NewHysteria2(option Hysteria2Option) (*Hysteria2, error) {
clientOptions := hysteria2.ClientOptions{
Context: context.TODO(),
Dialer: singDialer,
ServerAddress: M.ParseSocksaddrHostPort(option.Server, uint16(option.Port)),
Logger: log.SingLogger,
SendBPS: StringToBps(option.Up),
ReceiveBPS: StringToBps(option.Down),
SalamanderPassword: salamanderPassword,
Expand All @@ -138,6 +182,29 @@ func NewHysteria2(option Hysteria2Option) (*Hysteria2, error) {
UDPDisabled: false,
CWND: option.CWND,
UdpMTU: option.UdpMTU,
ServerAddress: func(ctx context.Context) (*net.UDPAddr, error) {
return resolveUDPAddrWithPrefer(ctx, "udp", addr, C.NewDNSPrefer(option.IPVersion))
},
}

if option.Ports != "" {
ports := parsePorts(option.Ports)
if len(ports) > 0 {
serverAddress := make([]string, len(ports))
for i, port := range ports {
serverAddress[i] = net.JoinHostPort(option.Server, strconv.Itoa(int(port)))
}
clientOptions.ServerAddress = func(ctx context.Context) (*net.UDPAddr, error) {
return resolveUDPAddrWithPrefer(ctx, "udp", serverAddress[fastrand.Intn(len(serverAddress))], C.NewDNSPrefer(option.IPVersion))
}

if option.HopInterval == 0 {
option.HopInterval = defaultHopInterval
} else if option.HopInterval < minHopInterval {
option.HopInterval = minHopInterval
}
clientOptions.HopInterval = time.Duration(option.HopInterval) * time.Second
}
}

client, err := hysteria2.NewClient(clientOptions)
Expand Down
Loading

0 comments on commit b2d2d3e

Please sign in to comment.