Compare commits

...

13 Commits

Author SHA1 Message Date
zu1k
8cb970c010 update html 2020-08-14 11:19:59 +08:00
zu1k
bc8002e656 add return 2020-08-14 11:08:06 +08:00
zu1k
ce1e4938d2 try to fix obfs-host none 2020-08-14 11:07:30 +08:00
zu1k
d9790fb7c6 fix ws-path 2020-08-14 11:02:26 +08:00
zu1k
01341f2894 ws-path not none 2020-08-14 10:58:32 +08:00
zu1k
36f7fb11b0 fix ss cipher auto 2020-08-14 10:51:58 +08:00
zu1k
a1b46e9fa4 fix vmess wsheader none 2020-08-14 10:46:38 +08:00
zu1k
3c68aafd18 update readme’ 2020-08-14 10:40:09 +08:00
zu1k
5ec8cfcc43 vmess ws-header ignore none 2020-08-14 10:34:43 +08:00
zu1k
272a1c1277 ignore parse ss 2020-08-14 10:32:55 +08:00
zu1k
23bdc67444 checkSurgesupport 2020-08-14 10:30:10 +08:00
zu1k
8f5d76a471 mod assets 2020-08-14 10:27:40 +08:00
zu1k
5222a11d20 try surge list 2020-08-14 10:24:15 +08:00
17 changed files with 346 additions and 15 deletions

View File

@@ -2,7 +2,7 @@
<br>proxypool<br>
</h1>
<h5 align="center">自动抓取tg频道、订阅地址、公开互联网上的ss、ssr、vmess节点信息聚合去重后提供clash配置</h5>
<h5 align="center">自动抓取tg频道、订阅地址、公开互联网上的ss、ssr、vmess节点信息聚合去重后提供节点列表</h5>
<p align="center">
<a href="https://github.com/zu1k/proxypool/actions">
@@ -67,7 +67,7 @@ proxypool -c source.yaml
### 用户使用
目前公开版本: https://proxy.tgbot.co/clash
目前公开版本: https://proxy.tgbot.co
直接在clash添加配置文件即可使用 https://proxy.tgbot.co/clash/config

View File

