Files
trojanZ/trojan-master/trojan/install.go
T
2026-07-26 00:09:57 +08:00

225 lines
6.5 KiB
Go

package trojan
import (
"fmt"
"net"
"runtime"
"strconv"
"strings"
"time"
"trojan/asset"
"trojan/core"
"trojan/util"
)
var (
dockerInstallUrl = "https://docker-install.netlify.app/install.sh"
dbDockerRun = "docker run --name trojan-mariadb --restart=always -p %d:3306 -v /home/mariadb:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=%s -e MYSQL_ROOT_HOST=%% -e MYSQL_DATABASE=trojan -d mariadb:10.2"
)
// InstallMenu 安装目录
func InstallMenu() {
fmt.Println()
menu := []string{"更新trojan", "证书申请", "安装mysql"}
switch util.LoopInput("请选择: ", menu, true) {
case 1:
InstallTrojan("")
case 2:
InstallTls()
case 3:
InstallMysql()
default:
return
}
}
// InstallDocker 安装docker
func InstallDocker() {
if !util.CheckCommandExists("docker") {
util.RunWebShell(dockerInstallUrl)
fmt.Println()
}
}
// InstallTrojan 安装trojan
func InstallTrojan(version string) {
fmt.Println()
data := string(asset.GetAsset("trojan-install.sh"))
checkTrojan := util.ExecCommandWithResult("systemctl list-unit-files|grep trojan.service")
if (checkTrojan == "" && runtime.GOARCH != "amd64") || Type() == "trojan-go" {
data = strings.ReplaceAll(data, "TYPE=0", "TYPE=1")
}
if version != "" {
data = strings.ReplaceAll(data, "INSTALL_VERSION=\"\"", "INSTALL_VERSION=\""+version+"\"")
}
util.ExecCommand(data)
util.OpenPort(443)
util.SystemctlRestart("trojan")
util.SystemctlEnable("trojan")
}
// InstallTls 安装证书
func InstallTls() {
domain := ""
server := "letsencrypt"
fmt.Println()
choice := util.LoopInput("请选择使用证书方式: ", []string{"Let's Encrypt 证书", "ZeroSSL 证书", "BuyPass 证书", "自定义证书路径"}, true)
if choice < 0 {
return
} else if choice == 4 {
crtFile := util.Input("请输入证书的cert文件路径: ", "")
keyFile := util.Input("请输入证书的key文件路径: ", "")
if !util.IsExists(crtFile) || !util.IsExists(keyFile) {
fmt.Println("输入的cert或者key文件不存在!")
} else {
domain = util.Input("请输入此证书对应的域名: ", "")
if domain == "" {
fmt.Println("输入域名为空!")
return
}
core.WriteTls(crtFile, keyFile, domain)
}
} else {
if choice == 2 {
server = "zerossl"
} else if choice == 3 {
server = "buypass"
}
localIP := util.GetLocalIP()
fmt.Printf("本机ip: %s\n", localIP)
for {
domain = util.Input("请输入申请证书的域名: ", "")
ipList, err := net.LookupIP(domain)
fmt.Printf("%s 解析到的ip: %v\n", domain, ipList)
if err != nil {
fmt.Println(err)
fmt.Println("域名有误,请重新输入")
continue
}
checkIp := false
for _, ip := range ipList {
if localIP == ip.String() {
checkIp = true
}
}
if checkIp {
break
} else {
fmt.Println("输入的域名和本机ip不一致, 请重新输入!")
}
}
util.InstallPack("socat")
if !util.IsExists("/root/.acme.sh/acme.sh") {
util.RunWebShell("https://get.acme.sh")
}
util.SystemctlStop("trojan-web")
util.OpenPort(80)
checkResult := util.ExecCommandWithResult("/root/.acme.sh/acme.sh -v|tr -cd '[0-9]'")
acmeVersion, _ := strconv.Atoi(checkResult)
if acmeVersion < 300 {
util.ExecCommand("/root/.acme.sh/acme.sh --upgrade")
}
if server != "letsencrypt" {
var email string
for {
email = util.Input(fmt.Sprintf("请输入申请%s域名所需的邮箱: ", server), "")
if email == "" {
fmt.Println("申请域名的邮箱地址为空!")
return
} else if util.VerifyEmailFormat(email) {
break
} else {
fmt.Println("邮箱格式不正确, 请重新输入!")
}
}
util.ExecCommand(fmt.Sprintf("bash /root/.acme.sh/acme.sh --server %s --register-account -m %s", server, email))
}
issueCommand := fmt.Sprintf("bash /root/.acme.sh/acme.sh --issue -d %s --debug --standalone --keylength ec-256 --force --server %s", domain, server)
if server == "buypass" {
issueCommand = issueCommand + " --days 170"
}
util.ExecCommand(issueCommand)
crtFile := "/root/.acme.sh/" + domain + "_ecc" + "/fullchain.cer"
keyFile := "/root/.acme.sh/" + domain + "_ecc" + "/" + domain + ".key"
core.WriteTls(crtFile, keyFile, domain)
}
Restart()
util.SystemctlRestart("trojan-web")
fmt.Println()
}
// InstallMysql 安装mysql
func InstallMysql() {
var (
mysql core.Mysql
choice int
)
fmt.Println()
if util.IsExists("/.dockerenv") {
choice = 2
} else {
choice = util.LoopInput("请选择: ", []string{"安装docker版mysql(mariadb)", "输入自定义mysql连接"}, true)
}
if choice < 0 {
return
} else if choice == 1 {
mysql = core.Mysql{ServerAddr: "127.0.0.1", ServerPort: util.RandomPort(), Password: util.RandString(8, util.LETTER+util.DIGITS), Username: "root", Database: "trojan"}
InstallDocker()
fmt.Println(fmt.Sprintf(dbDockerRun, mysql.ServerPort, mysql.Password))
if util.CheckCommandExists("setenforce") {
util.ExecCommand("setenforce 0")
}
util.OpenPort(mysql.ServerPort)
util.ExecCommand(fmt.Sprintf(dbDockerRun, mysql.ServerPort, mysql.Password))
db := mysql.GetDB()
for {
fmt.Printf("%s mariadb启动中,请稍等...\n", time.Now().Format("2006-01-02 15:04:05"))
err := db.Ping()
if err == nil {
db.Close()
break
} else {
time.Sleep(2 * time.Second)
}
}
fmt.Println("mariadb启动成功!")
} else if choice == 2 {
mysql = core.Mysql{}
for {
for {
mysqlUrl := util.Input("请输入mysql连接地址(格式: host:port), 默认连接地址为127.0.0.1:3306, 使用直接回车, 否则输入自定义连接地址: ",
"127.0.0.1:3306")
urlInfo := strings.Split(mysqlUrl, ":")
if len(urlInfo) != 2 {
fmt.Printf("输入的%s不符合匹配格式(host:port)\n", mysqlUrl)
continue
}
port, err := strconv.Atoi(urlInfo[1])
if err != nil {
fmt.Printf("%s不是数字\n", urlInfo[1])
continue
}
mysql.ServerAddr, mysql.ServerPort = urlInfo[0], port
break
}
mysql.Username = util.Input("请输入mysql的用户名(回车使用root): ", "root")
mysql.Password = util.Input(fmt.Sprintf("请输入mysql %s用户的密码: ", mysql.Username), "")
db := mysql.GetDB()
if db != nil && db.Ping() == nil {
mysql.Database = util.Input("请输入使用的数据库名(不存在可自动创建, 回车使用trojan): ", "trojan")
db.Exec(fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s;", mysql.Database))
break
} else {
fmt.Println("连接mysql失败, 请重新输入")
}
}
}
mysql.CreateTable()
core.WriteMysql(&mysql)
if userList, _ := mysql.GetData(); len(userList) == 0 {
AddUser()
}
Restart()
fmt.Println()
}