golang实现远程控制主机

news2024/11/17 21:57:02

文章目录

  • ssh原理
  • 使用golang远程下发命令
  • 使用golang远程传输文件

ssh原理

说到ssh原理个人觉得解释最全的一张图是这张华为画的
在这里插入图片描述
Connection establishment
这一步就是建立tcp连接
version negotiation
这一步是ssh客户端(连接者)和被ssh服务端(连接者)进行协议的交换,比如ssh客户端支持那些加密协议,协商出最后使用的协议,还有就是协商ssh版本

Key Exchange
在说Key Exchange之前,我们要知道主机有2类的ssh-key分别是hostkey和user ssh key,每类key都分公钥和私钥,公钥可以加密,私钥可以解密

  • hostkey:

  • user ssh key:

首先hostkey,当ssh server安装的时候这个hostkey就会默认生成,在第一次连接对端的时候会显示的提醒我们叫我们确认时候继续连接如下

The authenticity of host '192.168.152.132 (192.168.152.132)' can't be established.
ECDSA key fingerprint is SHA256:MzAmI+qRcIEb0AS+6XMcAH5gtxnB779KpHRa1vOvAMs.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes	 

这是啥意思呢我们第一次连接ssh服务端,服务段会发送自己的hostkey的hash后的值给我们,我们如果选择yes,这段hash后的ssh服务端的hostkey被存入本地的.ssh/know_hosts中这是为了防止中间人攻击,有了这个hostkey之后,会使用diffie-hellman,这个算法用于为2端同时生成session key,因为diffie-hellman算法的特新session key必定相等,后续session建立后都会用这个session key进行加密传输

Key Authentication
随后是user ssh key,这个东西是用户用ssh-keygen生成的(也是ssh -i指定的identity_file]),当用户使用key认证而非密码认证的时候,这个就非常重要,ssh客户端将自己的public user ssh key发送给服务端(因为是session,用session可以进行加密),然后每当ssh客户端登录到服务端都会自己生成一个随机数用user 自己的userprivate key进行加密通过session传递给客户端,服务端再用接收客户端的公钥进行解密再发送回客户端,客户端进行check,是自己刚刚生成的key就发送验证成功的消息给服务端,最后验证通过,每当客户端向服务端进行数据传输都会使用之前的session key进行加密,服务段接收后用相同的session key进行解密

使用golang远程下发命令

package main

import (
        "fmt"
        "log"
        "os"

        "golang.org/x/crypto/ssh"
        "golang.org/x/crypto/ssh/knownhosts"
        //"golang.org/x/cryto/ssh"
)

func main() {
        //用于对方返回的key
        hostkey, err := knownhosts.New("/root/.ssh/known_hosts")
        if err != nil {
                log.Fatal("get knowhosts file error: %s", err.Error())
        }

        identify_file := "/root/.ssh/ansible"
        addr := "192.168.152.132:22"

        key, err := os.ReadFile(identify_file)
        if err != nil {
                log.Fatal("error,Can not Read file " + identify_file + " : " + err.Error())
        }

        //将私钥用PEM方式加密返回成签名
        signer, err := ssh.ParsePrivateKey(key)
        if err != nil {
                log.Fatal("unbale to parseprivatekey: ", err)
        }

        //设置连接peer时候的config
        config := &ssh.ClientConfig{
                User: "root",
                Auth: []ssh.AuthMethod{
                        ssh.PublicKeys(signer),
                },
                HostKeyCallback: hostkey,
        }

        //连接(key exchange,这里exhcange的是host key,用于认证session,而user key也就是自己手动生成的key用于验证用户)
        client, err := ssh.Dial("tcp", addr, config)
        if err != nil {
                log.Fatal("unable to connect: " + err.Error())
        }

        defer client.Close()

        session, err := client.NewSession()
        if err != nil {
                log.Fatal("new session error: %s", err.Error())
        }

        result, _ := session.Output("ip a")
        if err != nil {
                fmt.Fprintf(os.Stderr, "faile to run command, err:%s", err.Error())
        }

        fmt.Println(string(result))

}

