diff --git a/util/genLink.go b/util/genLink.go index 3cb4489..2048273 100644 --- a/util/genLink.go +++ b/util/genLink.go @@ -10,7 +10,7 @@ import ( "strings" ) -var InboundTypeWithLink = []string{"shadowsocks", "naive", "hysteria", "hysteria2", "tuic", "vless", "trojan", "vmess"} +var InboundTypeWithLink = []string{"shadowsocks", "naive", "hysteria", "hysteria2", "anytls", "tuic", "vless", "trojan", "vmess"} func LinkGenerator(clientConfig json.RawMessage, i *model.Inbound, hostname string) []string { inbound, err := i.MarshalFull() @@ -73,6 +73,8 @@ func LinkGenerator(clientConfig json.RawMessage, i *model.Inbound, hostname stri return tuicLink(userConfig["tuic"], *inbound, Addrs) case "vless": return vlessLink(userConfig["vless"], *inbound, Addrs) + case "anytls": + return anytlsLink(userConfig["anytls"], Addrs) case "trojan": return trojanLink(userConfig["trojan"], *inbound, Addrs) case "vmess": @@ -280,6 +282,40 @@ func hysteria2Link( return links } +func anytlsLink( + userConfig map[string]interface{}, + addrs []map[string]interface{}) []string { + + password, _ := userConfig["password"].(string) + baseUri := fmt.Sprintf("%s%s@", "anytls://", password) + var links []string + + for _, addr := range addrs { + params := map[string]string{} + if tls, ok := addr["tls"].(map[string]interface{}); ok { + if sni, ok := tls["server_name"].(string); ok { + params["sni"] = sni + } + if alpn, ok := tls["alpn"].([]interface{}); ok { + alpnList := make([]string, len(alpn)) + for i, v := range alpn { + alpnList[i] = v.(string) + } + params["alpn"] = strings.Join(alpnList, ",") + } + if insecure, ok := tls["insecure"].(bool); ok && insecure { + params["insecure"] = "1" + } + } + + port, _ := addr["server_port"].(float64) + uri := fmt.Sprintf("%s%s:%d", baseUri, addr["server"].(string), uint(port)) + links = append(links, addParams(uri, params, addr["remark"].(string))) + } + + return links +} + func tuicLink( userConfig map[string]interface{}, inbound map[string]interface{}, diff --git a/util/linkToJson.go b/util/linkToJson.go index 549d8e2..bbe22d6 100644 --- a/util/linkToJson.go +++ b/util/linkToJson.go @@ -24,6 +24,8 @@ func GetOutbound(uri string, i int) (*map[string]interface{}, string, error) { return hy(u, i) case "hy2", "hysteria2": return hy2(u, i) + case "anytls": + return anytls(u, i) case "tuic": return tuic(u, i) case "ss", "shadowsocks": @@ -293,6 +295,42 @@ func hy2(u *url.URL, i int) (*map[string]interface{}, string, error) { return &hy2, tag, nil } +func anytls(u *url.URL, i int) (*map[string]interface{}, string, error) { + query, _ := url.ParseQuery(u.RawQuery) + host, portStr, _ := net.SplitHostPort(u.Host) + port := 443 + if len(portStr) > 0 { + port, _ = strconv.Atoi(portStr) + } + + tls := map[string]interface{}{ + "enabled": true, + "server_name": query.Get("sni"), + } + alpn := query.Get("alpn") + insecure := query.Get("insecure") + if len(alpn) > 0 { + tls["alpn"] = strings.Split(alpn, ",") + } + if insecure == "1" || insecure == "true" { + tls["insecure"] = true + } + + tag := u.Fragment + if i > 0 { + tag = fmt.Sprintf("%d.%s", i, u.Fragment) + } + anytls := map[string]interface{}{ + "type": "anytls", + "tag": tag, + "server": host, + "server_port": port, + "password": u.User.Username(), + "tls": tls, + } + return &anytls, tag, nil +} + func tuic(u *url.URL, i int) (*map[string]interface{}, string, error) { query, _ := url.ParseQuery(u.RawQuery) host, portStr, _ := net.SplitHostPort(u.Host)