1.4.5.2
This commit is contained in:
288
EdgePlus/pkg/utils/request_key.go
Normal file
288
EdgePlus/pkg/utils/request_key.go
Normal file
@@ -0,0 +1,288 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
stringutil "github.com/iwind/TeaGo/utils/string"
|
||||
"net"
|
||||
"os"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// RequestKey 申请码
|
||||
type RequestKey struct {
|
||||
MacAddresses []string `json:"macAddresses"` // MAC 排序后内容
|
||||
MachineId string `json:"machineId"` // /etc/machine-id
|
||||
HardwareUUID string `json:"hardwareUUID"` // hardware disk uuid
|
||||
}
|
||||
|
||||
// GenerateRequestKey 生成请求Key
|
||||
func GenerateRequestKey() (*RequestKey, error) {
|
||||
// mac addresses
|
||||
netInterfaces, err := findAllNetInterfaces()
|
||||
if err != nil {
|
||||
return nil, errors.New("could not generate request key (code: 001)")
|
||||
}
|
||||
|
||||
var macAddrs = []string{}
|
||||
for _, netInterface := range netInterfaces {
|
||||
var macAddr = strings.TrimSpace(netInterface.HardwareAddr.String())
|
||||
if len(macAddr) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
if !lists.ContainsString(macAddrs, macAddr) {
|
||||
macAddrs = append(macAddrs, macAddr)
|
||||
}
|
||||
}
|
||||
if len(macAddrs) == 0 {
|
||||
return nil, errors.New("could not generate request key (code: 002)")
|
||||
}
|
||||
sort.Strings(macAddrs)
|
||||
|
||||
// machine id
|
||||
var machineId = ""
|
||||
var machineIdFile = "/etc/machine-id"
|
||||
stat, err := os.Stat(machineIdFile)
|
||||
if err == nil && !stat.IsDir() {
|
||||
data, err := os.ReadFile(machineIdFile)
|
||||
data = bytes.TrimSpace(data)
|
||||
if err == nil && len(data) <= 32 {
|
||||
machineId = string(data)
|
||||
}
|
||||
}
|
||||
|
||||
return &RequestKey{
|
||||
MacAddresses: macAddrs,
|
||||
MachineId: machineId,
|
||||
HardwareUUID: generateHardwareUUID(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GenerateRequestCode 生成请求Key代码
|
||||
func GenerateRequestCode() (string, error) {
|
||||
key, err := GenerateRequestKey()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
keyJSON, err := json.Marshal(key)
|
||||
if err != nil {
|
||||
return "", errors.New("could not generate request code (code: 001)")
|
||||
}
|
||||
return Encode(keyJSON)
|
||||
}
|
||||
|
||||
// DecodeRequestCode 解析请求Key代码
|
||||
func DecodeRequestCode(requestCode string) (*RequestKey, error) {
|
||||
requestCode = regexp.MustCompile(`\s+`).ReplaceAllString(requestCode, "")
|
||||
|
||||
if requestCode == "*" {
|
||||
return &RequestKey{
|
||||
MacAddresses: nil,
|
||||
MachineId: "",
|
||||
}, nil
|
||||
}
|
||||
m, err := DecodeData([]byte(requestCode))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
jsonData, err := json.Marshal(m)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var key = &RequestKey{}
|
||||
err = json.Unmarshal(jsonData, key)
|
||||
return key, err
|
||||
}
|
||||
|
||||
// ValidateRequestCode 校验请求Key代码
|
||||
func ValidateRequestCode(requestCode string) (ok bool, errorCode string) {
|
||||
requestCode = regexp.MustCompile(`\s+`).ReplaceAllString(requestCode, "")
|
||||
|
||||
if requestCode == "*" {
|
||||
return true, ""
|
||||
}
|
||||
|
||||
key, err := DecodeRequestCode(requestCode)
|
||||
if err != nil {
|
||||
return false, "001"
|
||||
}
|
||||
|
||||
// check machine id
|
||||
if len(key.MachineId) > 0 {
|
||||
// machine id
|
||||
var machineId = ""
|
||||
var machineIdFile = "/etc/machine-id"
|
||||
stat, err := os.Stat(machineIdFile)
|
||||
if err == nil && !stat.IsDir() {
|
||||
data, err := os.ReadFile(machineIdFile)
|
||||
data = bytes.TrimSpace(data)
|
||||
if err == nil && len(data) <= 32 {
|
||||
machineId = string(data)
|
||||
}
|
||||
}
|
||||
if machineId != key.MachineId {
|
||||
return false, "004"
|
||||
}
|
||||
}
|
||||
|
||||
// hardware uuid
|
||||
if len(key.HardwareUUID) > 0 && key.HardwareUUID == generateHardwareUUID() {
|
||||
return true, ""
|
||||
}
|
||||
|
||||
// mac addresses
|
||||
netInterfaces, err := findAllNetInterfaces()
|
||||
if err != nil {
|
||||
return false, "002"
|
||||
}
|
||||
|
||||
// remove net interfaces related to docker
|
||||
{
|
||||
var cmd = NewTimeoutCmd(5*time.Second, "docker", "network", "ls")
|
||||
cmd.WithStdout()
|
||||
err = cmd.Run()
|
||||
if err == nil {
|
||||
var dockerIdRegexp = regexp.MustCompile(`^[0-9a-f]{12,}$`)
|
||||
var spaceRegexp = regexp.MustCompile(`\s+`)
|
||||
|
||||
var stdoutLines = strings.Split(cmd.Stdout(), "\n")
|
||||
var dockerInterfaceIds []string
|
||||
var dockerInterfaceNames []string
|
||||
for _, line := range stdoutLines {
|
||||
var pieces = spaceRegexp.Split(strings.TrimSpace(line), -1)
|
||||
if len(pieces) <= 3 {
|
||||
continue
|
||||
}
|
||||
var piece0 = strings.TrimSpace(pieces[0])
|
||||
if !dockerIdRegexp.MatchString(piece0) {
|
||||
continue
|
||||
}
|
||||
dockerInterfaceIds = append(dockerInterfaceIds, piece0)
|
||||
|
||||
var piece1 = strings.TrimSpace(pieces[1])
|
||||
if len(piece1) > 0 {
|
||||
dockerInterfaceNames = append(dockerInterfaceNames, piece1)
|
||||
}
|
||||
}
|
||||
|
||||
var newInterfaces []net.Interface
|
||||
for _, i := range netInterfaces {
|
||||
var skip bool
|
||||
for _, dockerInterfaceId := range dockerInterfaceIds {
|
||||
if strings.HasSuffix(i.Name, dockerInterfaceId) {
|
||||
skip = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !skip {
|
||||
skip = lists.ContainsString(dockerInterfaceNames, i.Name)
|
||||
}
|
||||
|
||||
if skip {
|
||||
continue
|
||||
}
|
||||
|
||||
newInterfaces = append(newInterfaces, i)
|
||||
}
|
||||
netInterfaces = newInterfaces
|
||||
}
|
||||
}
|
||||
|
||||
var allMACAddresses = []string{}
|
||||
for _, netInterface := range netInterfaces {
|
||||
var macAddr = strings.TrimSpace(netInterface.HardwareAddr.String())
|
||||
if len(macAddr) == 0 {
|
||||
continue
|
||||
}
|
||||
allMACAddresses = append(allMACAddresses, macAddr)
|
||||
}
|
||||
|
||||
// check mac addresses
|
||||
for _, macAddress := range allMACAddresses {
|
||||
if !lists.ContainsString(key.MacAddresses, macAddress) {
|
||||
return false, "003"
|
||||
}
|
||||
}
|
||||
|
||||
return true, ""
|
||||
}
|
||||
|
||||
func findAllNetInterfaces() ([]net.Interface, error) {
|
||||
interfaces, err := net.Interfaces()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var dockerReg = regexp.MustCompile(`^docker\d+$`)
|
||||
var resultInterfaces []net.Interface
|
||||
for _, i := range interfaces {
|
||||
if i.Flags&net.FlagLoopback == net.FlagLoopback {
|
||||
continue
|
||||
}
|
||||
|
||||
// ignore docker
|
||||
if dockerReg.MatchString(i.Name) {
|
||||
continue
|
||||
}
|
||||
|
||||
if i.Flags&net.FlagUp == net.FlagUp {
|
||||
resultInterfaces = append(resultInterfaces, i)
|
||||
}
|
||||
}
|
||||
|
||||
return resultInterfaces, nil
|
||||
}
|
||||
|
||||
func generateHardwareUUID() string {
|
||||
if runtime.GOOS != "linux" {
|
||||
return ""
|
||||
}
|
||||
|
||||
var diskUUID string
|
||||
{
|
||||
var cmd = NewCmd("ls", "/dev/disk/by-uuid")
|
||||
cmd.WithStdout()
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
var stdout = strings.TrimSpace(cmd.Stdout())
|
||||
if len(stdout) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
var pieces = regexp.MustCompile(`\s+`).Split(stdout, -1)
|
||||
sort.Strings(pieces)
|
||||
diskUUID = stringutil.Md5(strings.Join(pieces, "\n"))
|
||||
}
|
||||
|
||||
var hardwareUUID string
|
||||
{
|
||||
var cmd = NewCmd("dmidecode")
|
||||
cmd.WithStdout()
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
var stdout = strings.TrimSpace(cmd.Stdout())
|
||||
if len(stdout) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
hardwareUUID = stringutil.Md5(stdout)
|
||||
}
|
||||
|
||||
return stringutil.Md5(diskUUID + hardwareUUID)
|
||||
}
|
||||
Reference in New Issue
Block a user