This commit is contained in:
starry
2025-07-16 12:35:21 +00:00
commit 1f7b4314c3
49 changed files with 18341 additions and 0 deletions

469
proxy/duosk5.go Normal file
View File

@@ -0,0 +1,469 @@
package main
import (
"bufio"
"crypto/rand"
"encoding/json"
"fmt"
"io"
"net"
"net/http"
"os"
"os/exec"
"regexp"
"strconv"
"strings"
"time"
)
const (
// 颜色常量ANSI转义码
ColorReset = "\033[0m"
ColorRed = "\033[31m"
ColorGreen = "\033[32m"
ColorYellow = "\033[33m"
ColorCyan = "\033[36m"
// 构建CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o sk5 main.go
// 脚本过期时间以及其他变量
EXPIRE_DATE = "2025-06-08 02:01:01"
CONFIG_FILE = "/usr/local/etc/xray/config.json"
SOCKS_FILE = "/home/socks.txt"
XRAY_INSTALL_URL = "https://github.com/XTLS/Xray-install/raw/main/install-release.sh"
XRAY_VERSION = "v1.8.4"
START_PORT = 10001
)
// 彩色打印函数
func colorPrint(colorCode, format string, a ...interface{}) {
fmt.Printf(colorCode+format+ColorReset+"\n", a...)
}
// XrayConfig represents the Xray configuration structure
type XrayConfig struct {
Inbounds []Inbound `json:"inbounds"`
Outbounds []Outbound `json:"outbounds"`
Routing Routing `json:"routing"`
}
type Inbound struct {
Port int `json:"port"`
Protocol string `json:"protocol"`
Settings InboundSettings `json:"settings"`
StreamSettings StreamSettings `json:"streamSettings"`
Tag string `json:"tag"`
}
type InboundSettings struct {
Auth string `json:"auth"`
Accounts []Account `json:"accounts"`
UDP bool `json:"udp"`
IP string `json:"ip"`
}
type Account struct {
User string `json:"user"`
Pass string `json:"pass"`
}
type StreamSettings struct {
Network string `json:"network"`
}
type Outbound struct {
Protocol string `json:"protocol"`
Settings interface{} `json:"settings"`
SendThrough string `json:"sendThrough"`
Tag string `json:"tag"`
}
type Routing struct {
Rules []Rule `json:"rules"`
}
type Rule struct {
Type string `json:"type"`
InboundTag []string `json:"inboundTag"`
OutboundTag string `json:"outboundTag"`
}
type NodeInfo struct {
IP string
Port int
Username string
Password string
}
// generateRandomString generates a random string of specified length
func generateRandomString(length int) string {
const charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
b := make([]byte, length)
if _, err := rand.Read(b); err != nil {
panic(err)
}
for i := range b {
b[i] = charset[b[i]%byte(len(charset))]
}
return string(b)
}
// checkExpiration checks if the script has expired
func checkExpiration() error {
colorPrint(ColorCyan, "开始运行...")
// Get timestamp from cloudflare
resp, err := http.Get("https://www.cloudflare.com/cdn-cgi/trace")
if err != nil {
return fmt.Errorf("网络错误")
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return fmt.Errorf("读取响应失败")
}
// Extract timestamp
re := regexp.MustCompile(`ts=(\d+)`)
matches := re.FindStringSubmatch(string(body))
if len(matches) < 2 {
return fmt.Errorf("无法解析时间")
}
timestamp, err := strconv.ParseInt(matches[1], 10, 64)
if err != nil {
return fmt.Errorf("时间转换失败")
}
// Convert to Beijing time
currentTime := time.Unix(timestamp, 0).In(time.FixedZone("CST", 8*3600))
expireTime, _ := time.ParseInLocation("2006-01-02 15:04:05", EXPIRE_DATE, time.FixedZone("CST", 8*3600))
if currentTime.After(expireTime) {
return fmt.Errorf("当前脚本已过期,请联系作者")
}
return nil
}
// commandExists checks if a command exists in PATH
func commandExists(cmd string) bool {
_, err := exec.LookPath(cmd)
return err == nil
}
// installJQ installs jq if not present
func installJQ() error {
if commandExists("jq") {
colorPrint(ColorGreen, "jq 已安装")
return nil
}
colorPrint(ColorYellow, "jq 未安装,正在安装 jq...")
// Detect OS
if _, err := os.Stat("/etc/debian_version"); err == nil {
// Debian/Ubuntu
cmd := exec.Command("bash", "-c", "apt update && apt install -yq jq")
return cmd.Run()
} else if _, err := os.Stat("/etc/redhat-release"); err == nil {
// RHEL/CentOS
cmd := exec.Command("yum", "install", "-y", "epel-release", "jq")
return cmd.Run()
}
return fmt.Errorf("无法确定系统发行版,请手动安装 jq")
}
// installXray installs Xray if not present
func installXray() error {
if commandExists("xray") {
colorPrint(ColorGreen, "Xray 已安装")
return nil
}
colorPrint(ColorYellow, "Xray 未安装,正在安装 Xray...")
cmd := exec.Command("bash", "-c", fmt.Sprintf("curl -L %s | bash -s install --version %s", XRAY_INSTALL_URL, XRAY_VERSION))
if err := cmd.Run(); err != nil {
return fmt.Errorf("Xray 安装失败: %v", err)
}
colorPrint(ColorGreen, "Xray 安装完成")
return nil
}
// getPublicIPv4 gets all public IPv4 addresses
func getPublicIPv4() ([]string, error) {
var publicIPs []string
// Get all network interfaces
interfaces, err := net.Interfaces()
if err != nil {
return nil, err
}
for _, iface := range interfaces {
if iface.Flags&net.FlagUp == 0 || iface.Flags&net.FlagLoopback != 0 {
continue
}
addrs, err := iface.Addrs()
if err != nil {
continue
}
for _, addr := range addrs {
if ipNet, ok := addr.(*net.IPNet); ok && !ipNet.IP.IsLoopback() {
if ipNet.IP.To4() != nil {
ip := ipNet.IP.String()
// Check if it's a public IP
if isPublicIP(ip) {
publicIPs = append(publicIPs, ip)
}
}
}
}
}
return publicIPs, nil
}
// isPublicIP checks if an IP is public
func isPublicIP(ip string) bool {
parsedIP := net.ParseIP(ip)
if parsedIP == nil {
return false
}
// Check for private IP ranges
privateRanges := []string{
"127.0.0.0/8", // loopback
"10.0.0.0/8", // private
"172.16.0.0/12", // private
"192.168.0.0/16", // private
"169.254.0.0/16", // link-local
}
for _, cidr := range privateRanges {
_, network, _ := net.ParseCIDR(cidr)
if network.Contains(parsedIP) {
return false
}
}
return true
}
// ensureSocksFileExists creates socks.txt if it doesn't exist
func ensureSocksFileExists() error {
if _, err := os.Stat(SOCKS_FILE); os.IsNotExist(err) {
colorPrint(ColorYellow, "socks.txt 文件不存在,正在创建...")
file, err := os.Create(SOCKS_FILE)
if err != nil {
return err
}
file.Close()
}
return nil
}
// saveNodeInfo saves node information to file and prints it
func saveNodeInfo(node NodeInfo) error {
// Print node info with colors
fmt.Printf(" IP: %s%s%s 端口: %s%d%s 用户名: %s%s%s 密码: %s%s%s\n",
ColorGreen, node.IP, ColorReset,
ColorGreen, node.Port, ColorReset,
ColorGreen, node.Username, ColorReset,
ColorGreen, node.Password, ColorReset)
// Save to file
file, err := os.OpenFile(SOCKS_FILE, os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {
return err
}
defer file.Close()
_, err = fmt.Fprintf(file, "%s %d %s %s\n", node.IP, node.Port, node.Username, node.Password)
return err
}
// configureXray configures Xray with multiple IPs
func configureXray() error {
publicIPs, err := getPublicIPv4()
if err != nil {
return fmt.Errorf("获取公网IP失败: %v", err)
}
if len(publicIPs) == 0 {
return fmt.Errorf("未找到额外IP地址")
}
colorPrint(ColorCyan, "找到的公网 IPv4 地址: %v", publicIPs)
// Create initial config
config := XrayConfig{
Inbounds: []Inbound{},
Outbounds: []Outbound{},
Routing: Routing{
Rules: []Rule{},
},
}
// Configure each IP
port := START_PORT
for _, ip := range publicIPs {
colorPrint(ColorCyan, "正在配置 IP: %s 端口: %d", ip, port)
username := generateRandomString(8)
password := generateRandomString(8)
// Create inbound
inbound := Inbound{
Port: port,
Protocol: "socks",
Settings: InboundSettings{
Auth: "password",
Accounts: []Account{
{User: username, Pass: password},
},
UDP: true,
IP: "0.0.0.0",
},
StreamSettings: StreamSettings{
Network: "tcp",
},
Tag: fmt.Sprintf("in-%d", port),
}
// Create outbound
outbound := Outbound{
Protocol: "freedom",
Settings: map[string]interface{}{},
SendThrough: ip,
Tag: fmt.Sprintf("out-%d", port),
}
// Create routing rule
rule := Rule{
Type: "field",
InboundTag: []string{fmt.Sprintf("in-%d", port)},
OutboundTag: fmt.Sprintf("out-%d", port),
}
config.Inbounds = append(config.Inbounds, inbound)
config.Outbounds = append(config.Outbounds, outbound)
config.Routing.Rules = append(config.Routing.Rules, rule)
// Save node info
node := NodeInfo{
IP: ip,
Port: port,
Username: username,
Password: password,
}
if err := saveNodeInfo(node); err != nil {
return fmt.Errorf("保存节点信息失败: %v", err)
}
port++
}
// Write config file
configData, err := json.MarshalIndent(config, "", " ")
if err != nil {
return fmt.Errorf("序列化配置失败: %v", err)
}
if err := os.WriteFile(CONFIG_FILE, configData, 0644); err != nil {
return fmt.Errorf("写入配置文件失败: %v", err)
}
colorPrint(ColorGreen, "Xray 配置完成")
return nil
}
// restartXray restarts the Xray service
func restartXray() error {
colorPrint(ColorCyan, "正在重启 Xray 服务...")
// Restart service
cmd := exec.Command("systemctl", "restart", "xray")
if err := cmd.Run(); err != nil {
return fmt.Errorf("Xray 服务重启失败: %v", err)
}
// Enable service
cmd = exec.Command("systemctl", "enable", "xray")
if err := cmd.Run(); err != nil {
return fmt.Errorf("启用 Xray 服务失败: %v", err)
}
colorPrint(ColorGreen, "Xray 服务已重启")
return nil
}
// readUserInput reads user input for confirmation
func readUserInput(prompt string) string {
fmt.Print(prompt)
reader := bufio.NewReader(os.Stdin)
input, _ := reader.ReadString('\n')
return strings.TrimSpace(input)
}
func main() {
colorPrint(ColorCyan, "站群多IP源进源出sk5协议一键脚本")
colorPrint(ColorCyan, "当前为测试版,可以联系作者获取源码")
expireTime, err := time.ParseInLocation("2006-01-02 15:04:05", EXPIRE_DATE, time.FixedZone("CST", 8*3600))
if err == nil {
expireStr := fmt.Sprintf("%d年%d月%d日%d点%d分%d秒",
expireTime.Year(),
expireTime.Month(),
expireTime.Day(),
expireTime.Hour(),
expireTime.Minute(),
expireTime.Second())
colorPrint(ColorCyan, "脚本过期时间: %s", expireStr)
} else {
colorPrint(ColorYellow, "脚本过期时间解析失败")
}
fmt.Println()
// Check expiration
if err := checkExpiration(); err != nil {
colorPrint(ColorRed, "错误: %v", err)
os.Exit(1)
}
// Ensure socks file exists
if err := ensureSocksFileExists(); err != nil {
colorPrint(ColorRed, "创建socks文件失败: %v", err)
os.Exit(1)
}
// Install jq
if err := installJQ(); err != nil {
colorPrint(ColorRed, "安装jq失败: %v", err)
os.Exit(1)
}
// Install Xray
if err := installXray(); err != nil {
colorPrint(ColorRed, "安装Xray失败: %v", err)
os.Exit(1)
}
// Configure Xray
if err := configureXray(); err != nil {
colorPrint(ColorRed, "配置Xray失败: %v", err)
os.Exit(1)
}
// Restart Xray
if err := restartXray(); err != nil {
colorPrint(ColorRed, "重启Xray失败: %v", err)
os.Exit(1)
}
colorPrint(ColorGreen, "部署完成,所有节点信息已保存到 %s", SOCKS_FILE)
}