I have a pod running a PgPool image and a Postgresql cluster with writer and read-only instance. I am using PgPool just for loadbalancing read and write queries and have a single endpoint.
This all setup is working great, however when I try to setup TLS it does not work.
This what I have done:
Create a CA:
template := x509.Certificate{
SerialNumber: big.NewInt(1),
Subject: pkix.Name{
CommonName: "*",
},
NotBefore: time.Now(),
NotAfter: time.Now().Add(time.Hour * 24 * 180),
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
BasicConstraintsValid: true,
IsCA: true,
}
caCertBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &caPrivateKey.PublicKey, caPrivateKey)
if err != nil {
return certResp{}, fmt.Errorf("could not generate ca certificate: %v", err)
}
caPEM := new(bytes.Buffer)
if err := pem.Encode(caPEM, &pem.Block{
Type: "CERTIFICATE",
Bytes: caCertBytes,
}); err != nil {
return certResp{}, fmt.Errorf("could not encode ca certificate: %v", err)
}
caPrivateKeyPEM := new(bytes.Buffer)
if err := pem.Encode(caPrivateKeyPEM, &pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: x509.MarshalPKCS1PrivateKey(caPrivateKey),
}); err != nil {
return certResp{}, fmt.Errorf("could not encode ca key: %v", err)
}
Create server and key using the CA template and CA private key generated above:
template := x509.Certificate{
SerialNumber: big.NewInt(1),
Subject: pkix.Name{
CommonName: "*",
},
NotBefore: time.Now(),
NotAfter: time.Now().Add(time.Hour * 24 * 180),
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
KeyUsage: x509.KeyUsageDigitalSignature,
}
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return certResp{}, err
}
certBytes, err := x509.CreateCertificate(rand.Reader, &template, &caCertTemplate, &privateKey.PublicKey, caPrivateKey)
if err != nil {
return certResp{}, err
}
certPEM := new(bytes.Buffer)
if err := pem.Encode(certPEM, &pem.Block{
Type: "CERTIFICATE",
Bytes: certBytes,
}); err != nil {
return certResp{}, err
}
certPrivateKeyPEM := new(bytes.Buffer)
if err := pem.Encode(certPrivateKeyPEM, &pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: x509.MarshalPKCS1PrivateKey(privateKey),
}); err != nil {
return certResp{}, err
}
Update pgpool.conf ( using master slave mode)
ssl=on
ssl_key = '/tls/server.key'
ssl_cert = '/tls/server.crt'
Updated postgresql.conf
ssl_key = '/tls/server.key'
ssl_cert = '/tls/server.crt'
ssl_ca_cert = '/tls/root.crt'
If I set those in postgresql and try to connect to the instance directly it will work:
psql "sslmode=verify-ca sslrootcert=root.crt host=localhost user=postgres port=5432"
psql (14.2 (Ubuntu 14.2-1.pgdg20.04+1), server 13.4 (Ubuntu 13.4-4.pgdg18.04+1))
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off)
However if I try connecting via pgpool it does not and I get this error:
psql: error: connection to server at "localhost" (::1), port 5432 failed: ERROR: backend authentication failed
DETAIL: backend response with kind '' when expecting 'R'
And from the pgpool logs:
2022-04-07 06:06:28: pid 51: LOG: pool_ssl: "SSL_connect": "certificate verify failed"
2022-04-07 06:06:28: pid 51: LOG: pool_ssl: "SSL_connect": "certificate verify failed"
2022-04-07 06:06:28: pid 51: ERROR: backend authentication failed
2022-04-07 06:06:28: pid 51: DETAIL: backend response with kind '' when expecting 'R'
This is my pgpool config:
listen_addresses = '*'
port = 5432
socket_dir = '/var/run/pgpool'
pcp_listen_addresses = '*'
pcp_port = 9898
pcp_socket_dir = '/var/run/pgpool'
backend_hostname0 = '%v'
backend_port0 = 5432
backend_weight0 = 1
backend_flag0 = 'ALWAYS_PRIMARY|DISALLOW_TO_FAILOVER'
backend_hostname1 = '%v'
backend_port1 = 5432
backend_weight1 = 1
backend_flag1 = 'DISALLOW_TO_FAILOVER'
sr_check_period = 0
enable_pool_hba = off
backend_clustering_mode = 'streaming_replication'
num_init_children = 32
max_pool = 4
child_life_time = 300
child_max_connections = 0
connection_life_time = 0
client_idle_limit = 0
connection_cache = on
load_balance_mode = on
ssl = on
ssl_key = '/tls/server.key'
ssl_cert = '/tls/server.crt'
ssl_ca_cert = '/tls/root.crt'
failover_on_backend_error = off
allow_clear_text_frontend_auth = true
Seems there is something wrong with pgpool, but I am quite sure I am doing something wrong? Thanks
Related
I'm trying to use toml to store the connection settings of a database.
I want to load these settings that are in a config.toml file and thus do my operations
I tried the following:
go code:
func Init() *sql.DB {
config, err := toml.LoadFile("config.toml")
if err != nil {
log.Fatal("Erro ao carregar variaveis de ambiente")
}
host := config.Get("postgres.host").(string)
port := config.Get("postgres.port").(string)
user := config.Get("postgres.user").(string)
password := config.Get("postgres.password").(string)
dbname := config.Get("postgres.dbname").(string)
stringConnection := fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s", host, port, user, password, dbname)
db, err := sql.Open("postgres", stringConnection)
if err != nil {
panic(err)
}
fmt.Println("Sucesso ao realizar conexão com o banco de dados")
err = db.Ping()
return db
}
config.toml:
[postgres]
host = "localhost"
port = 5432
user = "postgres"
password = "ivaneteJC"
dbname = "webhook"
this attempt is returning an error, which unfortunately I do not know how to proceed
error:
panic: interface conversion: interface {} is int64, not string
Any solution ?
As for your error, like #tkausl said, you define port as integer, and not a string, yet you do type assertion of the value to string in this line
port := config.Get("postgres.port").(string)
Change the string to int64 like the error said and you should be fine.
Are you using the https://github.com/pelletier/go-toml package? If so, this package seems to also support unmarshalling config files into Go struct directly. This is a more convenient approach instead of having to config.Get each config one by one.
type PostgreConfig struct {
Host string
Port int
User string
Password string
Dbname string
}
type MyConfig struct {
Postgres *PostgreConfig
}
// Read the toml file content
doc, err := os.ReadFile("config.toml")
if err != nil {
panic(err)
}
// Parse the content
var cfg MyConfig
err = toml.Unmarshal(doc, &cfg)
if err != nil {
panic(err)
}
fmt.Println(cfg.Postgres.Host)
fmt.Println(cfg.Postgres.Port)
The solution with minimal changes:
// solution 1
port := config.Get("postgres.port")
stringConnection := fmt.Sprintf("host=%s port=%v user=%s password=%s dbname=%s", host, port, user, password, dbname)
// solution 2
port := config.Get("postgres.port").(int64)
stringConnection := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s", host, port, user, password, dbname)
// solution 3
// config.toml
port = "5432"
I'm trying to use pgx to make a TLS connection to a postgres 10 db.
My connection string is similar to: "host='my-host.com' port='5432' dbname='my-db' user='my-db-user' sslmode='verify-full' sslcert='/path/to/db_user.crt' sslkey='/path/to/db_user.key' sslrootcert='/path/to/ca_roots.pem'"
When I run this directly with psql on the command-line, it works, so the cert and key files must be valid. db_user.crt and db_user.key are both PEM files. (the command-line also works with sslmode='verify-full', so the rootcert should also be ok)
But when I initialize a pgx pool with that connection string, it fails with:
FATAL: connection requires a valid client certificate (SQLSTATE 28000)
Is go expecting something other than PEM? Or is there a different way ssl cert and key pair is supposed to be initialized with pgx?
Code
import (
"context"
"fmt"
"os"
"github.com/jackc/pgx/v4"
"github.com/jackc/pgx/v4/pgxpool"
)
type mockLogger struct{}
func (ml *mockLogger) Log(ctx context.Context, level pgx.LogLevel, msg string, data map[string]interface{}) {
fmt.Printf("[%s] %s : %+v\n", level.String(), msg, data)
}
func connect() error {
connStr := "host='my-host.com' port='5432' dbname='my-db' user='my-db-user' sslmode='verify-full' sslcert='/path/to/db_user.crt' sslkey='/path/to/db_user.key' sslrootcert='/path/to/ca_roots.pem'"
poolCfg, err := pgxpool.ParseConfig(connStr)
if err != nil {
return err
}
poolCfg.ConnConfig.Logger = &mockLogger{}
poolCfg.ConnConfig.LogLevel = pgx.LogLevelTrace
fmt.Printf("using connection string: \"%s\"\n", poolCfg.ConnString())
connPool, err := pgxpool.ConnectConfig(context.TODO(), poolCfg)
if err != nil {
return err
}
connPool.Close()
return nil
}
func main() {
if err := connect(); err != nil {
fmt.Printf("%+v\n", err)
os.Exit(1)
}
}
Output from calling connect():
using connection string: "host='my-host.com' port='5432' dbname='my-db' user='my-db-user' sslmode='require' sslcert='/path/to/db_user.crt' sslkey='/path/to/db_user.key' sslrootcert='/path/to/ca_roots.pem'"
[info] Dialing PostgreSQL server : map[host:my-host.com]
[error] connect failed : map[err:failed to connect to `host=my-host.com user=my-db-user database=my-db`: server error (FATAL: connection requires a valid client certificate (SQLSTATE 28000))]
failed to connect to `host=my-host.com user=my-db-user database=my-db`: server error (FATAL: connection requires a valid client certificate (SQLSTATE 28000))
Summary
Turns out for go, the cert pointed to by sslcert needed to contain the full client cert chain.
When /path/to/db_user.crt contained the client cert followed by client cert chain, the pgx connection worked.
Whereas the psql command worked in both cases:
when sslcert was just the leaf client cert without the chain
when sslcert contained client cert + chain
Not sure why psql was fine without the full chain, but it works now.
Details
Under-the-hood, pgx uses the pgconn module to create the connection. That, in turn, is just calling tls.X509KeyPair on the contents of the sslcert and sslkey files.
pgconn/config.go:
func configTLS(settings map[string]string, thisHost string, parseConfigOptions ParseConfigOptions) ([]*tls.Config, error) {
[...]
sslcert := settings["sslcert"]
sslkey := settings["sslkey"]
[...]
if sslcert != "" && sslkey != "" {
[...]
certfile, err := ioutil.ReadFile(sslcert)
if err != nil {
return nil, fmt.Errorf("unable to read cert: %w", err)
}
cert, err := tls.X509KeyPair(certfile, pemKey)
if err != nil {
return nil, fmt.Errorf("unable to load cert: %w", err)
}
tlsConfig.Certificates = []tls.Certificate{cert}
I'm trying to connect a go client to mongodb server running with ssl enabled. I get a clear error message indicating that the hand shake failed due to ssl error. I use a self signed certificate on the client side.
Got below from the mongodb server:
2017-05-13T04:38:53.910+0000 I NETWORK [thread1] connection accepted from 172.17.0.1:51944 #10 (1 connection now open)
2017-05-13T04:38:53.911+0000 E NETWORK [conn10] SSL: error:14094412:SSL routines:SSL3_READ_BYTES:sslv3 alert bad certificate
2017-05-13T04:38:53.911+0000 I - [conn10] end connection
Error from Go client:
Could not connect to mongodb_s1.dev:27017 x509: certificate signed by unknown authority (possibly because of "crypto/rsa: verification error" while trying to verify candidate authority certificate "XYZ")
Tried multiple options, but didn't help
You can skip TLS security checks using InsecureSkipVerify = true. This allows you to use self-signed certificates. See the code from compose help below.
Instead of skipping security checks, it is advisable to add the CA used to sign your certificates to the list of trusted CAs of the system.
package main
import (
"crypto/tls"
"fmt"
"net"
"os"
"strings"
"gopkg.in/mgo.v2"
)
func main() {
uri := os.Getenv("MONGODB_URL")
if uri == "" {
fmt.Println("No connection string provided - set MONGODB_URL")
os.Exit(1)
}
uri = strings.TrimSuffix(uri, "?ssl=true")
Here:
tlsConfig := &tls.Config{}
tlsConfig.InsecureSkipVerify = true
dialInfo, err := mgo.ParseURL(uri)
if err != nil {
fmt.Println("Failed to parse URI: ", err)
os.Exit(1)
}
And here:
dialInfo.DialServer = func(addr *mgo.ServerAddr) (net.Conn, error) {
conn, err := tls.Dial("tcp", addr.String(), tlsConfig)
return conn, err
}
session, err := mgo.DialWithInfo(dialInfo)
if err != nil {
fmt.Println("Failed to connect: ", err)
os.Exit(1)
}
defer session.Close()
dbnames, err := session.DB("").CollectionNames()
if err != nil {
fmt.Println("Couldn't query for collections names: ", err)
os.Exit(1)
}
fmt.Println(dbnames)
}
I have looked at various resources. I'm not sure how to accomplish this task. I can connect locally no problem, but I cannot connect to the remote easily. I need to pass on an RSA .pem key, and I'm not quite sure how to do this w/o forcing a connection unsecured
package main
import (
"database/sql"
"fmt"
"os"
_ "github.com/lib/pq"
)
var (
dbUser = os.Getenv("DB_USER")
dbPass = os.Getenv("DB_PASS")
dbName = os.Getenv("DB_NAME")
dbHost = os.Getenv("DB_HOST")
dbPort = os.Getenv("DB_PORT")
sslMode = os.Getenv("SSLMODE")
)
// ConnectDb is a short cut function that takes parameters through
// CLI that returns a pointer to a sql.DB connection.
// It takes no arguments.
func ConnectDb() (*sql.DB, error) {
db, err := sql.Open("postgres", getDbInfo())
CheckErr(err, "Unable to connecto tthe DB")
if err := db.Ping(); err != nil {
return nil, err
}
return db, nil
}
func getDbInfo() string {
var dbInfo string
if dbName != "" {
dbInfo += fmt.Sprintf("dbname=%s ", dbName)
} else {
dbInfo += fmt.Sprintf("dbname=%s ", "development")
}
// checks for nil value
if dbUser != "" {
dbInfo += fmt.Sprintf("dbuser=%s ", "user")
}
// checks for nil value
if dbPass != "" {
dbInfo += fmt.Sprintf("dbpass=%s ", dbPass)
}
if sslMode != "" {
dbInfo += fmt.Sprintf("sslmode=%s", sslMode)
} else {
dbInfo += fmt.Sprintf("sslmode=disable")
}
return dbInfo
}
It is my understanding that you need to open connection to postgre database. I don't know if a native postgre ssh tunneling support exists. So, this answer about SSH tunneling to DB machine.
I have not tested postgre this way, but I have had this model used in some proprietary server connections.
The process goes like that:
open ssh connection to db machine
establish tunnel from local port to remote db port
open db connection on local port
You can accomplish #1 and #2 with ssh client like OpenSSH or putty. You should probably do that 1st. If external client works, then you can attempt to put it all into go language code without external SSH client.
In go you would use
"golang.org/x/crypto/ssh"
package.
There are tutorials out there how to use GO ssh tunneling. Below is not a tested sample without error checking:
var buffer []byte
var err error
buffer, err = ioutil.ReadFile(sshKeyFile)
var key ssh.Signer
key, err = ssh.ParsePrivateKey(buffer)
var authMethod ssh.AuthMethod
authMethod = ssh.PublicKeys(key)
sshConfig = &ssh.ClientConfig{
User: "user_id",
Auth: []ssh.AuthMethod{authMethod},
}
conn, err := ssh.Dial("tcp", endpoint, sshConfig)
// open connection on postgre:
dbConn, err = conn.Dial("tcp", dbEndpoint)
The last line above is not exactly tunneling, but an TCP connection open to DB server. You might be able to pass that connection into db library. If not, you would have to setup a tunnel.
I am writing a TLS listener and accepting new connections. The new connections must be verified against a list of SHA1s before continuing. The issue is that tls.Listen() returns a listener of the interface net.Listener. This means Accept() will yield plain-jane net.Conn and not the tls.Conn which provides a ConnectionState().PeerCertificates.
The accepted net.Conn are too basic but when I cast to the more specific *tls.Conn type I receive a runtime exception.
package main
import (
"crypto/tls"
"fmt"
"net"
)
type Service struct {
listener net.Listener
}
func (serv *Service)Listen(port int64) (err error) {
cert, err := tls.LoadX509KeyPair( "/etc/SCAMP/services/helloworld.crt","/etc/SCAMP/services/helloworld.key" )
if err != nil {
return
}
config := &tls.Config{
Certificates: []tls.Certificate{ cert },
}
serv.listener,err = tls.Listen("tcp", "127.0.0.1:30101", config)
if err != nil {
return err
}
return
}
func (serv *Service)AcceptRequests() {
for {
netConn,_ := serv.listener.Accept()
var tlsConn (*tls.Conn) = netConn.(*tls.Conn)
certs := tlsConn.ConnectionState().PeerCertificates
fmt.Printf("got certs: `%s`\n", certs)
}
}
func main() {
serv := new(Service)
serv.Listen(30100)
tlsConn, _ := tls.Dial("tcp","127.0.0.1:30101", &tls.Config{
InsecureSkipVerify: true,
})
tlsConn.Write([]byte("hey"))
}
which errors as such:
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0xffffffff addr=0x0 pc=0x78a77]
goroutine 1 [running]:
crypto/tls.(*Conn).Handshake(0x0, 0x1050a008, 0x0, 0x0)
/usr/src/go/src/crypto/tls/conn.go:967 +0x317
crypto/tls.(*Conn).Write(0x0, 0x10538120, 0x3, 0x8, 0x0, 0x0, 0x0, 0xfefd2220)
/usr/src/go/src/crypto/tls/conn.go:845 +0x80
main.main()
/tmp/sandbox290881341/main.go:49 +0x1c0
goroutine 2 [runnable]:
runtime.forcegchelper()
/usr/src/go/src/runtime/proc.go:90
runtime.goexit()
/usr/src/go/src/runtime/asm_amd64p32.s:1086 +0x1
goroutine 3 [runnable]:
runtime.bgsweep()
/usr/src/go/src/runtime/mgc0.go:82
runtime.goexit()
/usr/src/go/src/runtime/asm_amd64p32.s:1086 +0x1
goroutine 4 [runnable]:
runtime.runfinq()
/usr/src/go/src/runtime/malloc.go:712
runtime.goexit()
/usr/src/go/src/runtime/asm_amd64p32.s:1086 +0x1
http://play.golang.org/p/gv7dy8XQ81
The issue was with loading the certificates. Here is a working example in case someone else stumbles upon this example. You can indeed check the certificates off an Accept() (but from what I'm learning, that's not a common case in TLS, you usually check the certificate from the client's side as the individual clients do not require certificates).
package main
import (
"crypto/tls"
"fmt"
"net"
"time"
)
type Service struct {
listener net.Listener
}
func (serv *Service)Listen(port int64) (err error) {
rsaCertPEM := `-----BEGIN CERTIFICATE-----
MIIGKjCCBBKgAwIBAgIJAOaBs5/Gdk7RMA0GCSqGSIb3DQEBBQUAMGsxHzAdBgNV
BAMTFlhhdmllcnMtTUJQIGhlbGxvd29ybGQxEjAQBgNVBAoTCVNDQU1QIEluYzEL
MAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEjAQBgNVBAcTCVNhbiBE
aWVnbzAeFw0xNTA3MjcxNzMyNDNaFw0yNTA3MjQxNzMyNDNaMGsxHzAdBgNVBAMT
FlhhdmllcnMtTUJQIGhlbGxvd29ybGQxEjAQBgNVBAoTCVNDQU1QIEluYzELMAkG
A1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEjAQBgNVBAcTCVNhbiBEaWVn
bzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAOMiK19vGbRH7Y40jC3E
B+r2NNeEO9BIB8umzAs0uh1hRxEWYgdYwOvmEeuUQgimHbJ7Neh8IKjUiD529Ir0
rxNwhmu3AxFJf5hBC9Ix5nO2oVjIPdCVX+1CL9BJvmYyRlV5cq5WukTeYuSLG/tB
h9fARwIhcR9HrjYYb6LtMUX0oIlHQytDRn9pM27TfoR6ad3dwZdRpf9kQH4x467d
rBiRvRnBx5JBCE/cpFg7fQtrsrurn6tmMR/WMpv8GU0dLGEMCs/Te1bwH3XHDwNZ
mLVukfIhyWU/hXNzbggar0wk3ZqJrEeDm8zQJ73ywhs4D8AY+UX3V+1SBah45U+f
S9fZi7yi8XoCuEHTZoYU3hVcSP3Yqx1aZS5D7rx2X+T5XrJxy8FHiRX1LEPWKzz+
3x3+s9UcCIFz9xlAm0tM6ZjzeOcXhadSd+zTNngfQcwOPbPbyTM4Z9RD2VDPtfvV
eqJ82ZOGVWWkBFElZV6I5idRDph4/eEvO1Ij02C6oJJbyfbXzuMAgGVch8oMd65S
mVLppAT2uiNYebWp2Q2TleShNiv7AhvnV0saEfuCtX6fsryzogOMsEXiK+EqAZ3c
QUT+9hdIrwGWEOcx4Dpm2Tzh2QDIzmPVKIJ/PHPZgVq/zkc03ThuSRGYiNgz0YY4
AWsPtAVVZafh3ZcnPjP8OocxAgMBAAGjgdAwgc0wHQYDVR0OBBYEFOePjJeN13Rm
AzPVb/Tcp8x1gGh6MIGdBgNVHSMEgZUwgZKAFOePjJeN13RmAzPVb/Tcp8x1gGh6
oW+kbTBrMR8wHQYDVQQDExZYYXZpZXJzLU1CUCBoZWxsb3dvcmxkMRIwEAYDVQQK
EwlTQ0FNUCBJbmMxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRIw
EAYDVQQHEwlTYW4gRGllZ2+CCQDmgbOfxnZO0TAMBgNVHRMEBTADAQH/MA0GCSqG
SIb3DQEBBQUAA4ICAQDTlOdkKl1VT+VleeORUU3vVfeNGmiWrd88v6JlUxdYBU2o
YfQgVzPijxy9EGdgdaw/BPI0ypMn/DQ5hOcAHtHWCn7hHnRGTM4GMqZ6TOwexUyh
W02QFdwnB5jKQ3HNokp43NnoxAxEFnd6m27O39unwbq49Tt16HfEeUXMbXQabV6I
fZy7YsulamH0M5eZ2qtX25BkuYV1d4PpnahKWGRRvdg9jEszMfksI/tmv8CDmCi4
3cOS2c6i86XF3Cx+SlNPhJ7YpQK8IVxE3xzRMCf2kiA2vdb7DhVz4N5ZBzZYX5qD
HkYdjTdj4I6jtdeeNKqrEMV2Q3/X2Mdp0jp8dcK8WO7jXSIBvo4GO5797ok5mbQT
om0xvBljFkkyTuWJLUJslg9N7IyXCYZXLXpUvm40J+fXMNnd6lGbygNSrKFyjdDX
x5r9XCAKmtRteZSVpknN1eE5Gl5naY6iZrxXeeNlCG8x6a2XaQM6/0/XhSEZnGog
XiiirE3s5xZnWVRqOwx7iihs9I4mdHNj9kFdsB3vPjlMfbiQl+GbLIaF16H+LFP2
ArBiqwKM5kOcA3kT0XMm1rvxHZrpEACGf2zRhuBlZRyP96KPp49A4FpVHjsYweI8
DkIeTJpAsCXxgqDCw0P8xfhM5gP/ILmWgOIGj0+E/8OTgL3J85Jg8rmIo86mSg==
-----END CERTIFICATE-----`
var rsaKeyPEM = `-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----`
cert, err := tls.X509KeyPair([]byte(rsaCertPEM), []byte(rsaKeyPEM))
config := &tls.Config{
Certificates: []tls.Certificate{ cert },
}
serv.listener,err = tls.Listen("tcp", "127.0.0.1:30101", config)
if err != nil {
return err
}
return
}
func (serv *Service)AcceptRequests() {
for {
netConn,_ := serv.listener.Accept()
var tlsConn (*tls.Conn) = netConn.(*tls.Conn)
certs := tlsConn.ConnectionState().PeerCertificates
fmt.Printf("got certs: `%s`\n", certs)
}
}
func main() {
serv := new(Service)
err := serv.Listen(30100)
if err != nil {
fmt.Printf("go err: `%s`", err)
return
}
go serv.AcceptRequests()
time.Sleep(1)
tlsConn, _ := tls.Dial("tcp","127.0.0.1:30101", &tls.Config{
InsecureSkipVerify: true,
})
tlsConn.Write([]byte("hey"))
}