https和http都属于应用层,基于TCP(以及UDP)协议。但是不同的是:
HTTP 缺省工作在TCP协议80端口
HTTPS缺省工作在TCP协议443端口
HTTPS服务不同于HTTP服务,HTTPS是HTTP over SSL或HTTP over TLS
SSL是“Secure Sockets Layer”的缩写,中文叫做“安全套接层”。它是在上世纪90年代中期,由NetScape公司设计的。为啥要发明 SSL 这个协议捏?因为原先互联网上使用的 HTTP 协议是明文的,存在很多缺点——比如传输内容会被偷窥(嗅探)和篡改。发明 SSL 协议,就是为了解决这些问题。
到了1999年,SSL 因为应用广泛,已经成为互联网上的事实标准。IETF 就在那年把 SSL 标准化。标准化之后的名称改为TLS是“Transport Layer Security”的缩写,中文叫做“传输层安全协议”。
很多相关的文章都把这两者并列称呼(SSL/TLS),因为这两者可以视作同一个东西的不同阶段。
要启用HTTPS首先需要创建私钥和证书。
有两种方式生成私钥和证书:
X.509 是密码学里公钥证书的格式标准
OpenSSL方式,生成私钥key.pem和证书cert.pem,3650代表有效期为10年
openssl genrsa -out key.pem 2048
openssl req -new -x509 -key key.pem -out cert.pem -days 3650
Golang标准库crypto/tls里有generate_cert.go,可以生成私钥key.pem和证书cert.pem,host参数是必须的,需要注意的是默认有效期是1年(36524time.Hour)
–duration参数可以设置时间
cd $GOROOT/src/crypto/tls/
go run generate_cert.go --host localhost
package main
import (
"log"
"net/http"
)
func handler(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Content-Type", "text/plain")
w.Write([]byte("This is an example server.\n"))
}
func main() {
http.HandleFunc("/", handler)
log.Printf("About to listen on 10443. Go to https://127.0.0.1:10443/")
err := http.ListenAndServeTLS(":10443", "cert.pem", "key.pem", nil)
log.Fatal(err)
}
package main
import (
"log"
"crypto/tls"
"net"
"bufio"
)
func main() {
log.SetFlags(log.Lshortfile)
cer, err := tls.LoadX509KeyPair("cert.pem", "key.pem")
if err != nil {
log.Println(err)
return
}
config := &tls.Config{Certificates: []tls.Certificate{cer}}
ln, err := tls.Listen("tcp", ":8000", config)
if err != nil {
log.Println(err)
return
}
defer ln.Close()
for {
conn, err := ln.Accept()
if err != nil {
log.Println(err)
continue
}
go handleConnection(conn)
}
}
func handleConnection(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
}
}
}
package main
import (
"log"
"crypto/tls"
)
func main() {
log.SetFlags(log.Lshortfile)
conf := &tls.Config{
InsecureSkipVerify: true,
}
conn, err := tls.Dial("tcp", "127.0.0.1:8000", 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]))
}