开放自动化与信息安全

   OT 安全和IEC62443标准

     与IT相比,工业控制系统(ICS)的安全性也称为OT安全性,它始于诸如电力,天然气和水等关键基础设施。随着向开放系统的发展以及与IIoT工业4.0趋势一致的威胁变化,各个领域的工作正全面展开。据说Stuxnet在2010年成为了全球触发者。在过去的十年中,各个国家和行业都积极制定了指南和框架,但是它们似乎缺乏连贯性。最近,已经整合了多个指南,可以说作为全球标准的两个引人注目的标准是IEC62443。从智能工厂的安全性角度来看,还有NIST CSF,SP800系列。

    IEC 62443。这个标准是ISA99和IEC委员会共同开发的。IEC62443是一组14个文档,提供了通用工业控制系统(IACS:在本标准中称为工业自动化控制系统)的安全技术规范。该标准是由国际自动化学会(ISA)和国际电工委员会(IEC)制定的,迄今为止已发布14个文档中的8个,并且正在进行修订和开发。我粗略地看了一下,好像蛮复杂的样子。

信息安全的基本知识

         结合IEC61499 分布式功能块技术,最近通过协议分析,发现施耐德公司EAE 中底层协议使用了websocket,hash 摘要和加密数据等。估计EAE采用的还是相对简单的,hash 数字摘要+AES对称加密,是否有证书机制,没有看出来。AES 的加密key 也不知道。按说,作为一个开放性系统,加密方式也需要Open 的。要不然,不同厂商额设备和软件工具无法兼容。

在这里,了解一些关于openSSL,TLS 基本的信息安全技术。为IEC61499 安全平台做一些准备工作。

信息安全问题

在信息安全性问题中,我们常常要做到三点才能保证信息的安全:

  1. 信息的保密性
  2. 信息的完整性
  3. 身份识别

 

SSL(Secure Socket Layer)代表安全套接字层,TLS(Transport Layer Security)代表传输层安全性。安全套接字层和传输层安全性都是用于在Web浏览器和Web服务器之间提供安全性的协议。

 

三项基础技术

散列函数Hash
    常见的有 MD5、SHA1、SHA256,该类函数特点是函数单向不可逆、对输入非常敏感、输出长度固定,针对数据的任何修改都会改变散列函数的结果,用于防止信息篡改并验证数据的完整性;
    在信息传输过程中,散列函数不能单独实现信息防篡改,因为明文传输,中间人可以修改信息之后重新计算信息摘要,因此需要对传输的信息以及信息摘要进行加密;

hash 函数产生的hash 值称为文本的数字摘要。如果接收端计算出来的数字摘要和发送端发送来的数字摘要是一致的,说明数据是完整的没有被修改。这有点类似于CRC 校验码,只是当文本很长的时候,简单地使用CRC 码无法完全判断文本是否完整。

Go 程序

package main
import "crypto/sha1"
import "fmt"
func main() {
    s := "Hello 8gwifi.org"
    // The pattern for generating a hash is `sha1.New()`,
    // `sha1.Write(bytes)`, then `sha1.Sum([]byte{})`.
    // Here we start with a new hash.
    h := sha1.New()
    
    // `Write` expects bytes. If you have a string `s`,
    // use `[]byte(s)` to coerce it to bytes.
    h.Write([]byte(s))

    // This gets the finalized hash result as a byte
    // slice. The argument to `Sum` can be used to append
    // to an existing byte slice: it usually isn't needed.
    bs := h.Sum(nil)

    // SHA1 values are often printed in hex, for example
    // in git commits. Use the `%x` format verb to convert
    // a hash results to a hex string.
    fmt.Println(s)
    fmt.Printf("%x\n", bs)
}

对称加密
    常见的有 AES-CBC、DES、3DES、AES-GCM等,相同的密钥可以用于信息的加密和解密,掌握密钥才能获取信息,能够防止信息窃听,通信方式是1对1;
    对称加密的优势是信息传输1对1,需要共享相同的密码,密码的安全是保证信息安全的基础,服务器和 N 个客户端通信,需要维持 N 个密码记录,且缺少修改密码的机制;

对称加密的例子,参考下列地址

Go Encryption and Decryption using AES - Tutorial

加密程序

package main