代码非常简单,注意我们如果是第一次连接那么上述代码会执行失败,因为第一次连接,ssh server要返回自己的hostkey给客户端(我们执行代码的机器),客户端要在自己的know_host里面check,但是第一次连接know_host没有数据就会失败,所以可以将代码改成不安全的模式,也就是不check know_host,方法也很简单,就是将连接时候的config的HostKeyCallback对应的值改为ssh.InsecureIgnoreHostKey()如下

package main

import (
        "fmt"
        "log"
        "os"

        "golang.org/x/crypto/ssh"
        //"golang.org/x/crypto/ssh/knownhosts"
        //"golang.org/x/cryto/ssh"
)

func main() {
        //用于对方返回的key
        //hostkey, err := knownhosts.New("/root/.ssh/known_hosts")
        //if err != nil {
        //      log.Fatal("get knowhosts file error: %s", err.Error())
        //}

        identify_file := "/root/.ssh/ansible"
        addr := "192.168.152.132:22"

        key, err := os.ReadFile(identify_file)
        if err != nil {
                log.Fatal("error,Can not Read file " + identify_file + " : " + err.Error())
        }

        //将私钥用PEM方式加密返回成签名
        signer, err := ssh.ParsePrivateKey(key)
        if err != nil {
                log.Fatal("unbale to parseprivatekey: ", err)
        }

        //设置连接peer时候的config
        config := &ssh.ClientConfig{
                User: "root",
                Auth: []ssh.AuthMethod{
                        ssh.PublicKeys(signer),
                },
                HostKeyCallback: ssh.InsecureIgnoreHostKey(),
        }

        //连接(key exchange,这里exhcange的是host key,用于认证session,而user key也就是自己手动生成的key用于验证用户)
        client, err := ssh.Dial("tcp", addr, config)
        if err != nil {
                log.Fatal("unable to connect: " + err.Error())
        }

        defer client.Close()

        session, err := client.NewSession()
        if err != nil {
                log.Fatal("new session error: %s", err.Error())
        }

        result, _ := session.Output("ip a")
        if err != nil {
                fmt.Fprintf(os.Stderr, "faile to run command, err:%s", err.Error())
        }

        fmt.Println(string(result))

}

最后打印出结果

root@master:~/demo/ssh# ./ssh
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:7e:76:1b brd ff:ff:ff:ff:ff:ff
    altname enp2s0
    inet 192.168.152.132/24 brd 192.168.152.255 scope global noprefixroute ens32
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe7e:761b/64 scope link
       valid_lft forever preferred_lft forever

使用golang远程传输文件

在代码之前,我们要了解2个小的知识点

  • scp -t的用途
  • 文件形式

首先scp -t这个选项不管是man还是其他的公开官方资料中都很难找到其身影,我们先运行看是在干嘛

root@slaver1:/test# scp -t .


输入后就卡着不动,因为这个时候scp的程序在等待远端的scp程序通过tcp的22号端口向他发送文件…
所以scp -t是通过端口接收文件用的

在说一个文件的格式,一个文件开头第一行标记了文件的信息,比如权限,比如大小,比如文件名,后面的才是内容,最后以\x000结尾,所以我们传递的时候最好使用管道,先传递文件原信息,再传递文件的内容,最后传递\x000表示结尾,直接看代码

package main
import (
	"bytes"
	"fmt"
	"io"
	"log"
	"os"
	"sync"

	"golang.org/x/crypto/ssh"
)

