mirror of
https://github.com/chenjia404/p2ptunnel.git
synced 2025-09-26 19:41:10 +08:00
0.0.9:支持从GitHub更新
This commit is contained in:
@@ -26,6 +26,7 @@
|
||||
|id | multiaddr格式的 | 连接远程服务id|
|
||||
|p2p_port|ip端口 |p2p使用的端口,也是监听其它节点连接的端口,默认4001,会自动进行nat,但是可能需要您进行端口映射|
|
||||
|type|网络类型|tcp或者udp|
|
||||
|update|bool|是否检查更新|
|
||||
|
||||
### id格式(multiaddr)
|
||||
| 类型 | 样例|说明 |
|
||||
|
9
main.go
9
main.go
@@ -7,6 +7,7 @@ import (
|
||||
"runtime"
|
||||
|
||||
"github.com/chenjia404/p2ptunnel/p2pforwarder"
|
||||
"github.com/chenjia404/p2ptunnel/update"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -18,7 +19,7 @@ var (
|
||||
)
|
||||
|
||||
var (
|
||||
version = "0.0.8"
|
||||
version = "0.0.9"
|
||||
gitRev = ""
|
||||
buildTime = ""
|
||||
)
|
||||
@@ -35,10 +36,16 @@ func main() {
|
||||
id := flag.String("id", "", "Destination multiaddr id string")
|
||||
p2p_port := flag.Int("p2p_port", 4001, "p2p use port")
|
||||
networkType := flag.String("type", "tcp", "network type tcp/udp")
|
||||
var flag_update = flag.Bool("update", false, "update form github")
|
||||
flag.Parse()
|
||||
|
||||
var err error
|
||||
|
||||
if *flag_update {
|
||||
update.CheckGithubVersion(version)
|
||||
return
|
||||
}
|
||||
|
||||
fwr, fwrCancel, err = p2pforwarder.NewForwarder(*p2p_port)
|
||||
if err != nil {
|
||||
log.Panicln(err)
|
||||
|
398
update/update.go
Normal file
398
update/update.go
Normal file
@@ -0,0 +1,398 @@
|
||||
package update
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"archive/zip"
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"crypto/sha512"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/polydawn/refmt/json"
|
||||
"golang.org/x/crypto/openpgp"
|
||||
)
|
||||
|
||||
func CheckGithubVersion(Version string) {
|
||||
githubName := "chenjia404"
|
||||
githubPath := "chenjia404/p2ptunnel"
|
||||
|
||||
archivesFormat := "tar.gz"
|
||||
if runtime.GOOS == "windows" {
|
||||
archivesFormat = "zip"
|
||||
}
|
||||
|
||||
r, err := http.Get(fmt.Sprintf("https://api.github.com/repos/%s/releases/latest", githubPath))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
b, err := io.ReadAll(r.Body)
|
||||
var v interface{}
|
||||
err = json.Unmarshal(b, &v)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
data := v.(map[string]interface{})
|
||||
|
||||
githubVerion := fmt.Sprintf("%s", data["tag_name"])
|
||||
githubVerion = strings.Replace(githubVerion, "v", "", 1)
|
||||
if compareVersion(githubVerion, Version) > 0 {
|
||||
fmt.Println("GitHub版本更高")
|
||||
} else {
|
||||
fmt.Println("不需要升级")
|
||||
return
|
||||
}
|
||||
|
||||
githubPublishedTime, _ := time.ParseInLocation("2006-01-02T15:04:05Z", fmt.Sprintf("%s", data["published_at"]), time.Local)
|
||||
if time.Now().Sub(githubPublishedTime) < (time.Second * 3600) {
|
||||
fmt.Println("更新时间不足1个小时,延迟更新")
|
||||
return
|
||||
}
|
||||
updateFileUrl := fmt.Sprintf("https://github.com/%s/releases/download/v%s/%s_%s_%s_%s.%s", githubPath, githubVerion, githubName, githubVerion, runtime.GOOS, runtime.GOARCH, archivesFormat)
|
||||
// Get the data
|
||||
resp, err := http.Get(updateFileUrl)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
if resp.StatusCode == 404 {
|
||||
fmt.Println("文件不存在,404错误" + updateFileUrl)
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// 创建一个文件用于保存
|
||||
out, err := os.Create("update." + archivesFormat)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
// 然后将响应流和文件流对接起来
|
||||
_, err = io.Copy(out, resp.Body)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
} else {
|
||||
fmt.Println("下载最新安装包成功")
|
||||
}
|
||||
|
||||
out, err = os.Open("update." + archivesFormat)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
h := sha512.New()
|
||||
if _, err := io.Copy(h, out); err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
fileSha512 := hex.EncodeToString(h.Sum(nil))
|
||||
|
||||
checksumsFileURL := fmt.Sprintf("https://github.com/%s/releases/download/v%s/checksums.txt", githubPath, githubVerion)
|
||||
r, err = http.Get(checksumsFileURL)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
b, err = io.ReadAll(r.Body)
|
||||
checksums := string(b)
|
||||
if strings.Index(checksums, fileSha512) < 0 {
|
||||
|
||||
fmt.Println("文件sha512错误" + fileSha512)
|
||||
return
|
||||
}
|
||||
|
||||
ascFileURL := fmt.Sprintf("https://github.com/%s/releases/download/v%s/%s_%s_%s_%s.%s.asc", githubPath, githubVerion, githubName, githubVerion, runtime.GOOS, runtime.GOARCH, archivesFormat)
|
||||
err = DownloadFile(ascFileURL, fmt.Sprintf("update.%s.asc", archivesFormat))
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
Verify, err := VerifySignature(fmt.Sprintf("update.%s", archivesFormat))
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
if !Verify {
|
||||
fmt.Println("gpg签名不通过")
|
||||
return
|
||||
}
|
||||
|
||||
exeFilename, _ := os.Executable()
|
||||
|
||||
//删除老文件
|
||||
if FileExists(path.Base(exeFilename) + ".old") {
|
||||
err = os.Remove(path.Base(exeFilename) + ".old")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
err = os.Rename(path.Base(exeFilename), path.Base(exeFilename)+".old")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
if archivesFormat == "zip" {
|
||||
|
||||
err = Unzip(fmt.Sprintf("update.%s", archivesFormat), ".")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
err = UnTarGz(fmt.Sprintf("update.%s", archivesFormat), "")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("current version: ", Version)
|
||||
fmt.Println("Update to version: ", githubVerion)
|
||||
fmt.Println("Ready to restart")
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
func Unzip(zipPath, dstDir string) error {
|
||||
// open zip file
|
||||
reader, err := zip.OpenReader(zipPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer reader.Close()
|
||||
for _, file := range reader.File {
|
||||
if err := unzipFile(file, dstDir); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func UnTarGz(tarFile, dest string) error {
|
||||
srcFile, err := os.Open(tarFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer srcFile.Close()
|
||||
gr, err := gzip.NewReader(srcFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer gr.Close()
|
||||
tr := tar.NewReader(gr)
|
||||
for {
|
||||
hdr, err := tr.Next()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if hdr.Typeflag != tar.TypeDir {
|
||||
|
||||
filename := dest + hdr.Name
|
||||
file, err := createFile(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
io.Copy(file, tr)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func createFile(name string) (*os.File, error) {
|
||||
if strings.LastIndex(name, "/") >= 0 {
|
||||
|
||||
err := os.MkdirAll(string([]rune(name)[0:strings.LastIndex(name, "/")]), 0755)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return os.Create(name)
|
||||
}
|
||||
|
||||
func unzipFile(file *zip.File, dstDir string) error {
|
||||
// create the directory of file
|
||||
filePath := path.Join(dstDir, file.Name)
|
||||
if file.FileInfo().IsDir() {
|
||||
if err := os.MkdirAll(filePath, os.ModePerm); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if err := os.MkdirAll(filepath.Dir(filePath), os.ModePerm); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// open the file
|
||||
rc, err := file.Open()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer rc.Close()
|
||||
|
||||
// create the file
|
||||
w, err := os.Create(filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer w.Close()
|
||||
|
||||
w.Chmod(0777)
|
||||
|
||||
// save the decompressed file content
|
||||
_, err = io.Copy(w, rc)
|
||||
return err
|
||||
}
|
||||
|
||||
func compareVersion(version1 string, version2 string) int {
|
||||
var res int
|
||||
ver1Strs := strings.Split(version1, ".")
|
||||
ver2Strs := strings.Split(version2, ".")
|
||||
ver1Len := len(ver1Strs)
|
||||
ver2Len := len(ver2Strs)
|
||||
verLen := ver1Len
|
||||
if len(ver1Strs) < len(ver2Strs) {
|
||||
verLen = ver2Len
|
||||
}
|
||||
for i := 0; i < verLen; i++ {
|
||||
var ver1Int, ver2Int int
|
||||
if i < ver1Len {
|
||||
ver1Int, _ = strconv.Atoi(ver1Strs[i])
|
||||
}
|
||||
if i < ver2Len {
|
||||
ver2Int, _ = strconv.Atoi(ver2Strs[i])
|
||||
}
|
||||
if ver1Int < ver2Int {
|
||||
res = -1
|
||||
break
|
||||
}
|
||||
if ver1Int > ver2Int {
|
||||
res = 1
|
||||
break
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func DownloadFile(url string, dest string) error {
|
||||
// Get the data
|
||||
resp, err := http.Get(url)
|
||||
|
||||
if resp.StatusCode == 404 {
|
||||
fmt.Println("文件不存在,404错误" + url)
|
||||
return http.ErrMissingFile
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// 创建一个文件用于保存
|
||||
out, err := os.Create(dest)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
_, err = io.Copy(out, resp.Body)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return err
|
||||
} else {
|
||||
fmt.Println("签名文件下载成功")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var publicKey = `-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
mQINBGRVILgBEACxqkRKodS2Mfxn6GTYvUDaBSgQCjT/GMqmto38buSing9PCXv6
|
||||
QMWko8Ax7cKVkxEKGD+4T+AD2mLfhpjLBlMOcxqBwuJ4YVsWkHH2TLHc/gU3DL9Y
|
||||
ajH9Lt8TF+Xin/pBfGdOBXGeKK2Az8RshK5D3w3E89//plL15kaR0BWbVIp6Ne0P
|
||||
c5D7BNboRuqJGAY+aYEipWAHLZW5M2dD1wgVjUpZRwWv+qIKuQ+hri+fxehFjz3S
|
||||
8ElwqZu8JQHxcO3b3m3j11x1qfekqRvNf/dxMpuS+ymenAjOmDDlarmSTj9RTzrA
|
||||
97uYi2meIr5e85yMNk5n8Ks7HOQyQ1K6J7YBodjItO7bp1EE5xSecNsaIT2kBQX3
|
||||
0+uga0IsZkA6MIC8caWfkMIXrdyLse4XFywCdOGI3BhrA6QV/7ZAXRBs5HtO6SQO
|
||||
eVfDptZ0VCvmWG8v6d5mBJ6081FylHEoDYXfJVwgRo71UR334WBpRJZQNV76p383
|
||||
muUSq05IcwjbAdyol26enqO2s5LRNs7OeISAhQ+u2LV6LJK+G23JKbmIuWD7Rhol
|
||||
gLDXYukoIlOcY7x++qnqoLT8V1aNFE/4XDAd+/Xq7VdgvKbPZxxEkXj9LMrPBIaS
|
||||
9/1Nmiq/ni779pnGCFDS7UUFLJvWjEDgWKnZb8MYBdyvq9T9biecJ2oR6wARAQAB
|
||||
tCJjaGVuamlhNDA0IDxjaGVuamlhYmxvZ0BnbWFpbC5jb20+iQJXBBMBCABBFiEE
|
||||
4TRiUu1mI2TKN/cWGJvnloM2naMFAmRVILgCGw8FCQPDFwgFCwkIBwICIgIGFQoJ
|
||||
CAsCBBYCAwECHgcCF4AACgkQGJvnloM2naMQJA/+OxZGpywGLf+C1Wi9iVsSb0UA
|
||||
Xit9yOujEpgttgJBdZcfP/1W5G7Vlt9pEH1ByJ28RHlSrEdMkycYhmvnDPdCTg+c
|
||||
x3NtjWP8xWXsWN9upPPnn3ZdtsSDZ2YQOMjunP7mucRW8NofDFytPFgSVb6+NcqM
|
||||
9Obcd6gmOY3qoQcv4XofdlP6ObFZxvr/mGKdSBgWgOQivGK8QtimNeC/V5ChJKyl
|
||||
rueQJ1RRnGtlTXW3tNPNmYkXeVR/TVZgVHyIBHjlNHRV7V8Wgm+vsNIo7xPD/PHL
|
||||
3Kq2pmuz8EpcJpNK1+IYsQJTEx9+Y4E4Vjjp/U6WBjGDWXF5KrdTKMsRsHvhxOW7
|
||||
C/u6e9gG/eHPLo5Pw3Dg5MWZh/+dRZ/1kWoKhabp719CCPOh9SBgUdSc8RAoVTwp
|
||||
b/UHSPokJPPlpBWU7mdBJ+fCapswHU8Gg4WnwBrm2C+p7GEXZiJ6f5n2Ic9rVu6x
|
||||
mkmOANLziPe7kC8T6830d0l2nlyCR/oKoGrQ8+bQNChHHhGWtr4O/uCrES5NK/Xr
|
||||
kT6OojW8UeV5ngFa0fFurYcMahHHaoy/S3bduGMk3yiFI8Wh7LkZQO6ugkoesvqv
|
||||
YSCJJrSTjHnBCkddmOHpDpvgOe+COOrVCe42PNSovTJ+14rhMTsYOWShLLOdC02L
|
||||
/xTrrn8LrU9TVEUWf4I=
|
||||
=l1Ub
|
||||
-----END PGP PUBLIC KEY BLOCK-----`
|
||||
|
||||
func VerifySignature(filename string) (bool, error) {
|
||||
keyring, err := openpgp.ReadArmoredKeyRing(bytes.NewReader([]byte(publicKey)))
|
||||
if err != nil {
|
||||
fmt.Println("Read Armored Key Ring: " + err.Error())
|
||||
return false, err
|
||||
}
|
||||
|
||||
signature, err := os.Open(filename + ".asc")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
verificationTarget, err := os.Open(filename)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return false, err
|
||||
}
|
||||
entity, err := openpgp.CheckArmoredDetachedSignature(keyring, verificationTarget, signature)
|
||||
if err != nil {
|
||||
fmt.Println("Check Detached Signature: " + err.Error())
|
||||
return false, err
|
||||
}
|
||||
if entity.PrimaryKey.KeyIdString() == "189BE79683369DA3" {
|
||||
return true, nil
|
||||
} else {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func FileExists(path string) bool {
|
||||
_, err := os.Stat(path) //os.Stat获取文件信息
|
||||
if err != nil {
|
||||
if os.IsExist(err) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
Reference in New Issue
Block a user