Files
v2ray_simple/cmd/verysimple/cmd.go
T
2023-02-11 18:40:39 +08:00

254 lines
5.5 KiB
Go

package main
import (
"flag"
"fmt"
"io"
"net/http"
"os"
httpProxy "github.com/e1732a364fed/v2ray_simple/proxy/http"
"github.com/e1732a364fed/v2ray_simple/tlsLayer"
vs "github.com/e1732a364fed/v2ray_simple"
"github.com/e1732a364fed/v2ray_simple/advLayer"
"github.com/e1732a364fed/v2ray_simple/netLayer"
"github.com/e1732a364fed/v2ray_simple/proxy"
"github.com/e1732a364fed/v2ray_simple/utils"
)
//本文件下所有命令的输出统一使用 fmt 而不是 log
var (
download bool
preCommands []func()
exitCmds = []exitCmd{
{name: "sp", desc: "print supported protocols", f: printSupportedProtocols},
{name: "v", desc: "print the version string then exit", f: func() { printVersion_simple(os.Stdout) }},
{name: "pifs", desc: "print all network interfaces", f: func() {
netLayer.PrintAllInterface(os.Stdout)
}},
}
)
type exitCmd struct {
enable, defaultBoolValue, isStr bool
name, desc, defaultStringValue, strValue string
f func()
fs func(string)
}
func init() {
flag.BoolVar(&download, "d", false, " automatically download required mmdb file")
}
func initExitCmds() {
for i, ec := range exitCmds {
if ec.isStr {
flag.StringVar(&exitCmds[i].strValue, ec.name, ec.defaultStringValue, ec.desc)
} else {
flag.BoolVar(&exitCmds[i].enable, ec.name, ec.defaultBoolValue, ec.desc)
}
}
}
// 运行一些 执行后立即退出程序的 命令
func runExitCommands() (atLeastOneCalled bool) {
for _, ec := range exitCmds {
if ec.isStr {
if ec.strValue != "" {
if ec.fs != nil {
ec.fs(ec.strValue)
atLeastOneCalled = true
}
}
} else {
if ec.enable {
if ec.f != nil {
ec.f()
atLeastOneCalled = true
}
}
}
}
return
}
// 运行 一些 在 加载配置文件前 执行的 命令
func runPreCommands() {
if len(preCommands) > 0 {
for _, f := range preCommands {
f()
}
}
}
// 运行一些 在 加载配置文件后 、开始正式代理前 执行的 命令
func runPreCommandsAfterLoadConf() {
if download {
tryDownloadMMDB()
tryDownloadGeositeSource()
}
}
func generateAndPrintUUID() {
utils.PrintStr("New random uuid : ")
utils.PrintStr(utils.GenerateUUIDStr())
utils.PrintStr("\n")
}
func generateRandomSSlCert() {
const certFn = "cert.pem"
const keyFn = "cert.key"
if utils.FileExist(certFn) {
utils.PrintStr(certFn)
utils.PrintStr(" 已存在!\n")
return
}
if utils.FileExist(keyFn) {
utils.PrintStr(keyFn)
utils.PrintStr(" 已存在!\n")
return
}
err := tlsLayer.GenerateRandomCertKeyFiles(certFn, keyFn)
if err == nil {
utils.PrintStr("生成成功!请查看目录中的 ")
utils.PrintStr(certFn)
utils.PrintStr(" 和 ")
utils.PrintStr(keyFn)
utils.PrintStr("\n")
} else {
utils.PrintStr("生成失败,")
utils.PrintStr(err.Error())
utils.PrintStr("\n")
}
}
func printSupportedProtocols() {
proxy.PrintAllServerNames()
proxy.PrintAllClientNames()
advLayer.PrintAllProtocolNames()
//todo: tlsLayer
}
// see https://dev.maxmind.com/geoip/geolite2-free-geolocation-data?lang=en
func tryDownloadMMDB() {
fp := utils.GetFilePath(netLayer.GeoipFileName)
if utils.FileExist(fp) {
return
}
fmt.Printf("No %s found,start downloading from %s\n", netLayer.GeoipFileName, netLayer.MMDB_DownloadLink)
var outClient proxy.Client
if mainM.DefaultClientUsable() {
outClient = mainM.DefaultOutClient
utils.PrintStr("trying to download mmdb through your proxy dial\n")
} else {
utils.PrintStr("trying to download mmdb directly\n")
}
var proxyUrl string
var listener io.Closer
if outClient != nil {
clientEndInServer, proxyurl, err := httpProxy.SetupTmpProxyServer()
if err != nil {
fmt.Println("can not create clientEndInServer: ", err)
return
}
listener = vs.ListenSer(clientEndInServer, outClient, nil, nil)
if listener != nil {
proxyUrl = proxyurl
defer listener.Close()
}
}
_, resp, err := utils.TryDownloadWithProxyUrl(proxyUrl, netLayer.MMDB_DownloadLink)
if err != nil {
fmt.Printf("Download mmdb failed %s\n", err.Error())
return
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
fmt.Printf("Download mmdb got bad status: %s\n", resp.Status)
return
}
out, err := os.Create(netLayer.GeoipFileName)
if err != nil {
fmt.Printf("Can Download mmdb but Can't Create File,%s \n", err.Error())
return
}
defer out.Close()
_, err = io.Copy(out, resp.Body)
if err != nil {
fmt.Printf("Write downloaded mmdb to file failed: %s\n", err.Error())
return
}
utils.PrintStr("Download mmdb success!\n")
}
// 试图从自己已经配置好的节点去下载geosite源码文件, 如果没有节点则直连下载。
// 我们只需要一个dial配置即可. listen我们不使用配置文件的配置,而是自行监听一个随机端口用于http代理
func tryDownloadGeositeSource() {
if netLayer.HasGeositeFolder() {
return
}
var outClient proxy.Client
if mainM.DefaultClientUsable() {
outClient = mainM.DefaultOutClient
utils.PrintStr("trying to download geosite through your proxy dial\n")
} else {
utils.PrintStr("trying to download geosite directly\n")
}
var proxyUrl string
var listener io.Closer
if outClient != nil {
clientEndInServer, proxyurl, err := httpProxy.SetupTmpProxyServer()
if err != nil {
fmt.Println("can not create clientEndInServer: ", err)
return
}
listener = vs.ListenSer(clientEndInServer, outClient, nil, nil)
if listener != nil {
proxyUrl = proxyurl
defer listener.Close()
}
}
netLayer.DownloadCommunity_DomainListFiles(proxyUrl)
}