@@ -13,8 +13,11 @@ var router *gin.Engine
func setupRouter() {
router = gin.Default()
router.StaticFile("/clash", "example/clash.html")
router.StaticFile("/clash/config", "example/clash-config.yaml")
router.StaticFile("/", "assets/index.html")
router.StaticFile("/clash", "assets/clash.html")
router.StaticFile("/surge", "assets/surge.html")
router.StaticFile("/clash/config", "assets/clash-config.yaml")
router.StaticFile("/surge/config", "assets/surge.conf")
router.GET("/clash/proxies", func(c *gin.Context) {
text := cache.GetString("clashproxies")
if text == "" {
@@ -25,6 +28,16 @@ func setupRouter() {
}
c.String(200, text)
})
router.GET("/surge/proxies", func(c *gin.Context) {
text := cache.GetString("surgeproxies")
if text == "" {
proxies := cache.GetProxies()
surge := provider.Surge{Proxies: proxies}
text = surge.Provide()
cache.SetString("surgeproxies", text)
}
c.String(200, text)
})
}
func Run() {

View File

@@ -37,6 +37,7 @@ func Crawl() {
log.Println("Crawl node count:", num)
cache.SetProxies(proxies)
cache.SetString("clashproxies", provider.Clash{Proxies: proxies}.Provide())
cache.SetString("surgeproxies", provider.Surge{Proxies: proxies}.Provide())
}
func CrawlGo() {
@@ -68,6 +69,7 @@ func CrawlGo() {
log.Println("CrawlGo node count:", num)
cache.SetProxies(proxies)
cache.SetString("clashproxies", provider.Clash{Proxies: proxies}.Provide())
cache.SetString("surgeproxies", provider.Surge{Proxies: proxies}.Provide())
}
func FetchNewConfigFileThenInit() {

89
assets/index.html Normal file
View File

@@ -0,0 +1,89 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="HandheldFriendly" content="True">
<title>免费节点</title>
<style type='text/css'>
body {
background-color: white;
color: #333333;
font-family: Arial, sans-serif;
margin: 0;
padding: 36px;
line-height: 1;
font-size: 14px; }
.section {
margin-bottom: 36px; }
.section.friendly {
color: #222222; }
.section.friendly h1 {
font-size: 26px;
background-color: #dad8e4;
padding: 18px 22px 15px 22px;
margin: 0;
overflow: hidden; }
.section.friendly h1 strong {
display: inline-block;
float: left; }
.section.friendly h1 small {
display: inline-block;
float: right;
text-align: right;
font-size: 18px;
padding-top: 4px;
color: #333333; }
.section.friendly .article {
border: 4px solid #dad8e4;
padding: 24px 18px 18px 18px; }
.section.friendly .article h3 {
font-size: 20px;
margin: 0 0 18px 0; }
.section.friendly .article a {
color: #6b6ceb; }
.section.friendly .article a:visited {
color: #1d1d3b; }
.section.friendly .article p {
font-size: 14px; }
.section.friendly .article ul {
list-style-type: square; }
.section.original {
background-color: #eeeeee;
color: #444444; }
.section.original h2 {
background-color: #dddddd;
margin: 0;
padding: 18px 22px 18px 22px;
font-size: 20px; }
.section.original pre {
margin: 0;
padding: 18px 22px 18px 22px;
overflow: auto;
font-family: monaco, monospaced; }
.section.original pre code {
display: block;
font-size: 11px;
width: 100%; }
</style>
</head>
<body>
<div class='container'>
<div class='section friendly'>
<h1><strong>免费节点</strong></h1>
<div class='article'>
<p>自动抓取tg频道、订阅地址、公开互联网上的ss、ssr、vmess节点信息聚合去重后提供节点列表每10分钟更新</p>
<br>
<p>Clash配置文件<a href="https://proxy.tgbot.co/clash/config">https://proxy.tgbot.co/clash/config</a> <a href="clash://install-config?url=https://proxy.tgbot.co/clash/config">一键导入</a></p>
<p>Clash proxy-provider<a href="https://proxy.tgbot.co/clash/proxies">https://proxy.tgbot.co/clash/proxies</a></p>
<br>
<p>Surge配置文件<a href="https://proxy.tgbot.co/surge/config">https://proxy.tgbot.co/surge/config</a> <a href="surge3:///install-config?url=https://proxy.tgbot.co/surge/config">一键导入</a></p>
<p>Surge proxy list<a href="https://proxy.tgbot.co/surge/proxies">https://proxy.tgbot.co/surge/proxies</a></p>
<br>
<p>抓取程序已开源:<a href="https://github.com/zu1k/proxypool">https://github.com/zu1k/proxypool</a></p>
</div>
</div>
</div>
</body>
</html>

45
assets/surge.conf Normal file
View File

@@ -0,0 +1,45 @@
[Proxy]
Direct = direct
[Proxy Group]
Proxy = select, 延迟最低, 失败切换, 手动选择
延迟最低 = url-test, policy-path=https://proxy.tgbot.co/surge/proxies, url=http://www.qualcomm.cn/generate_204, update-interval=3600, interval = 600s, tolerance = 100ms, timeout = 5s, evaluate-before-use = true
失败切换 = fallback, policy-path=https://proxy.tgbot.co/surge/proxies, url=http://www.qualcomm.cn/generate_204, update-interval=3600, interval = 600s, tolerance = 100ms, timeout = 5s, evaluate-before-use = true
手动选择 = select, policy-path=https://proxy.tgbot.co/surge/proxies, url=http://www.qualcomm.cn/generate_204, update-interval=3600, interval = 600s, tolerance = 100ms, timeout = 5s, evaluate-before-use = true
Apple = select, Direct, Proxy
Adblock = select, Direct, REJECT, REJECT-TINYGIF
[Rule]
# RULESET
RULE-SET,SYSTEM,Direct
#
# Unbreak 后续规则修正
RULE-SET,https://github.com/DivineEngine/Profiles/raw/master/Surge/Ruleset/Unbreak.list,Adblock
# Advertising 广告
RULE-SET,https://github.com/DivineEngine/Profiles/raw/master/Surge/Ruleset/Guard/Advertising.list,Adblock
# Privacy 隐私
# RULE-SET,https://github.com/DivineEngine/Profiles/raw/master/Surge/Ruleset/Guard/Privacy.list,Adblock
# Hijacking 运营商劫持或恶意网站
RULE-SET,https://github.com/DivineEngine/Profiles/raw/master/Surge/Ruleset/Guard/Hijacking.list,Adblock
#
# Apple
RULE-SET,https://github.com/DivineEngine/Profiles/raw/master/Surge/Ruleset/Extra/Apple/Apple.list,Apple
#
# 代理
# Streaming 国际流媒体服务
RULE-SET,https://github.com/DivineEngine/Profiles/raw/master/Surge/Ruleset/StreamingMedia/Streaming.list,Proxy
# StreamingSE 中国流媒体服务(面向海外版本)
RULE-SET,https://github.com/DivineEngine/Profiles/raw/master/Surge/Ruleset/StreamingMedia/StreamingSE.list,Proxy
# Global 全球加速
RULE-SET,https://github.com/DivineEngine/Profiles/raw/master/Surge/Ruleset/Global.list,Proxy
#
RULE-SET,https://github.com/Hackl0us/SS-Rule-Snippet/raw/master/Rulesets/App/social/Telegram.list,Proxy
RULE-SET,https://github.com/Hackl0us/SS-Rule-Snippet/raw/master/Rulesets/App/social/WhatsApp.list,Proxy
RULE-SET,https://github.com/Hackl0us/SS-Rule-Snippet/raw/master/Rulesets/App/social/LINE.list,Proxy
#
# Direct
RULE-SET,https://github.com/DivineEngine/Profiles/raw/master/Surge/Ruleset/Extra/ChinaIP.list,Direct
#
RULE-SET,LAN,Direct
# GEOIP,CN,Direct
FINAL,Proxy,dns-failed

86
assets/surge.html Normal file
View File

@@ -0,0 +1,86 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="HandheldFriendly" content="True">
<title>免费Surge节点</title>
<style type='text/css'>
body {
background-color: white;
color: #333333;
font-family: Arial, sans-serif;
margin: 0;
padding: 36px;
line-height: 1;
font-size: 14px; }
.section {
margin-bottom: 36px; }
.section.friendly {
color: #222222; }
.section.friendly h1 {
font-size: 26px;
background-color: #dad8e4;
padding: 18px 22px 15px 22px;
margin: 0;
overflow: hidden; }
.section.friendly h1 strong {
display: inline-block;
float: left; }
.section.friendly h1 small {
display: inline-block;
float: right;
text-align: right;
font-size: 18px;
padding-top: 4px;
color: #333333; }
.section.friendly .article {
border: 4px solid #dad8e4;
padding: 24px 18px 18px 18px; }
.section.friendly .article h3 {
font-size: 20px;
margin: 0 0 18px 0; }
.section.friendly .article a {
color: #6b6ceb; }
.section.friendly .article a:visited {
color: #1d1d3b; }
.section.friendly .article p {
font-size: 14px; }
.section.friendly .article ul {
list-style-type: square; }
.section.original {
background-color: #eeeeee;
color: #444444; }
.section.original h2 {
background-color: #dddddd;
margin: 0;
padding: 18px 22px 18px 22px;
font-size: 20px; }
.section.original pre {
margin: 0;
padding: 18px 22px 18px 22px;
overflow: auto;
font-family: monaco, monospaced; }
.section.original pre code {
display: block;
font-size: 11px;
width: 100%; }
</style>
</head>
<body>
<div class='container'>
<div class='section friendly'>
<h1><strong>免费Surge节点</strong></h1>
<div class='article'>
<p>自动抓取tg频道、订阅地址、公开互联网上的ss、vmess节点信息聚合去重后提供Surge节点列表每10分钟更新</p>
<br>
<p>Surge配置文件<a href="https://proxy.tgbot.co/surge/config">https://proxy.tgbot.co/surge/config</a> <a href="surge3:///install-config?url=https://proxy.tgbot.co/surge/config">一键导入</a></p>
<p>Surge proxy list<a href="https://proxy.tgbot.co/surge/proxies">https://proxy.tgbot.co/surge/proxies</a></p>
<br>
<p>抓取程序已开源:<a href="https://github.com/zu1k/proxypool">https://github.com/zu1k/proxypool</a></p>
</div>
</div>
</div>
</body>
</html>

2
go.mod
View File

@@ -31,5 +31,5 @@ require (
google.golang.org/appengine v1.6.6 // indirect
google.golang.org/protobuf v1.25.0 // indirect
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
gopkg.in/yaml.v2 v2.3.0 // indirect
gopkg.in/yaml.v2 v2.3.0
)

View File

@@ -3,3 +3,12 @@ package provider
type Provider interface {
Provide() string
}
func checkInList(list []string, item string) bool {
for _, i := range list {
if item == i {
return true
}
}
return false
}

View File

@@ -46,15 +46,6 @@ func checkClashSupport(p proxy.Proxy) bool {
return false
}
func checkInList(list []string, item string) bool {
for _, i := range list {
if item == i {
return true
}
}
return false
}
var ssrCipherList = []string{
"aes-128-cfb",
"aes-192-cfb",

40
provider/surge.go Normal file
View File

@@ -0,0 +1,40 @@
package provider
import (
"strings"
"github.com/zu1k/proxypool/proxy"
)
type Surge struct {
Proxies []proxy.Proxy `yaml:"proxies"`
}
func (s Surge) Provide() string {
var resultBuilder strings.Builder
for _, p := range s.Proxies {
if checkSurgeSupport(p) {
resultBuilder.WriteString(p.ToSurge() + "\n")
}
}
return resultBuilder.String()
}
func checkSurgeSupport(p proxy.Proxy) bool {
switch p.(type) {
case *proxy.ShadowsocksR:
return false
case *proxy.Vmess:
return true
case *proxy.Shadowsocks:
ss := p.(*proxy.Shadowsocks)
if checkInList(ssCipherList, ss.Cipher) {
return true
}
default:
return false
}
return false
}

View File

@@ -11,6 +11,7 @@ type Base struct {
type Proxy interface {
String() string
ToClash() string
ToSurge() string
Identifier() string
SetName(name string)
}

View File

@@ -3,6 +3,7 @@ package proxy
import (
"encoding/json"
"errors"
"fmt"
"math/rand"
"net"
"net/url"
@@ -45,6 +46,21 @@ func (ss Shadowsocks) ToClash() string {
return "- " + string(data)
}
func (ss Shadowsocks) ToSurge() string {
// node1 = ss, server, port, encrypt-method=, password=, obfs=, obfs-host=, udp-relay=false
if ss.Plugin == "obfs" {
text := fmt.Sprintf("%s = ss, %s, %d, encrypt-method=%s, password=%s, obfs=%s, udp-relay=false",
ss.Name, ss.Server, ss.Port, ss.Cipher, ss.Password, ss.PluginOpts["mode"])
if ss.PluginOpts["host"].(string) != "" {
text += ", obfs-host=" + ss.PluginOpts["host"].(string)
}
return text
} else {
return fmt.Sprintf("%s = ss, %s, %d, encrypt-method=%s, password=%s, udp-relay=false",
ss.Name, ss.Server, ss.Port, ss.Cipher, ss.Password)
}
}
func (ss *Shadowsocks) SetName(name string) {
ss.Name = name
}
@@ -107,6 +123,9 @@ func ParseSSLink(link string) (*Shadowsocks, error) {
}
}
}
if port == 0 || cipher == "" {
return nil, ErrorNotSSLink
}
return &Shadowsocks{
Base: Base{

View File

@@ -53,6 +53,10 @@ func (ssr ShadowsocksR) ToClash() string {
return "- " + string(data)
}
func (ssr ShadowsocksR) ToSurge() string {
return ""
}
func (ssr *ShadowsocksR) SetName(name string) {
ssr.Name = name
}

View File

@@ -3,6 +3,7 @@ package proxy
import (
"encoding/json"
"errors"
"fmt"
"math/rand"
"net"
"net/url"
@@ -58,6 +59,29 @@ func (v Vmess) ToClash() string {
return "- " + string(data)
}
func (v Vmess) ToSurge() string {
// node2 = vmess, server, port, username=, ws=true, ws-path=, ws-headers=
if v.Network == "ws" {
wsHeasers := ""
for k, v := range v.WSHeaders {
if wsHeasers == "" {
wsHeasers = k + ":" + v
} else {
wsHeasers += "|" + k + ":" + v
}
}
text := fmt.Sprintf("%s = vmess, %s, %d, username=%s, ws=true, tls=%t, ws-path=%s",
v.Name, v.Server, v.Port, v.UUID, v.TLS, v.WSPath)
if wsHeasers != "" {
text += ", ws-headers=" + wsHeasers
}
return text
} else {
return fmt.Sprintf("%s = vmess, %s, %d, username=%s, tls=%t",
v.Name, v.Server, v.Port, v.UUID, v.TLS)
}
}
func (v *Vmess) SetName(name string) {
v.Name = name
}
@@ -129,6 +153,9 @@ func ParseVmessLink(link string) (*Vmess, error) {
}
//obfsParam := moreInfo.Get("obfsParam")
path := moreInfo.Get("path")
if path == "" {
path = "/"
}
tls := moreInfo.Get("tls") == "1"
wsHeaders := make(map[string]string)
@@ -176,8 +203,13 @@ func ParseVmessLink(link string) (*Vmess, error) {
tls := vmessJson.Tls == "tls"
wsHeaders := make(map[string]string)
wsHeaders["HOST"] = vmessJson.Host
if vmessJson.Host != "" {
wsHeaders["HOST"] = vmessJson.Host
}
if vmessJson.Path == "" {
vmessJson.Path = "/"
}
return &Vmess{
Base: Base{
Name: vmessJson.Ps + "_" + strconv.Itoa(rand.Int()),