import (
    "crypto/aes"
    "crypto/cipher"
    "crypto/rand"
    "fmt"
	"io/ioutil"
	"io"
)
func main() {
    fmt.Println("Encryption Program v0.01")

    text := []byte("My Super Secret Code Stuff")
    key := []byte("passphrasewhichneedstobe32bytes!")

    // generate a new aes cipher using our 32 byte long key
    c, err := aes.NewCipher(key)
    // if there are any errors, handle them
    if err != nil {
        fmt.Println(err)
    }

    // gcm or Galois/Counter Mode, is a mode of operation
    // for symmetric key cryptographic block ciphers
    // - https://en.wikipedia.org/wiki/Galois/Counter_Mode
    gcm, err := cipher.NewGCM(c)
    // if any error generating new GCM
    // handle them
    if err != nil {
        fmt.Println(err)
    }

    // creates a new byte array the size of the nonce
    // which must be passed to Seal
    nonce := make([]byte, gcm.NonceSize())
    // populates our nonce with a cryptographically secure
    // random sequence
    if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
        fmt.Println(err)
    }

    // here we encrypt our text using the Seal function
    // Seal encrypts and authenticates plaintext, authenticates the
    // additional data and appends the result to dst, returning the updated
    // slice. The nonce must be NonceSize() bytes long and unique for all
    // time, for a given key.
	fmt.Println(gcm.Seal(nonce, nonce, text, nil))
	// the WriteFile method returns an error if unsuccessful
    err = ioutil.WriteFile("myfile.data", gcm.Seal(nonce, nonce, text, nil), 0777)
// handle this error
   if err != nil {
  // print it out
  fmt.Println(err)
}
}

解密程序

package main

import (
    "crypto/aes"
    "crypto/cipher"
    "fmt"
    "io/ioutil"
)

func main() {
    fmt.Println("Decryption Program v0.01")

    key := []byte("passphrasewhichneedstobe32bytes!")
    ciphertext, err := ioutil.ReadFile("./myfile.data")
    // if our program was unable to read the file
    // print out the reason why it can't
    if err != nil {
        fmt.Println(err)
    }

    c, err := aes.NewCipher(key)
    if err != nil {
        fmt.Println(err)
    }

    gcm, err := cipher.NewGCM(c)
    if err != nil {
        fmt.Println(err)
    }

    nonceSize := gcm.NonceSize()
    if len(ciphertext) < nonceSize {
        fmt.Println(err)
    }

    nonce, ciphertext := ciphertext[:nonceSize], ciphertext[nonceSize:]
    plaintext, err := gcm.Open(nil, nonce, ciphertext, nil)
    if err != nil {
        fmt.Println(err)
    }
    fmt.Println(string(plaintext))
}


非对称加密
    即常见的 RSA 算法,还包括 ECC、DH 等算法,算法特点是,密钥成对出现,一般称为公钥(公开)和私钥(保密),公钥加密的信息只能私钥解开,私钥加密的信息只能公钥解开。因此掌握公钥的不同客户端之间不能互相解密信息,只能和掌握私钥的服务器进行加密通信,服务器可以实现1对多的通信,客户端也可以用来验证掌握私钥的服务器身份。
    非对称加密的特点是信息传输1对多,服务器只需要维持一个私钥就能够和多个客户端进行加密通信,但服务器发出的信息能够被所有的客户端解密,且该算法的计算复杂,加密速度慢。

 

非对称加密算法比对称加密算法要复杂的多,处理起来也要慢得多。如果所有的网络数据都用非对称加密算法来加密,那效率会很低。所以在实际中,非对称加密只会用来传递一条信息,那就是用于对称加密的密钥。当用于对称加密的密钥确定了,A和B还是通过对称加密算法进行网络通信。这样,既保证了网络通信的安全性,又不影响效率,A和B也不用见面商量密钥了。

加/解密主要步骤

所以,在现代,A和B之间要进行安全,省心的网络通信,需要经过以下几个步骤

  1. 通过CA体系交换public key
  2. 通过非对称加密算法,交换用于对称加密的密钥
  3. 通过对称加密算法,加密正常的网络通信

 

公钥/私钥

当客户端发送请求到服务端的时候,将会收到服务端发送的公钥,服务器有对应的私钥; 服务端与客户端进行通讯的时候,使用私钥将数据进行加密传输,客户端使用公钥进行解密后获得内容,而客户端发送数据到服务端的时候会使用公钥将内容进行加密,服务器接收后使用私钥解密。

 

CA 证书身份识别

在传输的过程中,客户端如何获得服务器端的公钥呢?当时是服务器分发给客户端,如果一开始服务端发送的公钥到客户端的过程中有可能被第三方劫持,然后第三方自己伪造一对密钥,将公钥发送给客户端,当服务器发送数据给客户端的时候,中间人将信息进行劫持,用一开始劫持的公钥进行解密后,然后使用自己的私钥将数据加密发送给客户端,而客户端收到后使用公钥解密,反过来亦是如此,整个过程中间人是透明的,但信息泄露却不得而知。

服务器端生成私钥

openssl genrsa -out server.key 2048

服务器端生成证书


openssl req -new -x509 -key server.key -out server.pem -days 3650


Golang TLS 服务器/客户端

