极路由E30开启ssh

package main

import (
	"crypto/hmac"
	"crypto/sha1"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"hash"
	"io"
	"net"
	"net/http"
	"strconv"
	"strings"
	"time"
)

const (
	localTokenUrl = "/local-ssh/api?method=get"
	routerInfoUrl = "/cgi-bin/turbo/proxy/router_info"
	localSshUrl   = "/local-ssh/api?method=valid&data=%s"
)

const (
	retry       = 10
	sleepSecond = 10 * time.Second
)

type LocalTokenResp struct {
	Data string
}

type LocalSshResp struct {
	Data string
}

type RouterInfoResp struct {
	Data RouterInfoData
}

type RouterInfoData struct {
	Uuid string
}

var ErrorSystemBusy = errors.New("系统忙,请稍后重试")
var address = "192.168.199.1"

func main() {
	var input string
	var n int
	var ip net.IP
	var err error

	for {
		fmtPrint("请输入极路由管理IP,然后按回车继续(不输入则默认192.168.199.1): ")

		n, err = fmt.Scanln(&input)
		if err != nil && err.Error() != "unexpected newline" {
			fmtPrintFln("输入有误,请重新输入: %v", err)
			continue
		}

		if n == 0 {
			input = address
		}

		ip = net.ParseIP(input)
		if ip == nil {
			fmtPrintFln("输入非合法IP,请重新输入")
			continue
		}

		address = ip.String()
		fmtPrintFln("极路由IP为: %s", address)
		break
	}

	launchSsh()

	fmtPrint("按回车退出...")
	_, _ = fmt.Scanln(&input)
}

func launchSsh() {
	var localToken string
	var uuid string
	var cloudToken string
	var port string
	var err error

	for i := 0; i <= retry; i++ {
		if i != 0 {
			time.Sleep(sleepSecond)
			fmtPrintFln("----------------------------------------------------------------")
			fmtPrintFln("第%d次重试", i)
		}

		fmtPrintFln("开始获取UUID")
		uuid, err = getUUID()
		if err != nil {
			fmtPrintFln("获取uuid出错: %v", err)
			continue
		}
		fmtPrintFln("获取uuid成功: %s ", uuid)

		fmtPrintFln("开始获取local_token")
		localToken, err = getLocalToken()
		if err != nil {
			fmtPrintFln("获取local_token出错: %v", err)
			continue
		}
		fmtPrintFln("获取local_token成功: %s", localToken)

		fmtPrintFln("开始生成cloud_token")
		cloudToken, err = getCloudToken(uuid, localToken)
		if err != nil {
			fmtPrintFln("生成cloud_token出错: %v", err)
			continue
		}
		fmtPrintFln("生成cloud_token成功: %s", cloudToken)

		fmtPrintFln("开始获取local_ssh")
		port, err = getLocalSsh(cloudToken)
		if err != nil {
			fmtPrintFln("获取local_ssh出错: %v", err)
			continue
		}
		fmtPrintFln("获取local_ssh成功,端口号: %s,有效期5分钟,请及时更改为永久ssh", port)
		return
	}
	fmtPrintFln("获取local_ssh出错,请检查IP是否有误,UUID,LocalToken是否正常获取")
	fmtPrintFln("极路由IP为: %s", address)
	fmtPrintFln("UUID为: %s", uuid)
	fmtPrintFln("LocalToken为: %s", localToken)
	fmtPrintFln("CloudToken为: %s", cloudToken)
}

func getLocalSsh(cloudToken string) (port string, err error) {
	var osr *LocalSshResp
	osr = &LocalSshResp{}

	err = httpGet(generateUrl(localSshUrl, cloudToken), osr)
	if err != nil {
		return
	}

	if !strings.Contains(osr.Data, "Success: ssh port is ") {
		err = errors.New(fmt.Sprint("Unknown error:", osr.Data))
	}

	port = strings.ReplaceAll(osr.Data, "Success: ssh port is ", "")
	return
}

func getUUID() (uuid string, err error) {
	var rir *RouterInfoResp
	rir = &RouterInfoResp{}

	err = httpGet(generateUrl(routerInfoUrl), rir)
	if err != nil {
		return
	}

	uuid = rir.Data.Uuid
	return
}

func getLocalToken() (localToken string, err error) {
	var ltr *LocalTokenResp
	ltr = &LocalTokenResp{}

	err = httpGet(generateUrl(localTokenUrl), ltr)
	if err != nil {
		return
	}

	localToken = ltr.Data
	return
}

func getCloudToken(uuid, localToken string) (cloudToken string, err error) {
	var key [sha1.Size]byte
	var msg []byte
	var expectedMAC []byte

	msg, err = tokenToMsg(localToken)
	if err != nil {
		return
	}

	key = sha1Sum(uuid)
	expectedMAC = hmacSha1Sum(msg, key[:])
	cloudToken = base64.StdEncoding.EncodeToString(expectedMAC)

	return
}

func httpGet(url string, data interface{}) (err error) {
	var resp *http.Response
	var body []byte

	url = strings.ReplaceAll(url, "+", "%2B")

	resp, err = http.Get(url)
	if err != nil {
		return
	}

	body, err = io.ReadAll(resp.Body)
	if err != nil {
		return
	}

	if strings.Contains(string(body), "系统忙,请稍后重试") {
		err = ErrorSystemBusy
		return
	}

	err = json.Unmarshal(body, data)
	if err != nil {
		fmtPrintFln("json Unmarshal error: %s", string(body))
		return
	}

	return
}

func generateUrl(api string, a ...any) (url string) {
	api = fmt.Sprintf(api, a...)
	url = "http://" + address + api
	return
}

func tokenToMsg(localToken string) (msg []byte, err error) {
	var decodedLocalToken []byte
	var splitToken []string
	var timestamp int
	var msgStr string

	decodedLocalToken, err = base64.StdEncoding.DecodeString(localToken)
	if err != nil {
		return
	}
	splitToken = strings.Split(string(decodedLocalToken), ",")

	timestamp, err = strconv.Atoi(splitToken[2])
	if err != nil {
		return
	}

	timestamp += 1
	splitToken[2] = strconv.Itoa(timestamp)
	msgStr = strings.Join(splitToken[:3], ",")
	msg = []byte(msgStr)

	return
}

func sha1Sum(uuid string) (checksum [sha1.Size]byte) {
	var data []byte
	data = []byte(uuid)
	checksum = sha1.Sum(data)
	return
}

func hmacSha1Sum(msg, key []byte) (expectedMAC []byte) {
	var mac hash.Hash
	mac = hmac.New(sha1.New, key)
	mac.Write(msg)
	expectedMAC = mac.Sum(nil)
	return
}

func fmtPrintFln(format string, a ...any) {
	fmt.Printf(format, a...)
	fmt.Println()
}

func fmtPrint(a ...any) {
	fmt.Print(a...)
}

/usr/sbin/dropbear -P /var/run/dropbear.1.pid -p 22

ssh -o KexAlgorithms=+diffie-hellman-group1-sha1 -o HostKeyAlgorithms=+ssh-rsa root@192.168.199.1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值