feat: support juicity (#248)

* feat: support juicity

* optimize(juicity): lower reserved streams

* fix(juicity): support to detach from client pool

* docs: add docs

* fix(trojan): udp

* fix: panic if tuic and juice are both used

---------

Co-authored-by: dae-bot[bot] <136105375+dae-bot[bot]@users.noreply.github.com>
This commit is contained in:
mzz
2023-07-29 23:41:40 +08:00
committed by GitHub
parent afae72e4b9
commit e4a95aade0
8 changed files with 144 additions and 5 deletions

View File

@ -0,0 +1,133 @@
package juicity
import (
"crypto/tls"
"fmt"
"net"
"net/url"
"strconv"
"github.com/daeuniverse/dae/common"
"github.com/daeuniverse/dae/component/outbound/dialer"
"github.com/mzz2017/softwind/netproxy"
"github.com/mzz2017/softwind/protocol"
)
func init() {
dialer.FromLinkRegister("juicity", NewJuice)
}
type Juice struct {
Name string
Server string
Port int
User string
Password string
Sni string
AllowInsecure bool
CongestionControl string
Protocol string
}
func NewJuice(option *dialer.GlobalOption, nextDialer netproxy.Dialer, link string) (netproxy.Dialer, *dialer.Property, error) {
s, err := ParseJuiceURL(link)
if err != nil {
return nil, nil, err
}
return s.Dialer(option, nextDialer)
}
func (s *Juice) Dialer(option *dialer.GlobalOption, nextDialer netproxy.Dialer) (netproxy.Dialer, *dialer.Property, error) {
d := nextDialer
var err error
var flags protocol.Flags
if d, err = protocol.NewDialer("juicity", d, protocol.Header{
ProxyAddress: net.JoinHostPort(s.Server, strconv.Itoa(s.Port)),
Feature1: s.CongestionControl,
TlsConfig: &tls.Config{
NextProtos: []string{"h3"},
MinVersion: tls.VersionTLS13,
ServerName: s.Sni,
InsecureSkipVerify: s.AllowInsecure || option.AllowInsecure,
},
User: s.User,
Password: s.Password,
IsClient: true,
Flags: flags,
}); err != nil {
return nil, nil, err
}
return d, &dialer.Property{
Name: s.Name,
Address: net.JoinHostPort(s.Server, strconv.Itoa(s.Port)),
Protocol: s.Protocol,
Link: s.ExportToURL(),
}, nil
}
func ParseJuiceURL(u string) (data *Juice, err error) {
//trojan://password@server:port#escape(remarks)
t, err := url.Parse(u)
if err != nil {
err = fmt.Errorf("invalid trojan format")
return
}
allowInsecure, _ := strconv.ParseBool(t.Query().Get("allowInsecure"))
if !allowInsecure {
allowInsecure, _ = strconv.ParseBool(t.Query().Get("allow_insecure"))
}
if !allowInsecure {
allowInsecure, _ = strconv.ParseBool(t.Query().Get("allowinsecure"))
}
if !allowInsecure {
allowInsecure, _ = strconv.ParseBool(t.Query().Get("skipVerify"))
}
sni := t.Query().Get("peer")
if sni == "" {
sni = t.Query().Get("sni")
}
if sni == "" {
sni = t.Hostname()
}
disableSni, _ := strconv.ParseBool(t.Query().Get("disable_sni"))
if disableSni {
sni = ""
allowInsecure = true
}
port, err := strconv.Atoi(t.Port())
if err != nil {
return nil, dialer.InvalidParameterErr
}
password, _ := t.User.Password()
data = &Juice{
Name: t.Fragment,
Server: t.Hostname(),
Port: port,
User: t.User.Username(),
Password: password,
Sni: sni,
AllowInsecure: allowInsecure,
CongestionControl: t.Query().Get("congestion_control"),
Protocol: "juicity",
}
return data, nil
}
func (t *Juice) ExportToURL() string {
u := &url.URL{
Scheme: "juicity",
User: url.UserPassword(t.User, t.Password),
Host: net.JoinHostPort(t.Server, strconv.Itoa(t.Port)),
Fragment: t.Name,
}
q := u.Query()
if t.AllowInsecure {
q.Set("allow_insecure", "1")
}
common.SetValue(&q, "sni", t.Sni)
if t.CongestionControl != "" {
common.SetValue(&q, "congestion_control", t.CongestionControl)
}
u.RawQuery = q.Encode()
return u.String()
}

View File

@ -132,7 +132,7 @@ func ParseTuicURL(u string) (data *Tuic, err error) {
func (t *Tuic) ExportToURL() string { func (t *Tuic) ExportToURL() string {
u := &url.URL{ u := &url.URL{
Scheme: "trojan", Scheme: "tuic",
User: url.UserPassword(t.User, t.Password), User: url.UserPassword(t.User, t.Password),
Host: net.JoinHostPort(t.Server, strconv.Itoa(t.Port)), Host: net.JoinHostPort(t.Server, strconv.Itoa(t.Port)),
Fragment: t.Name, Fragment: t.Name,

View File

@ -7,6 +7,7 @@ package outbound
import ( import (
_ "github.com/daeuniverse/dae/component/outbound/dialer/http" _ "github.com/daeuniverse/dae/component/outbound/dialer/http"
_ "github.com/daeuniverse/dae/component/outbound/dialer/juicity"
_ "github.com/daeuniverse/dae/component/outbound/dialer/shadowsocks" _ "github.com/daeuniverse/dae/component/outbound/dialer/shadowsocks"
_ "github.com/daeuniverse/dae/component/outbound/dialer/shadowsocksr" _ "github.com/daeuniverse/dae/component/outbound/dialer/shadowsocksr"
_ "github.com/daeuniverse/dae/component/outbound/dialer/socks" _ "github.com/daeuniverse/dae/component/outbound/dialer/socks"
@ -16,6 +17,7 @@ import (
_ "github.com/daeuniverse/dae/component/outbound/transport/simpleobfs" _ "github.com/daeuniverse/dae/component/outbound/transport/simpleobfs"
_ "github.com/daeuniverse/dae/component/outbound/transport/tls" _ "github.com/daeuniverse/dae/component/outbound/transport/tls"
_ "github.com/daeuniverse/dae/component/outbound/transport/ws" _ "github.com/daeuniverse/dae/component/outbound/transport/ws"
_ "github.com/mzz2017/softwind/protocol/juicity"
_ "github.com/mzz2017/softwind/protocol/shadowsocks" _ "github.com/mzz2017/softwind/protocol/shadowsocks"
_ "github.com/mzz2017/softwind/protocol/trojanc" _ "github.com/mzz2017/softwind/protocol/trojanc"
_ "github.com/mzz2017/softwind/protocol/tuic" _ "github.com/mzz2017/softwind/protocol/tuic"

View File

@ -23,6 +23,7 @@
- [x] Trojan-gfw - [x] Trojan-gfw
- [x] Trojan-go - [x] Trojan-go
- [x] [Tuic (v5)](https://github.com/daeuniverse/dae/discussions/182) - [x] [Tuic (v5)](https://github.com/daeuniverse/dae/discussions/182)
- [x] [Juicity](https://github.com/juicity/juicity)
- [x] [Proxy chain (flexible protocol)](https://github.com/daeuniverse/dae/discussions/236) - [x] [Proxy chain (flexible protocol)](https://github.com/daeuniverse/dae/discussions/236)
For other requirements, one way to expand protocol support is by using external proxy programs. Below is an example of using the external naiveproxy. For other requirements, one way to expand protocol support is by using external proxy programs. Below is an example of using the external naiveproxy.

View File

@ -22,6 +22,9 @@
- [x] Trojan-gfw - [x] Trojan-gfw
- [x] Trojan-go - [x] Trojan-go
- [x] Tuic (v5) - [x] Tuic (v5)
- [x] [Tuic (v5)](https://github.com/daeuniverse/dae/discussions/182)
- [x] [Juicity](https://github.com/juicity/juicity)
- [x] [Proxy chain (flexible protocol)](https://github.com/daeuniverse/dae/discussions/236)
有其他需求的,一种方式是通过外接其他代理程序来扩展协议支持。下面给出外接 naiveproxy 的例子。 有其他需求的,一种方式是通过外接其他代理程序来扩展协议支持。下面给出外接 naiveproxy 的例子。

View File

@ -107,7 +107,7 @@ subscription {
# Nodes defined here will be merged as a part of the global node pool. # Nodes defined here will be merged as a part of the global node pool.
node { node {
# Add your node links here. # Add your node links here.
# Support socks5, http, https, ss, ssr, vmess, vless, trojan, tuic, etc. # Support socks5, http, https, ss, ssr, vmess, vless, trojan, tuic, juicity, etc.
# Full support list: https://github.com/daeuniverse/dae/blob/main/docs/en/proxy-protocols.md # Full support list: https://github.com/daeuniverse/dae/blob/main/docs/en/proxy-protocols.md
'socks5://localhost:1080' 'socks5://localhost:1080'
mylink: 'ss://LINK' mylink: 'ss://LINK'

2
go.mod
View File

@ -12,7 +12,7 @@ require (
github.com/json-iterator/go v1.1.12 github.com/json-iterator/go v1.1.12
github.com/miekg/dns v1.1.55 github.com/miekg/dns v1.1.55
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826
github.com/mzz2017/softwind v0.0.0-20230723115304-666ec11098b8 github.com/mzz2017/softwind v0.0.0-20230729115435-7bfb07d4e1f6
github.com/okzk/sdnotify v0.0.0-20180710141335-d9becc38acbd github.com/okzk/sdnotify v0.0.0-20180710141335-d9becc38acbd
github.com/safchain/ethtool v0.3.0 github.com/safchain/ethtool v0.3.0
github.com/sirupsen/logrus v1.9.3 github.com/sirupsen/logrus v1.9.3

4
go.sum
View File

@ -91,8 +91,8 @@ github.com/mzz2017/disk-bloom v1.0.1 h1:rEF9MiXd9qMW3ibRpqcerLXULoTgRlM21yqqJl1B
github.com/mzz2017/disk-bloom v1.0.1/go.mod h1:JLHETtUu44Z6iBmsqzkOtFlRvXSlKnxjwiBRDapizDI= github.com/mzz2017/disk-bloom v1.0.1/go.mod h1:JLHETtUu44Z6iBmsqzkOtFlRvXSlKnxjwiBRDapizDI=
github.com/mzz2017/quic-go v0.0.0-20230706143320-cc858d4932b7 h1:9zmZilN02x3byMB2X3x+B4iyKHkucv70WA4hsyZkjo8= github.com/mzz2017/quic-go v0.0.0-20230706143320-cc858d4932b7 h1:9zmZilN02x3byMB2X3x+B4iyKHkucv70WA4hsyZkjo8=
github.com/mzz2017/quic-go v0.0.0-20230706143320-cc858d4932b7/go.mod h1:3H6d55CEofIWWr3gQThiB27+hA3WG5tATtPovzEYPAA= github.com/mzz2017/quic-go v0.0.0-20230706143320-cc858d4932b7/go.mod h1:3H6d55CEofIWWr3gQThiB27+hA3WG5tATtPovzEYPAA=
github.com/mzz2017/softwind v0.0.0-20230723115304-666ec11098b8 h1:T/VA4g5qkPeZFvZ+gkx4SK9wijDSOgFwumEZAxdHZ8U= github.com/mzz2017/softwind v0.0.0-20230729115435-7bfb07d4e1f6 h1:9xuiuwjy5nMtWBUmcGDnGhEzobUnLEG+0T2A4RRnCPE=
github.com/mzz2017/softwind v0.0.0-20230723115304-666ec11098b8/go.mod h1:Fz8fgR7/dbnfR6RLpeOMkUDyebq4xShdmjj+cE5jnJ4= github.com/mzz2017/softwind v0.0.0-20230729115435-7bfb07d4e1f6/go.mod h1:Fz8fgR7/dbnfR6RLpeOMkUDyebq4xShdmjj+cE5jnJ4=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=