服务器端

package main
import (
    "bufio"
    "crypto/tls"
    "log"
    "net"
)
func main() {
    cert, err := tls.LoadX509KeyPair("server.pem", "server.key")
    if err != nil {
        log.Println(err)
        return
    }
    config := &tls.Config{Certificates: []tls.Certificate{cert}}
    ln, err := tls.Listen("tcp", ":443", config)
    if err != nil {
        log.Println(err)
        return
    }
    defer ln.Close()
    for {
        conn, err := ln.Accept()
        if err != nil {
            log.Println(err)
            continue
        }
        go handleConn(conn)
    }
}
func handleConn(conn net.Conn) {
    defer conn.Close()
    r := bufio.NewReader(conn)
    for {
        msg, err := r.ReadString('\n')
        if err != nil {
            log.Println(err)
            return
        }
        println(msg)
        n, err := conn.Write([]byte("World\n"))
        if err != nil {
            log.Println(n, err)
            return
        }
    }
}

客户端

func main() {
    conf := &tls.Config{
        InsecureSkipVerify: true,
    }
    conn, err := tls.Dial("tcp", "127.0.0.1:443", conf)
    if err != nil {
        log.Println(err)
        return
    }
    defer conn.Close()
    n, err := conn.Write([]byte("Hello\n"))
    if err != nil {
        log.Println(n, err)
        return
    }
    buf := make([]byte, 100)
    n, err = conn.Read(buf)
    if err != nil {
        log.Println(n, err)
        return
    }
    println(string(buf[:n]))
}

Crypto++®  库

crypto++ 是一个·C++ 的加密库。网站地址:https://www.cryptopp.com/

它支持下列算法:

AlgorithmName
authenticated encryption schemesGCMCCMEAXChaCha20Poly1305XChaCha20Poly1305
high speed stream ciphersChaCha (8/12/20)ChaCha (IETF) HC (128/256)PanamaRabbit (128/256)SosemanukSalsa20 (8/12/20)XChaCha (8/12/20)XSalsa20
AES and AES candidatesAES (Rijndael), RC6MARSTwofishSerpentCAST-256
other block ciphersARIA, Blowfish, CamelliaCHAMHIGHTIDEAKalyna (128/256/512)LEASEED, RC5, SHACAL-2, SIMECKSIMON (64/128), Skipjack, SPECK (64/128)SimeckSM4,Threefish (256/512/1024)Triple-DES (DES-EDE2 and DES-EDE3), TEA, XTEA
block cipher modes of operationECB, CBC, CBC ciphertext stealing (CTS), CFB, OFB, counter mode (CTR), XTS
message authentication codesBLAKE2b, BLAKE2sCMAC, CBC-MAC, DMAC, GMAC (GCM)HMACPoly1305SipHash, Two-Track-MAC, VMAC
hash functionsBLAKE2b, BLAKE2s, Keccack (F1600), SHA-1SHA-2, SHA-3, SHAKE (128/256)SipHashTiger, RIPEMD (128/160/256/320), SM3WHIRLPOOL
public-key cryptographyRSA, DSA, Determinsitic DSA (RFC 6979), ElGamal, Nyberg-Rueppel (NR), Rabin-Williams (RW), EC-based German Digital Signature (ECGDSA), LUC, LUCELG, DLIES (variants of DHAES), ESIGN
padding schemes for public-key systemsPKCS#1 v2.0, OAEP, PSS, PSSR, IEEE P1363 EMSA2 and EMSA5
key agreement schemesDiffie-Hellman (DH), Unified Diffie-Hellman (DH2), Menezes-Qu-Vanstone (MQV), Hashed MQV (HMQV), Fully Hashed MQV (FHMQV), LUCDIF, XTR-DH
elliptic curve cryptographyECDSA, Determinsitic ECDSA (RFC 6979), ed25519, ECGDSA, ECNR, ECIES, x25519, ECDH, ECMQV
insecure or obsolescent algorithms retained for backwards compatibility and historical valueMD2MD4MD5Panama HashDESARC4SEAL 3.0, WAKE-OFB, DESX (DES-XEX3), RC2, SAFER, 3-WAY, GOST, SHARK, CAST-128, Square

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Ansible是一种用于自动化运维的工具,可以帮助管理员简化和自动化常见的管理任务。下面是一个使用Ansible的自动化运维实例。 假设我们有一个包含多个服务器的Web应用程序。每次更新应用程序或更改配置时,都需要在所有服务器上手动执行相同的操作,这是一项耗时且容易出错的任务。使用Ansible,我们可以自动化这个过程。 首先,我们需要在Ansible主控节点上创建一个名为inventory的清单文件,列出所有的服务器。然后,我们需要编写一个名为playbook的配置文件,在其中定义我们要执行的任务。 在playbook中,我们可以使用Ansible的模块来执行特定的操作。对于我们的Web应用程序,我们可以使用模块来安装软件包、启动/停止服务、复制文件等。 例如,要更新我们的应用程序,我们可以使用Ansible的模块来从源代码库中拉取最新版本的应用程序代码,并在服务器上进行部署。我们可以通过在playbook中使用Git模块来下载最新代码,并使用Shell模块在服务器上执行必要的命令来构建和部署应用程序。 另外,我们还可以使用Ansible的变量来配置不同的环境。例如,我们可以在playbook中定义一个变量,用于指定部署应用程序时使用的配置文件。 最后,我们可以在命令行中运行Ansible命令,指定使用的inventory和playbook文件。Ansible将会连接到目标服务器并执行我们定义的任务。 通过使用Ansible,我们可以实现自动化运维,避免手动执行重复任务,提高效率和准确性。这不仅节省了管理员的时间和精力,还能减少人为错误的发生,提高整个系统的稳定性和可靠性。 ### 回答2: Ansible是一种自动化运维工具,它具有简单易用、灵活可扩展的特点。下面我将介绍一个使用Ansible实现自动化运维的实例。 假设我们有一个由多台Web服务器组成的集群,需要将代码及相关配置文件更新到每台服务器并重启服务。使用Ansible可以轻松实现这个任务。 首先,我们需要在本地机器上安装Ansible并配置相关的主机清单文件和SSH密钥。主机清单文件用于指定要管理的远程服务器,SSH密钥用于与远程服务器进行安全连接。 接下来,我们创建一个Ansible Playbook文件来定义整个任务的执行流程。在该文件中,我们可以使用Ansible的模块来执行各种操作,如复制文件、运行命令等。 playbook的执行由几个组件组成,包括主机清单文件、变量文件、任务和处理器。我们可以在任务中定义一系列的步骤来完成更新和重启服务的操作。 例如,我们可以使用`copy`模块将最新的代码复制到远程服务器上的指定目录。使用`command`模块可以执行重启服务的命令。同时,还可以使用`notify`和`handlers`来定义触发重启服务的条件和处理方法。 执行该playbook时,Ansible会自动连接到每台服务器,并按照playbook中定义的步骤逐个执行。通过Ansible的并发执行特性,我们可以同时在集群中的多台服务器上进行操作,大大提高了效率。 除了更新代码和重启服务,Ansible还可以实现其他自动化运维任务,如添加用户、配置数据库等。通过编写相应的playbook文件,我们可以轻松地扩展和定制自己的自动化运维需求。 总之,Ansible是一款强大的自动化运维工具,它提供了简单且灵活的方式来管理和维护服务器集群。通过使用Ansible,我们可以轻松实现各种自动化任务,提高工作效率并降低人为失误的风险。 ### 回答3: Ansible是一款强大的自动化运维工具,它具有简单易用、开放源代码、轻量级等特点。下面我将以一个简单的实例来说明Ansible的自动化运维能力。 假设我们有一组服务器,需要在每个服务器上安装一个名为"Nginx"的Web服务器,并确保所有服务器上的Nginx服务都处于运行状态。使用Ansible可以轻松实现这个任务。 首先,我们需要编写一个Ansible的Playbook,定义我们希望在目标服务器上执行的操作。假设我们的Playbook文件名为"nginx_installation.yml",内容如下: --- - name: Install and start Nginx hosts: web_servers become: true tasks: - name: Install Nginx apt: name=nginx state=present - name: Start Nginx service: name=nginx state=started 这个Playbook定义了一个名为"Install and start Nginx"的任务,使用apt模块在目标服务器上安装Nginx,并使用service模块启动Nginx服务。我们还通过指定hosts参数将任务应用到名为"web_servers"的服务器组上,并通过become参数指定使用特权权限执行任务。 接下来,我们可以使用ansible命令来运行这个Playbook,指定目标服务器组和登录凭证: ansible-playbook -i inventory.ini nginx_installation.yml -u username -k 其中,inventory.ini是一个主机清单文件,包含了我们的服务器信息,username是登录服务器的用户名,-k参数表示提示输入密码。 当我们运行这个命令后,Ansible会自动连接到每个目标服务器,并在其上执行定义的操作。安装和启动Nginx服务的过程将在每个服务器上自动完成,我们不再需要手动登录服务器进行操作。 通过这个简单的实例,我们可以看到Ansible实现自动化运维的便利性和高效性。只需要编写一个简单的Playbook,就能轻松地在多台服务器上执行相同的操作,大大提升运维效率。而且,Ansible的语法简洁明了,易于理解和维护,即使对于没有编程经验的运维人员也能够快速上手使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值