Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8cb970c010 | ||
|
|
bc8002e656 | ||
|
|
ce1e4938d2 | ||
|
|
d9790fb7c6 | ||
|
|
01341f2894 | ||
|
|
36f7fb11b0 | ||
|
|
a1b46e9fa4 | ||
|
|
3c68aafd18 | ||
|
|
5ec8cfcc43 | ||
|
|
272a1c1277 | ||
|
|
23bdc67444 | ||
|
|
8f5d76a471 | ||
|
|
5222a11d20 | ||
|
|
5329a7b545 | ||
|
|
180c5b7943 | ||
|
|
0d30186ea4 | ||
|
|
956910881e | ||
|
|
d885b747fa | ||
|
|
14b8577186 | ||
|
|
3653819e28 | ||
|
|
055e1f3db0 | ||
|
|
15b4ce563c | ||
|
|
abb65edfb2 | ||
|
|
cc61798fdf |
76
README.md
Normal file
76
README.md
Normal file
@@ -0,0 +1,76 @@
|
||||
<h1 align="center">
|
||||
<br>proxypool<br>
|
||||
</h1>
|
||||
|
||||
<h5 align="center">自动抓取tg频道、订阅地址、公开互联网上的ss、ssr、vmess节点信息,聚合去重后提供节点列表</h5>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/zu1k/proxypool/actions">
|
||||
<img src="https://img.shields.io/github/workflow/status/zu1k/proxypool/Go?style=flat-square" alt="Github Actions">
|
||||
</a>
|
||||
<a href="https://goreportcard.com/report/github.com/zu1k/proxypool">
|
||||
<img src="https://goreportcard.com/badge/github.com/zu1k/proxypool?style=flat-square">
|
||||
</a>
|
||||
<a href="https://github.com/zu1k/proxypool/releases">
|
||||
<img src="https://img.shields.io/github/release/zu1k/proxypool/all.svg?style=flat-square">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
## 支持
|
||||
|
||||
- 支持ss、ssr、vmess节点链接与订阅
|
||||
- 任意 Telegram 频道抓取
|
||||
- 机场订阅地址抓取解析
|
||||
- 公开互联网页面模糊抓取
|
||||
- 翻墙党论坛新节点信息
|
||||
- 其他节点分享网站
|
||||
- 定时抓取更新
|
||||
- 使用配置文件提供抓取源
|
||||
|
||||
## 安装
|
||||
|
||||
### 从源码编译
|
||||
|
||||
需要安装Golang
|
||||
|
||||
```sh
|
||||
$ go get -u -v github.com/zu1k/proxypool
|
||||
```
|
||||
|
||||
### 下载预编译程序
|
||||
|
||||
从这里下载预编译好的程序 [release](https://github.com/zu1k/proxypool/releases)
|
||||
|
||||
### 使用docker
|
||||
|
||||
```sh
|
||||
docker pull docker.pkg.github.com/zu1k/proxypool/proxypool:latest
|
||||
```
|
||||
|
||||
## 使用
|
||||
|
||||
### 共享抓取配置文件
|
||||
|
||||
每一次抓取前会自动从github下载最新的抓取配置文件
|
||||
|
||||
直接运行 `proxypool` 程序即可
|
||||
|
||||
### 自定义抓取配置文件
|
||||
|
||||
```shell
|
||||
proxypool -c source.yaml
|
||||
```
|
||||
|
||||
### 帮助更新配置文件
|
||||
|
||||
可以在 https://github.com/zu1k/proxypool/issues/3 进行留言
|
||||
|
||||
### 用户使用
|
||||
|
||||
目前公开版本: https://proxy.tgbot.co
|
||||
|
||||
直接在clash添加配置文件即可使用: https://proxy.tgbot.co/clash/config
|
||||
|
||||
## 截图
|
||||
|
||||

|
||||
@@ -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() {
|
||||
|
||||
14
app/task.go
14
app/task.go
@@ -5,10 +5,12 @@ import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"math/rand"
|
||||
"os"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"github.com/zu1k/proxypool/config"
|
||||
"gopkg.in/yaml.v2"
|
||||
|
||||
"github.com/zu1k/proxypool/app/cache"
|
||||
"github.com/zu1k/proxypool/provider"
|
||||
"github.com/zu1k/proxypool/proxy"
|
||||
@@ -35,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() {
|
||||
@@ -66,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() {
|
||||
@@ -76,12 +80,10 @@ func FetchNewConfigFileThenInit() {
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
|
||||
err = yaml.Unmarshal(body, &config.SourceConfig)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = ioutil.WriteFile("source.yaml", body, os.ModePerm)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
InitConfigAndGetters("source.yaml")
|
||||
InitGetters(config.SourceConfig.Sources)
|
||||
}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
# 所有节点均从公开互联网上抓取,使用clash自动检查可用性即可
|
||||
# 抓取程序已开源: https://github.com/zu1k/proxypool
|
||||
|
||||
# port of HTTP
|
||||
port: 7890
|
||||
|
||||
@@ -73,9 +73,12 @@
|
||||
<div class='section friendly'>
|
||||
<h1><strong>免费Clash节点</strong></h1>
|
||||
<div class='article'>
|
||||
<p>所有节点均从公开互联网上爬取,每10分钟自动更新</p>
|
||||
<p>Clash配置文件:<a href="https://proxy.tgbot.co/clash/config">https://proxy.tgbot.co/clash/config</a></p>
|
||||
<p>自动抓取tg频道、订阅地址、公开互联网上的ss、ssr、vmess节点信息,聚合去重后提供clash配置,每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>抓取程序已开源:<a href="https://github.com/zu1k/proxypool">https://github.com/zu1k/proxypool</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
89
assets/index.html
Normal file
89
assets/index.html
Normal 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
45
assets/surge.conf
Normal 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
86
assets/surge.html
Normal 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>
|
||||
BIN
docs/run.png
Normal file
BIN
docs/run.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 188 KiB |
@@ -22,14 +22,14 @@ type TGChannelGetter struct {
|
||||
|
||||
func NewTGChannelGetter(options tool.Options) Getter {
|
||||
num, found := options["num"]
|
||||
if !found || int(num.(float64)) <= 0 {
|
||||
if !found || num.(int) <= 0 {
|
||||
num = 200
|
||||
}
|
||||
url, found := options["channel"]
|
||||
if found {
|
||||
return &TGChannelGetter{
|
||||
c: colly.NewCollector(),
|
||||
NumNeeded: int(num.(float64)),
|
||||
NumNeeded: num.(int),
|
||||
Url: "https://t.me/s/" + url.(string),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,14 +22,14 @@ type WebFanqiangdang struct {
|
||||
|
||||
func NewWebFanqiangdangGetter(options tool.Options) Getter {
|
||||
num, found := options["num"]
|
||||
if !found || int(num.(float64)) <= 0 {
|
||||
if !found || num.(int) <= 0 {
|
||||
num = 200
|
||||
}
|
||||
url, found := options["url"]
|
||||
if found {
|
||||
return &WebFanqiangdang{
|
||||
c: colly.NewCollector(),
|
||||
NumNeeded: int(num.(float64)),
|
||||
NumNeeded: num.(int),
|
||||
Url: url.(string),
|
||||
}
|
||||
}
|
||||
|
||||
2
go.mod
2
go.mod
@@ -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
|
||||
)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
40
provider/surge.go
Normal 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
|
||||
}
|
||||
@@ -11,6 +11,7 @@ type Base struct {
|
||||
type Proxy interface {
|
||||
String() string
|
||||
ToClash() string
|
||||
ToSurge() string
|
||||
Identifier() string
|
||||
SetName(name string)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -59,20 +75,35 @@ func ParseSSLink(link string) (*Shadowsocks, error) {
|
||||
return nil, ErrorNotSSLink
|
||||
}
|
||||
|
||||
cipher := ""
|
||||
password := ""
|
||||
if uri.User.String() == "" {
|
||||
// base64的情况
|
||||
infos, err := tool.Base64DecodeString(uri.Hostname())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
uri, err = url.Parse("ss://" + infos)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cipher = uri.User.Username()
|
||||
password, _ = uri.User.Password()
|
||||
} else {
|
||||
cipherInfoString, err := tool.Base64DecodeString(uri.User.Username())
|
||||
if err != nil {
|
||||
return nil, ErrorPasswordParseFail
|
||||
}
|
||||
cipherInfo := strings.SplitN(cipherInfoString, ":", 2)
|
||||
if len(cipherInfo) < 2 {
|
||||
return nil, ErrorPasswordParseFail
|
||||
}
|
||||
cipher = strings.ToLower(cipherInfo[0])
|
||||
password = cipherInfo[1]
|
||||
}
|
||||
server := uri.Hostname()
|
||||
port, _ := strconv.Atoi(uri.Port())
|
||||
|
||||
cipherInfoString, err := tool.Base64DecodeString(uri.User.Username())
|
||||
if err != nil {
|
||||
return nil, ErrorPasswordParseFail
|
||||
}
|
||||
cipherInfo := strings.SplitN(cipherInfoString, ":", 2)
|
||||
if len(cipherInfo) < 2 {
|
||||
return nil, ErrorPasswordParseFail
|
||||
}
|
||||
cipher := strings.ToLower(cipherInfo[0])
|
||||
password := cipherInfo[1]
|
||||
|
||||
moreInfos := uri.Query()
|
||||
pluginString := moreInfos.Get("plugin")
|
||||
plugin := ""
|
||||
@@ -92,6 +123,9 @@ func ParseSSLink(link string) (*Shadowsocks, error) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if port == 0 || cipher == "" {
|
||||
return nil, ErrorNotSSLink
|
||||
}
|
||||
|
||||
return &Shadowsocks{
|
||||
Base: Base{
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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()),
|
||||
|
||||
@@ -202,6 +202,10 @@ sources:
|
||||
options:
|
||||
channel: ssrList
|
||||
num: 200
|
||||
- type: tgchannel
|
||||
options:
|
||||
channel: ssList
|
||||
num: 200
|
||||
|
||||
- type: tgchannel
|
||||
options:
|
||||
@@ -248,6 +252,11 @@ sources:
|
||||
channel: fanqiang666
|
||||
num: 200
|
||||
|
||||
- type: tgchannel
|
||||
options:
|
||||
channel: jiedianfenxiang
|
||||
num: 200
|
||||
|
||||
- type: web-fanqiangdang
|
||||
options:
|
||||
url: https://fanqiangdang.com/forum.php?mod=rss&fid=50&auth=0
|
||||
|
||||
Reference in New Issue
Block a user