func main(){
	identify_file := "/root/.ssh/ansible"
	addr := "192.168.152.132:22"
	key, _ := os.ReadFile(identify_file)
	signer, _ := ssh.ParsePrivateKey(key) //用协商出来的动态session key进行加密
	config := &ssh.ClientConfig{
		User: "root",
		Auth: []ssh.AuthMethod{
			ssh.PublicKeys(signer),
		},
		HostKeyCallback: ssh.InsecureIgnoreHostKey(),
	}

	client, _ := ssh.Dial("tcp", addr, config)
	defer client.Close()

	session, _ := client.NewSession()
	defer session.Close()

	file, _ := os.Open("apply.sh")
	defer file.Close()
	stat, _ := file.Stat()

	wg := sync.WaitGroup{}
	wg.Add(1)

	go func() {
		hostIn, _ := session.StdinPipe()
		defer hostIn.Close()
		fmt.Fprintf(hostIn, "C0655 %d %s\n", stat.Size(), "apply.sh")//第一行输入文件元数据
		io.Copy(hostIn, file)	//copy 文件内容
		fmt.Fprint(hostIn, "\x000") //表示结束
		wg.Done()
	}()

	session.Run("/usr/bin/scp -t /test")
	wg.Wait()

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1025465.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

湖南长沙石雕石质文物三维扫描数字化雕刻3D打印复刻文化遗产-CASAIM中科广电

石质文物主要包括石雕、石塔和古建筑等&#xff0c;颇具代表性的雕刻动物作品有&#xff1a;龙、凤、狮子、麒麟、貔貅、金蟾等。石雕是我国文化遗产的重要组成&#xff0c;在书写灿烂文明中扮演着重要角色&#xff0c;记载了我国文化和历史的变迁。 随着现代艺术的发展&#…

vscode快捷键大全中英文

vscode快捷键大全中英文 源文件下载链接

700多心理测试性格测试大全ACCESS\EXCEL数据库

这是一个关于心理测试、性格测试的ACCESS数据库&#xff0c;这个测试有一个测试项目一个问题选择后就有结果&#xff0c;也有一个测试项目有N多题需做完N多题根据各题得分得出总结果&#xff0c;所以ACCESS数据表的结构设计的很灵活。 测试项目表&#xff1a;为整个ACCESS数据…

DDoS攻击和CC攻击

DDoS是&#xff08;Distributed Denial of Service&#xff0c;分布式拒绝服务&#xff09;攻击和CC&#xff08;Challenge Collapsar&#xff0c;挑战黑洞) 攻击是两种常见且具有破坏性的攻击类型&#xff0c;它们可以对网络基础设施和在线业务造成重大损害。为了抵御这些攻击…

vscode编写前端提升效率的三个必不可缺的插件以及使用方法

直接官网下载这个软件就行&#xff0c;没什么操作的。 这里面有新建文件夹&#xff0c;你可以自己去建一个文件夹 然后点击那个小号&#xff0c;就可以新建一个文件&#xff0c;比如说demo01.html,⚠️后面的html是你需要自己手动输入的 第一个插件&#xff0c;就是这个她可以让…

Android 虚拟机

文章目录 Android 虚拟机Java虚拟机基于栈的虚拟机栈的执行流程 Dalvik虚拟机基于寄存器的虚拟机寄存器的执行流程Java虚拟机与Dalvik虚拟机区别 ART虚拟机Android 7.0的运行方式 Android 虚拟机 Java虚拟机 基于栈的虚拟机 每一个运行时的线程&#xff0c;都有一个独立的栈…

包装类型和基本类型的转换(自动装箱/自动拆箱)

①包装类型->基本类型 ②基本类型->包装类型 //第一种&#xff1a;直接创建对象Integer ynew Integer(20);//第二种&#xff1a;使用Integer类的静态方法valueOf()Integer zInteger.valueOf(30); JAVA对以上内容的简化&#xff1a; 自动装箱&#xff08;基本类型->包…

嵌入式C语言知识复习和提高

文章目录 前言基础知识main函数防BUG注释&#xff08;重要&#xff09;关键字标识符命名&#xff08;驼峰命名&#xff09;常量类型变量printf1.输出不同类型数据2.输出不同宽度数据3.不同类型数据长度归类 scanf函数运算符sizeof&#xff08;运算符&#xff0c;优先级2&#x…

Springboot ruoyi配置mysql备份定时任务

一、RuoYiConfig.class 新增获取备份路径方法 public static String getDataBaseBackUp() {return getProfile() "/dbBackUp";} 二、RyTask&#xff1a;新增备份数据库方法 mySqlDump方法&#xff1a;参数详见代码 package com.ruoyi.quartz.task;import cn.hut…

智慧工地4G+蓝牙+GPS/北斗RTK人员定位系统解决方案

工地是事故多发地&#xff0c;对工地人员进行定位管理非常有必要。传统工地管理手段存在局限性&#xff0c;往往难以高效地管理工地上的人员。随着科技的发展&#xff0c;工地人员定位管理系统逐渐普及。通过使用人员定位系统&#xff0c;工地管理者可以对工地上的人员进行全面…

对权限的理解和使用

目录 一&#xff1a;用户权限&#xff1a; ★su命令 ★sudo命令 二&#xff1a;文件权限 ★文件的类型权限 ★文件夹的权限的使用 ▲文件夹的可读权限&#xff1a; ▲文件夹的可写权限&#xff1a; ▲文件夹的可执行权限&#xff1a; ★权限的修改操作 ▲chmod命令 ★对于文件的…

C++:deque的概念以及stack和queue的模拟实现

文章目录 stack的模拟实现dequequeue的模拟实现 本篇主要总结的是stack和queue的模拟实现以及deque的原理 stack的模拟实现 和前面的模拟实现相同&#xff0c;首先要看官方实现的功能 这里引入了Container的概念&#xff0c;从字面意思来看&#xff0c;也就是说&#xff0c;在…

pdf转换成word,这里有几个不错的方法

pdf转换成word怎么转&#xff1f;大家都知道&#xff0c;在电脑进行各种文件格式转换中&#xff0c;PDF转换为Word文档的需求量应该是最大的。在我们的日常工作中&#xff0c;经常需要将PDF转换为Word格式。为什么要将pdf文件转换成word&#xff0c;相信大家也都应该知道的&…

图解 | 这就是网络

你是一台电脑&#xff0c;你的名字叫 A 很久很久之前&#xff0c;你不与任何其他电脑相连接&#xff0c;孤苦伶仃。 直到有一天&#xff0c;你希望与另一台电脑 B 建立通信&#xff0c;于是你们各开了一个网口&#xff0c;用一根网线连接了起来。 用一根网线连接起来怎么就能&q…

二叉树链式结构基础

一、前中后序遍历 1、前序遍历&#xff1a;前序遍历是采用 根 - 左子树 - 右子树 的顺序遍历二叉树。 也就是把整棵树分为一个个子问题&#xff0c;每个结点都可以看作 根、左子树、右子树 三个部分 (左右子树可以为空&#xff0c;就是单节点&#xff0c;根为空就表示探索完成&…

自动化测试需知的4项测试工具!

一般来说学自动化会建议大家先学selenium&#xff0c;因为最早的时候&#xff0c;自动化就代表selenium&#xff0c;进入测试行业就开始做接口测试&#xff0c;而且现在基本每个公司都需要接口测试。今天就和大家聊一下接口测试的工具。 一、Robot Framework 机器人框架。之所…

利用证书给pdf文件添加数字签名

文章目录 给pdf文件签名文件准备构建印章获取证书方法一 阿里云申请证书方法二 自建证书 利用证书给pdf签名在指定位置签名在指定坐标签名在指定签名域签名 给pdf文件签名 如何给pdf文件签名&#xff0c;这样pdf文件就具有不可修改性&#xff0c;具有鉴权、完整性、不可抵赖。…

【操作系统笔记】内存寻址

物理寻址 主存&#xff08;内存&#xff09; 计算机主存也可以称为物理内存&#xff0c;内存可以看成由若干个连续字节大小的单元组成的数组每个字节都有一个唯一的物理地址&#xff08;Physical Address&#xff09;CPU访问内存前&#xff0c;先拿到内存地址&#xff0c;然后…

通讯网关软件005——利用CommGate X2OPC实现OPC客户端访问MS SQL服务器

本文推荐利用CommGate X2OPC实现OPC客户端访问MS SQL服务器获取数据。CommGate X2OPC是宁波科安网信开发的网关软件&#xff0c;软件可以登录到网信智汇(http://wangxinzhihui.com)下载。 【案例】如下图所示&#xff0c;上位机通过OPC Client软件来获取MS SQL数据库的数据。 …

Qt扩展-KDDockWidgets 简介及配置

Qt扩展-KDDockWidgets 简介及配置] 一、概述二、编译 KDDockWidgets 库1. Cmake Gui 中选择源文件和编译后的路径2. 点击Config&#xff0c;配置好编译器3. 点击Generate4. 在存放编译的文件夹输入如下命令开始编译 三、qmake 配置 一、概述 kdockwidgets是一个由KDAB组织编写…