Skip to content

Commit 0ac6c3b

Browse files
committed
feat: inbound support vless
1 parent b69e52d commit 0ac6c3b

File tree

12 files changed

+608
-6
lines changed

12 files changed

+608
-6
lines changed

adapter/outbound/vless.go

-3
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import (
2121
"github.com/metacubex/mihomo/component/resolver"
2222
tlsC "github.com/metacubex/mihomo/component/tls"
2323
C "github.com/metacubex/mihomo/constant"
24-
"github.com/metacubex/mihomo/log"
2524
"github.com/metacubex/mihomo/transport/gun"
2625
"github.com/metacubex/mihomo/transport/socks5"
2726
"github.com/metacubex/mihomo/transport/vless"
@@ -513,8 +512,6 @@ func NewVless(option VlessOption) (*Vless, error) {
513512
if option.Flow != vless.XRV {
514513
return nil, fmt.Errorf("unsupported xtls flow type: %s", option.Flow)
515514
}
516-
517-
log.Warnln("To use %s, ensure your server is upgrade to Xray-core v1.8.0+", vless.XRV)
518515
addons = &vless.Addons{
519516
Flow: option.Flow,
520517
}

component/generater/cmd.go

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package generater
2+
3+
import (
4+
"encoding/base64"
5+
"fmt"
6+
7+
"github.com/gofrs/uuid/v5"
8+
)
9+
10+
func Main(args []string) {
11+
if len(args) < 1 {
12+
panic("Using: generate uuid/reality-keypair/wg-keypair")
13+
}
14+
switch args[0] {
15+
case "uuid":
16+
newUUID, err := uuid.NewV4()
17+
if err != nil {
18+
panic(err)
19+
}
20+
fmt.Println(newUUID.String())
21+
case "reality-keypair":
22+
privateKey, err := GeneratePrivateKey()
23+
if err != nil {
24+
panic(err)
25+
}
26+
publicKey := privateKey.PublicKey()
27+
fmt.Println("PrivateKey: " + base64.RawURLEncoding.EncodeToString(privateKey[:]))
28+
fmt.Println("PublicKey: " + base64.RawURLEncoding.EncodeToString(publicKey[:]))
29+
case "wg-keypair":
30+
privateKey, err := GeneratePrivateKey()
31+
if err != nil {
32+
panic(err)
33+
}
34+
fmt.Println("PrivateKey: " + privateKey.String())
35+
fmt.Println("PublicKey: " + privateKey.PublicKey().String())
36+
}
37+
}

component/generater/types.go

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
// Copy from https://github.com/WireGuard/wgctrl-go/blob/a9ab2273dd1075ea74b88c76f8757f8b4003fcbf/wgtypes/types.go#L71-L155
2+
3+
package generater
4+
5+
import (
6+
"crypto/rand"
7+
"encoding/base64"
8+
"fmt"
9+
10+
"golang.org/x/crypto/curve25519"
11+
)
12+
13+
// KeyLen is the expected key length for a WireGuard key.
14+
const KeyLen = 32 // wgh.KeyLen
15+
16+
// A Key is a public, private, or pre-shared secret key. The Key constructor
17+
// functions in this package can be used to create Keys suitable for each of
18+
// these applications.
19+
type Key [KeyLen]byte
20+
21+
// GenerateKey generates a Key suitable for use as a pre-shared secret key from
22+
// a cryptographically safe source.
23+
//
24+
// The output Key should not be used as a private key; use GeneratePrivateKey
25+
// instead.
26+
func GenerateKey() (Key, error) {
27+
b := make([]byte, KeyLen)
28+
if _, err := rand.Read(b); err != nil {
29+
return Key{}, fmt.Errorf("wgtypes: failed to read random bytes: %v", err)
30+
}
31+
32+
return NewKey(b)
33+
}
34+
35+
// GeneratePrivateKey generates a Key suitable for use as a private key from a
36+
// cryptographically safe source.
37+
func GeneratePrivateKey() (Key, error) {
38+
key, err := GenerateKey()
39+
if err != nil {
40+
return Key{}, err
41+
}
42+
43+
// Modify random bytes using algorithm described at:
44+
// https://cr.yp.to/ecdh.html.
45+
key[0] &= 248
46+
key[31] &= 127
47+
key[31] |= 64
48+
49+
return key, nil
50+
}
51+
52+
// NewKey creates a Key from an existing byte slice. The byte slice must be
53+
// exactly 32 bytes in length.
54+
func NewKey(b []byte) (Key, error) {
55+
if len(b) != KeyLen {
56+
return Key{}, fmt.Errorf("wgtypes: incorrect key size: %d", len(b))
57+
}
58+
59+
var k Key
60+
copy(k[:], b)
61+
62+
return k, nil
63+
}
64+
65+
// ParseKey parses a Key from a base64-encoded string, as produced by the
66+
// Key.String method.
67+
func ParseKey(s string) (Key, error) {
68+
b, err := base64.StdEncoding.DecodeString(s)
69+
if err != nil {
70+
return Key{}, fmt.Errorf("wgtypes: failed to parse base64-encoded key: %v", err)
71+
}
72+
73+
return NewKey(b)
74+
}
75+
76+
// PublicKey computes a public key from the private key k.
77+
//
78+
// PublicKey should only be called when k is a private key.
79+
func (k Key) PublicKey() Key {
80+
var (
81+
pub [KeyLen]byte
82+
priv = [KeyLen]byte(k)
83+
)
84+
85+
// ScalarBaseMult uses the correct base value per https://cr.yp.to/ecdh.html,
86+
// so no need to specify it.
87+
curve25519.ScalarBaseMult(&pub, &priv)
88+
89+
return Key(pub)
90+
}
91+
92+
// String returns the base64-encoded string representation of a Key.
93+
//
94+
// ParseKey can be used to produce a new Key from this string.
95+
func (k Key) String() string {
96+
return base64.StdEncoding.EncodeToString(k[:])
97+
}

constant/metadata.go

+5
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const (
2525
SOCKS5
2626
SHADOWSOCKS
2727
VMESS
28+
VLESS
2829
REDIR
2930
TPROXY
3031
TUNNEL
@@ -69,6 +70,8 @@ func (t Type) String() string {
6970
return "ShadowSocks"
7071
case VMESS:
7172
return "Vmess"
73+
case VLESS:
74+
return "Vless"
7275
case REDIR:
7376
return "Redir"
7477
case TPROXY:
@@ -103,6 +106,8 @@ func ParseType(t string) (*Type, error) {
103106
res = SHADOWSOCKS
104107
case "VMESS":
105108
res = VMESS
109+
case "VLESS":
110+
res = VLESS
106111
case "REDIR":
107112
res = REDIR
108113
case "TPROXY":

docs/config.yaml

+24
Original file line numberDiff line numberDiff line change
@@ -1176,6 +1176,30 @@ listeners:
11761176
network: [tcp, udp]
11771177
target: target.com
11781178

1179+
- name: vless-in-1
1180+
type: vless
1181+
port: 10817
1182+
listen: 0.0.0.0
1183+
# rule: sub-rule-name1 # 默认使用 rules,如果未找到 sub-rule 则直接使用 rules
1184+
# proxy: proxy # 如果不为空则直接将该入站流量交由指定 proxy 处理 (当 proxy 不为空时,这里的 proxy 名称必须合法,否则会出错)
1185+
users:
1186+
- username: 1
1187+
uuid: 9d0cb9d0-964f-4ef6-897d-6c6b3ccf9e68
1188+
flow: xtls-rprx-vision
1189+
# ws-path: "/" # 如果不为空则开启 websocket 传输层
1190+
# 下面两项如果填写则开启 tls(需要同时填写)
1191+
# certificate: ./server.crt
1192+
# private-key: ./server.key
1193+
# 如果填写reality-config则开启reality(注意不可与certificate和private-key同时填写)
1194+
reality-config:
1195+
dest: test.com:443
1196+
private-key: jNXHt1yRo0vDuchQlIP6Z0ZvjT3KtzVI-T4E7RoLJS0 # 可由 mihomo generate reality-keypair 命令生成
1197+
short-id:
1198+
- 0123456789abcdef
1199+
server-names:
1200+
- test.com
1201+
### 注意,对于vless listener, 至少需要填写 “certificate和private-key” 或 “reality-config” 的其中一项 ###
1202+
11791203
- name: tun-in-1
11801204
type: tun
11811205
# rule: sub-rule-name1 # 默认使用 rules,如果未找到 sub-rule 则直接使用 rules

go.mod

+2-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ require (
2727
github.com/metacubex/sing-shadowsocks v0.2.8
2828
github.com/metacubex/sing-shadowsocks2 v0.2.2
2929
github.com/metacubex/sing-tun v0.4.5
30-
github.com/metacubex/sing-vmess v0.1.9-0.20240719134745-1df6fb20bbf9
30+
github.com/metacubex/sing-vmess v0.1.14-0.20250203033000-f61322b3dbe3
3131
github.com/metacubex/sing-wireguard v0.0.0-20241126021510-0827d417b589
3232
github.com/metacubex/tfo-go v0.0.0-20241231083714-66613d49c422
3333
github.com/metacubex/utls v1.6.6
@@ -40,6 +40,7 @@ require (
4040
github.com/sagernet/cors v1.2.1
4141
github.com/sagernet/fswatch v0.1.1
4242
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a
43+
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691
4344
github.com/sagernet/sing v0.5.1
4445
github.com/sagernet/sing-mux v0.2.1
4546
github.com/sagernet/sing-shadowtls v0.1.5

go.sum

+4-2
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,8 @@ github.com/metacubex/sing-shadowsocks2 v0.2.2 h1:eaf42uVx4Lr21S6MDYs0ZdTvGA0GEhD
122122
github.com/metacubex/sing-shadowsocks2 v0.2.2/go.mod h1:BhOug03a/RbI7y6hp6q+6ITM1dXjnLTmeWBHSTwvv2Q=
123123
github.com/metacubex/sing-tun v0.4.5 h1:kWSyQzuzHI40r50OFBczfWIDvMBMy1RIk+JsXeBPRB0=
124124
github.com/metacubex/sing-tun v0.4.5/go.mod h1:V0N4rr0dWPBEE20ESkTXdbtx2riQYcb6YtwC5w/9wl0=
125-
github.com/metacubex/sing-vmess v0.1.9-0.20240719134745-1df6fb20bbf9 h1:OAXiCosqY8xKDp3pqTW3qbrCprZ1l6WkrXSFSCwyY4I=
126-
github.com/metacubex/sing-vmess v0.1.9-0.20240719134745-1df6fb20bbf9/go.mod h1:olVkD4FChQ5gKMHG4ZzuD7+fMkJY1G8vwOKpRehjrmY=
125+
github.com/metacubex/sing-vmess v0.1.14-0.20250203033000-f61322b3dbe3 h1:2kq6azIvsTjTnyw66xXDl5zMzIJqF7GTbvLpkroHssg=
126+
github.com/metacubex/sing-vmess v0.1.14-0.20250203033000-f61322b3dbe3/go.mod h1:nE7Mdzj/QUDwgRi/8BASPtsxtIFZTHA4Yst5GgwbGCQ=
127127
github.com/metacubex/sing-wireguard v0.0.0-20241126021510-0827d417b589 h1:Z6bNy0HLTjx6BKIkV48sV/yia/GP8Bnyb5JQuGgSGzg=
128128
github.com/metacubex/sing-wireguard v0.0.0-20241126021510-0827d417b589/go.mod h1:4NclTLIZuk+QkHVCGrP87rHi/y8YjgPytxTgApJNMhc=
129129
github.com/metacubex/tfo-go v0.0.0-20241231083714-66613d49c422 h1:zGeQt3UyNydIVrMRB97AA5WsYEau/TyCnRtTf1yUmJY=
@@ -170,6 +170,8 @@ github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a h1:ObwtHN2VpqE0ZN
170170
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
171171
github.com/sagernet/nftables v0.3.0-beta.4 h1:kbULlAwAC3jvdGAC1P5Fa3GSxVwQJibNenDW2zaXr8I=
172172
github.com/sagernet/nftables v0.3.0-beta.4/go.mod h1:OQXAjvjNGGFxaTgVCSTRIhYB5/llyVDeapVoENYBDS8=
173+
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byLGkEnIYp6grlXfo1QYUfiYFGjewIdc=
174+
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU=
173175
github.com/sagernet/sing-mux v0.2.1 h1:N/3MHymfnFZRd29tE3TaXwPUVVgKvxhtOkiCMLp9HVo=
174176
github.com/sagernet/sing-mux v0.2.1/go.mod h1:dm3BWL6NvES9pbib7llpylrq7Gq+LjlzG+0RacdxcyE=
175177
github.com/sagernet/sing-shadowtls v0.1.5 h1:uXxmq/HXh8DIiBGLzpMjCbWnzIAFs+lIxiTOjdgG5qo=

listener/config/vless.go

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package config
2+
3+
import (
4+
"github.com/metacubex/mihomo/listener/sing"
5+
6+
"encoding/json"
7+
)
8+
9+
type VlessUser struct {
10+
Username string
11+
UUID string
12+
Flow string
13+
}
14+
15+
type VlessServer struct {
16+
Enable bool
17+
Listen string
18+
Users []VlessUser
19+
WsPath string
20+
Certificate string
21+
PrivateKey string
22+
RealityConfig RealityConfig
23+
MuxOption sing.MuxOption `yaml:"mux-option" json:"mux-option,omitempty"`
24+
}
25+
26+
func (t VlessServer) String() string {
27+
b, _ := json.Marshal(t)
28+
return string(b)
29+
}
30+
31+
type RealityConfig struct {
32+
Dest string
33+
PrivateKey string
34+
ShortID []string
35+
ServerNames []string
36+
MaxTimeDifference int
37+
Proxy string
38+
}

0 commit comments

Comments
 (0)