mirror of
https://github.com/status-im/status-go.git
synced 2025-02-16 16:56:53 +00:00
Added preflight outbound check to local pairing
This commit is contained in:
parent
5935339c19
commit
9a2e9fbc3c
@ -916,7 +916,7 @@ func ConvertToRegularAccount(mnemonic, currPassword, newPassword string) string
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ImageServerTLSCert() string {
|
func ImageServerTLSCert() string {
|
||||||
cert, err := server.PublicTLSCert()
|
cert, err := server.PublicMediaTLSCert()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return makeJSONResponse(err)
|
return makeJSONResponse(err)
|
||||||
|
@ -13,8 +13,8 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var globalCertificate *tls.Certificate = nil
|
var globalMediaCertificate *tls.Certificate = nil
|
||||||
var globalPem string
|
var globalMediaPem string
|
||||||
|
|
||||||
func makeRandomSerialNumber() (*big.Int, error) {
|
func makeRandomSerialNumber() (*big.Int, error) {
|
||||||
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
|
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
|
||||||
@ -59,47 +59,52 @@ func GenerateX509PEMs(cert *x509.Certificate, key *ecdsa.PrivateKey) (certPem, k
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateTLSCert() error {
|
func GenerateTLSCert(notBefore, notAfter time.Time, hostname string) (*tls.Certificate, []byte, error) {
|
||||||
if globalCertificate != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
sn, err := makeRandomSerialNumber()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
cert := GenerateX509Cert(sn, notBefore, notAfter, hostname)
|
||||||
|
certPem, keyPem, err := GenerateX509PEMs(cert, priv)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
finalCert, err := tls.X509KeyPair(certPem, keyPem)
|
||||||
|
return &finalCert, certPem, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func generateMediaTLSCert() error {
|
||||||
|
if globalMediaCertificate != nil {
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
notBefore := time.Now()
|
notBefore := time.Now()
|
||||||
notAfter := notBefore.Add(365 * 24 * time.Hour)
|
notAfter := notBefore.Add(365 * 24 * time.Hour)
|
||||||
|
|
||||||
sn, err := makeRandomSerialNumber()
|
finalCert, certPem, err := GenerateTLSCert(notBefore, notAfter, Localhost)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
cert := GenerateX509Cert(sn, notBefore, notAfter, Localhost)
|
globalMediaCertificate = finalCert
|
||||||
certPem, keyPem, err := GenerateX509PEMs(cert, priv)
|
globalMediaPem = string(certPem)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
finalCert, err := tls.X509KeyPair(certPem, keyPem)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
globalCertificate = &finalCert
|
|
||||||
globalPem = string(certPem)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func PublicTLSCert() (string, error) {
|
func PublicMediaTLSCert() (string, error) {
|
||||||
err := generateTLSCert()
|
err := generateMediaTLSCert()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return globalPem, nil
|
return globalMediaPem, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToECDSA takes a []byte of D and uses it to create an ecdsa.PublicKey on the elliptic.P256 curve
|
// ToECDSA takes a []byte of D and uses it to create an ecdsa.PublicKey on the elliptic.P256 curve
|
||||||
|
142
server/pairing/preflight/preflight.go
Normal file
142
server/pairing/preflight/preflight.go
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
package preflight
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"crypto/x509"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/status-im/status-go/logutils"
|
||||||
|
"github.com/status-im/status-go/protocol/common"
|
||||||
|
"github.com/status-im/status-go/server"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
outboundCheck = "/outbound_check"
|
||||||
|
headerPing = "ping"
|
||||||
|
headerPong = "pong"
|
||||||
|
)
|
||||||
|
|
||||||
|
func preflightHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ping := r.Header.Get(headerPing)
|
||||||
|
if ping == "" {
|
||||||
|
http.Error(w, "no value in 'ping' header", http.StatusBadRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Header().Set(headerPong, ping)
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeCert(address net.IP) (*tls.Certificate, []byte, error) {
|
||||||
|
notBefore := time.Now()
|
||||||
|
notAfter := notBefore.Add(time.Minute)
|
||||||
|
return server.GenerateTLSCert(notBefore, notAfter, address.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeAndStartServer(cert *tls.Certificate, address net.IP) (string, func() error, error) {
|
||||||
|
s := server.NewServer(
|
||||||
|
cert,
|
||||||
|
address.String(),
|
||||||
|
nil,
|
||||||
|
logutils.ZapLogger().Named("Preflight Server"),
|
||||||
|
)
|
||||||
|
|
||||||
|
s.SetHandlers(server.HandlerPatternMap{outboundCheck: preflightHandler})
|
||||||
|
err := s.Start()
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// hack : sleep to give server time
|
||||||
|
// TODO something funky with the afterPortChanged func. Maybe waitgroup magic
|
||||||
|
time.Sleep(500 * time.Millisecond)
|
||||||
|
return s.GetHostname() + ":" + strconv.Itoa(s.GetPort()), s.Stop, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeClient(certPem []byte) (*http.Client, error) {
|
||||||
|
rootCAs, err := x509.SystemCertPool()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if ok := rootCAs.AppendCertsFromPEM(certPem); !ok {
|
||||||
|
return nil, fmt.Errorf("failed to append certPem to rootCAs")
|
||||||
|
}
|
||||||
|
|
||||||
|
tr := &http.Transport{
|
||||||
|
TLSClientConfig: &tls.Config{
|
||||||
|
MinVersion: tls.VersionTLS12,
|
||||||
|
InsecureSkipVerify: false, // MUST BE FALSE
|
||||||
|
RootCAs: rootCAs,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return &http.Client{Transport: tr}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeOutboundCheck(c *http.Client, host string) error {
|
||||||
|
u := url.URL{
|
||||||
|
Scheme: "https",
|
||||||
|
Host: host,
|
||||||
|
Path: outboundCheck,
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := http.NewRequest("GET", u.String(), nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ping, err := common.RandomAlphanumericString(64)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Header.Set(headerPing, ping)
|
||||||
|
|
||||||
|
resp, err := c.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
return fmt.Errorf("response status not ok, received '%d' : '%s'", resp.StatusCode, resp.Status)
|
||||||
|
}
|
||||||
|
|
||||||
|
pong := resp.Header.Get(headerPong)
|
||||||
|
if pong != ping {
|
||||||
|
return fmt.Errorf("ping should match pong: ping '%s', pong '%s'", ping, pong)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func CheckOutbound() error {
|
||||||
|
// cert stuff
|
||||||
|
outboundIP, err := server.GetOutboundIP()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
cert, certPem, err := makeCert(outboundIP)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// server stuff
|
||||||
|
host, stop, err := makeAndStartServer(cert, outboundIP)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
stop()
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Client stuff
|
||||||
|
c, err := makeClient(certPem)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return makeOutboundCheck(c, host)
|
||||||
|
}
|
12
server/pairing/preflight/preflight_test.go
Normal file
12
server/pairing/preflight/preflight_test.go
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package preflight
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCheckOutbound(t *testing.T) {
|
||||||
|
err := CheckOutbound()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
@ -20,14 +20,14 @@ type MediaServer struct {
|
|||||||
|
|
||||||
// NewMediaServer returns a *MediaServer
|
// NewMediaServer returns a *MediaServer
|
||||||
func NewMediaServer(db *sql.DB, downloader *ipfs.Downloader, multiaccountsDB *multiaccounts.Database) (*MediaServer, error) {
|
func NewMediaServer(db *sql.DB, downloader *ipfs.Downloader, multiaccountsDB *multiaccounts.Database) (*MediaServer, error) {
|
||||||
err := generateTLSCert()
|
err := generateMediaTLSCert()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
s := &MediaServer{
|
s := &MediaServer{
|
||||||
Server: NewServer(
|
Server: NewServer(
|
||||||
globalCertificate,
|
globalMediaCertificate,
|
||||||
Localhost,
|
Localhost,
|
||||||
signal.SendMediaServerStarted,
|
signal.SendMediaServerStarted,
|
||||||
logutils.ZapLogger().Named("MediaServer"),
|
logutils.ZapLogger().Named("MediaServer"),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user