feat(oohelperd): measure TLS for :443 endpoints (#886)
This diff improves oohelperd to measure :443 endpoints with TLS. Part of https://github.com/ooni/probe/issues/2237.
This commit is contained in:
parent
df0e099b73
commit
1e7384d1cc
|
@ -50,7 +50,11 @@ func dnsDo(ctx context.Context, config *dnsConfig) {
|
||||||
addrs = []string{} // fix: the old test helper did that
|
addrs = []string{} // fix: the old test helper did that
|
||||||
}
|
}
|
||||||
failure := dnsMapFailure(newfailure(err))
|
failure := dnsMapFailure(newfailure(err))
|
||||||
config.Out <- ctrlDNSResult{Failure: failure, Addrs: addrs}
|
config.Out <- ctrlDNSResult{
|
||||||
|
Failure: failure,
|
||||||
|
Addrs: addrs,
|
||||||
|
ASNs: []int64{}, // unused by the TH and not serialized
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// dnsMapFailure attempts to map netxlite failures to the strings
|
// dnsMapFailure attempts to map netxlite failures to the strings
|
||||||
|
|
|
@ -29,6 +29,9 @@ type handler struct {
|
||||||
|
|
||||||
// NewResolver is the MANDATORY factory for creating a new resolver.
|
// NewResolver is the MANDATORY factory for creating a new resolver.
|
||||||
NewResolver func() model.Resolver
|
NewResolver func() model.Resolver
|
||||||
|
|
||||||
|
// NewTLSHandshaker is the MANDATORY factory for creating a new TLS handshaker.
|
||||||
|
NewTLSHandshaker func() model.TLSHandshaker
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ http.Handler = &handler{}
|
var _ http.Handler = &handler{}
|
||||||
|
|
|
@ -63,6 +63,9 @@ func TestHandlerWorkingAsIntended(t *testing.T) {
|
||||||
NewResolver: func() model.Resolver {
|
NewResolver: func() model.Resolver {
|
||||||
return netxlite.NewUnwrappedStdlibResolver()
|
return netxlite.NewUnwrappedStdlibResolver()
|
||||||
},
|
},
|
||||||
|
NewTLSHandshaker: func() model.TLSHandshaker {
|
||||||
|
return netxlite.NewTLSHandshakerStdlib(model.DiscardLogger)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
srv := httptest.NewServer(handler)
|
srv := httptest.NewServer(handler)
|
||||||
defer srv.Close()
|
defer srv.Close()
|
||||||
|
@ -76,25 +79,37 @@ func TestHandlerWorkingAsIntended(t *testing.T) {
|
||||||
parseBody bool
|
parseBody bool
|
||||||
}
|
}
|
||||||
expectations := []expectationSpec{{
|
expectations := []expectationSpec{{
|
||||||
name: "check for invalid method",
|
name: "check for invalid method",
|
||||||
reqMethod: "GET",
|
reqMethod: "GET",
|
||||||
respStatusCode: 400,
|
reqContentType: "",
|
||||||
|
reqBody: "",
|
||||||
|
respStatusCode: 400,
|
||||||
|
respContentType: "",
|
||||||
|
parseBody: false,
|
||||||
}, {
|
}, {
|
||||||
name: "check for invalid content-type",
|
name: "check for invalid content-type",
|
||||||
reqMethod: "POST",
|
reqMethod: "POST",
|
||||||
respStatusCode: 400,
|
reqContentType: "",
|
||||||
|
reqBody: "",
|
||||||
|
respStatusCode: 400,
|
||||||
|
respContentType: "",
|
||||||
|
parseBody: false,
|
||||||
}, {
|
}, {
|
||||||
name: "check for invalid request body",
|
name: "check for invalid request body",
|
||||||
reqMethod: "POST",
|
reqMethod: "POST",
|
||||||
reqContentType: "application/json",
|
reqContentType: "application/json",
|
||||||
reqBody: "{",
|
reqBody: "{",
|
||||||
respStatusCode: 400,
|
respStatusCode: 400,
|
||||||
|
respContentType: "",
|
||||||
|
parseBody: false,
|
||||||
}, {
|
}, {
|
||||||
name: "with measurement failure",
|
name: "with measurement failure",
|
||||||
reqMethod: "POST",
|
reqMethod: "POST",
|
||||||
reqContentType: "application/json",
|
reqContentType: "application/json",
|
||||||
reqBody: `{"http_request": "http://[::1]aaaa"}`,
|
reqBody: `{"http_request": "http://[::1]aaaa"}`,
|
||||||
respStatusCode: 400,
|
respStatusCode: 400,
|
||||||
|
respContentType: "",
|
||||||
|
parseBody: false,
|
||||||
}, {
|
}, {
|
||||||
name: "with reasonably good request",
|
name: "with reasonably good request",
|
||||||
reqMethod: "POST",
|
reqMethod: "POST",
|
||||||
|
|
|
@ -18,6 +18,9 @@ import (
|
||||||
"github.com/ooni/probe-cli/v3/internal/tracex"
|
"github.com/ooni/probe-cli/v3/internal/tracex"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TODO(bassosimone): we should refactor the TH to use step-by-step such that we
|
||||||
|
// can use an existing connection for the HTTP-measuring task
|
||||||
|
|
||||||
// ctrlHTTPResponse is the result of the HTTP check performed by
|
// ctrlHTTPResponse is the result of the HTTP check performed by
|
||||||
// the Web Connectivity test helper.
|
// the Web Connectivity test helper.
|
||||||
type ctrlHTTPResponse = webconnectivity.ControlHTTPRequestResult
|
type ctrlHTTPResponse = webconnectivity.ControlHTTPRequestResult
|
||||||
|
@ -51,11 +54,13 @@ func httpDo(ctx context.Context, config *httpConfig) {
|
||||||
defer config.Wg.Done()
|
defer config.Wg.Done()
|
||||||
req, err := http.NewRequestWithContext(ctx, "GET", config.URL, nil)
|
req, err := http.NewRequestWithContext(ctx, "GET", config.URL, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
config.Out <- ctrlHTTPResponse{ // fix: emit -1 like the old test helper does
|
// fix: emit -1 like the old test helper does
|
||||||
|
config.Out <- ctrlHTTPResponse{
|
||||||
BodyLength: -1,
|
BodyLength: -1,
|
||||||
Failure: httpMapFailure(err),
|
Failure: httpMapFailure(err),
|
||||||
StatusCode: -1,
|
Title: "",
|
||||||
Headers: map[string]string{},
|
Headers: map[string]string{},
|
||||||
|
StatusCode: -1,
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -73,11 +78,13 @@ func httpDo(ctx context.Context, config *httpConfig) {
|
||||||
defer clnt.CloseIdleConnections()
|
defer clnt.CloseIdleConnections()
|
||||||
resp, err := clnt.Do(req)
|
resp, err := clnt.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
config.Out <- ctrlHTTPResponse{ // fix: emit -1 like old test helper does
|
// fix: emit -1 like the old test helper does
|
||||||
|
config.Out <- ctrlHTTPResponse{
|
||||||
BodyLength: -1,
|
BodyLength: -1,
|
||||||
Failure: httpMapFailure(err),
|
Failure: httpMapFailure(err),
|
||||||
StatusCode: -1,
|
Title: "",
|
||||||
Headers: map[string]string{},
|
Headers: map[string]string{},
|
||||||
|
StatusCode: -1,
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,9 @@ type endpointInfo struct {
|
||||||
|
|
||||||
// Epnt is the endpoint to measure
|
// Epnt is the endpoint to measure
|
||||||
Epnt string
|
Epnt string
|
||||||
|
|
||||||
|
// TLS indicates whether we should try using TLS
|
||||||
|
TLS bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// ipInfoToEndpoints takes in input the [ipinfo] returned by newIPInfo
|
// ipInfoToEndpoints takes in input the [ipinfo] returned by newIPInfo
|
||||||
|
@ -86,6 +89,7 @@ func ipInfoToEndpoints(URL *url.URL, ipinfo map[string]*webconnectivity.ControlI
|
||||||
out = append(out, endpointInfo{
|
out = append(out, endpointInfo{
|
||||||
Addr: addr,
|
Addr: addr,
|
||||||
Epnt: epnt,
|
Epnt: epnt,
|
||||||
|
TLS: port == "443",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -142,15 +142,19 @@ func Test_ipInfoToEndpoints(t *testing.T) {
|
||||||
want: []endpointInfo{{
|
want: []endpointInfo{{
|
||||||
Addr: "8.8.4.4",
|
Addr: "8.8.4.4",
|
||||||
Epnt: "8.8.4.4:443",
|
Epnt: "8.8.4.4:443",
|
||||||
|
TLS: true,
|
||||||
}, {
|
}, {
|
||||||
Addr: "8.8.4.4",
|
Addr: "8.8.4.4",
|
||||||
Epnt: "8.8.4.4:80",
|
Epnt: "8.8.4.4:80",
|
||||||
|
TLS: false,
|
||||||
}, {
|
}, {
|
||||||
Addr: "8.8.8.8",
|
Addr: "8.8.8.8",
|
||||||
Epnt: "8.8.8.8:443",
|
Epnt: "8.8.8.8:443",
|
||||||
|
TLS: true,
|
||||||
}, {
|
}, {
|
||||||
Addr: "8.8.8.8",
|
Addr: "8.8.8.8",
|
||||||
Epnt: "8.8.8.8:80",
|
Epnt: "8.8.8.8:80",
|
||||||
|
TLS: false,
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
name: "with bogons and explicit port",
|
name: "with bogons and explicit port",
|
||||||
|
@ -176,9 +180,11 @@ func Test_ipInfoToEndpoints(t *testing.T) {
|
||||||
want: []endpointInfo{{
|
want: []endpointInfo{{
|
||||||
Addr: "8.8.4.4",
|
Addr: "8.8.4.4",
|
||||||
Epnt: "8.8.4.4:5432",
|
Epnt: "8.8.4.4:5432",
|
||||||
|
TLS: false,
|
||||||
}, {
|
}, {
|
||||||
Addr: "8.8.8.8",
|
Addr: "8.8.8.8",
|
||||||
Epnt: "8.8.8.8:5432",
|
Epnt: "8.8.8.8:5432",
|
||||||
|
TLS: false,
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
name: "with addresses and some bogons, no port, and unknown scheme",
|
name: "with addresses and some bogons, no port, and unknown scheme",
|
||||||
|
@ -224,9 +230,11 @@ func Test_ipInfoToEndpoints(t *testing.T) {
|
||||||
want: []endpointInfo{{
|
want: []endpointInfo{{
|
||||||
Addr: "8.8.4.4",
|
Addr: "8.8.4.4",
|
||||||
Epnt: "8.8.4.4:443",
|
Epnt: "8.8.4.4:443",
|
||||||
|
TLS: true,
|
||||||
}, {
|
}, {
|
||||||
Addr: "8.8.8.8",
|
Addr: "8.8.8.8",
|
||||||
Epnt: "8.8.8.8:443",
|
Epnt: "8.8.8.8:443",
|
||||||
|
TLS: true,
|
||||||
}},
|
}},
|
||||||
}}
|
}}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
|
|
@ -62,6 +62,9 @@ func main() {
|
||||||
return netxlite.NewDialerWithResolver(log.Log, newResolver())
|
return netxlite.NewDialerWithResolver(log.Log, newResolver())
|
||||||
},
|
},
|
||||||
NewResolver: newResolver,
|
NewResolver: newResolver,
|
||||||
|
NewTLSHandshaker: func() model.TLSHandshaker {
|
||||||
|
return netxlite.NewTLSHandshakerStdlib(log.Log)
|
||||||
|
},
|
||||||
})
|
})
|
||||||
srv := &http.Server{Addr: *endpoint, Handler: mux}
|
srv := &http.Server{Addr: *endpoint, Handler: mux}
|
||||||
listener, err := net.Listen("tcp", *endpoint)
|
listener, err := net.Listen("tcp", *endpoint)
|
||||||
|
|
|
@ -47,7 +47,13 @@ func measure(ctx context.Context, config *handler, creq *ctrlRequest) (*ctrlResp
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|
||||||
// start assembling the response
|
// start assembling the response
|
||||||
cresp := &ctrlResponse{}
|
cresp := &ctrlResponse{
|
||||||
|
TCPConnect: map[string]webconnectivity.ControlTCPConnectResult{},
|
||||||
|
TLSHandshake: map[string]webconnectivity.ControlTLSHandshakeResult{},
|
||||||
|
HTTPRequest: webconnectivity.ControlHTTPRequestResult{},
|
||||||
|
DNS: webconnectivity.ControlDNSResult{},
|
||||||
|
IPInfo: map[string]*webconnectivity.ControlIPInfo{},
|
||||||
|
}
|
||||||
select {
|
select {
|
||||||
case cresp.DNS = <-dnsch:
|
case cresp.DNS = <-dnsch:
|
||||||
default:
|
default:
|
||||||
|
@ -56,6 +62,7 @@ func measure(ctx context.Context, config *handler, creq *ctrlRequest) (*ctrlResp
|
||||||
cresp.DNS = ctrlDNSResult{
|
cresp.DNS = ctrlDNSResult{
|
||||||
Failure: nil,
|
Failure: nil,
|
||||||
Addrs: []string{},
|
Addrs: []string{},
|
||||||
|
ASNs: []int64{}, // unused by the TH and not serialized
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,11 +75,14 @@ func measure(ctx context.Context, config *handler, creq *ctrlRequest) (*ctrlResp
|
||||||
for _, endpoint := range endpoints {
|
for _, endpoint := range endpoints {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go tcpDo(ctx, &tcpConfig{
|
go tcpDo(ctx, &tcpConfig{
|
||||||
Address: endpoint.Addr,
|
Address: endpoint.Addr,
|
||||||
Endpoint: endpoint.Epnt,
|
EnableTLS: endpoint.TLS,
|
||||||
NewDialer: config.NewDialer,
|
Endpoint: endpoint.Epnt,
|
||||||
Out: tcpconnch,
|
NewDialer: config.NewDialer,
|
||||||
Wg: wg,
|
NewTSLHandshaker: config.NewTLSHandshaker,
|
||||||
|
URLHostname: URL.Hostname(),
|
||||||
|
Out: tcpconnch,
|
||||||
|
Wg: wg,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,12 +103,17 @@ func measure(ctx context.Context, config *handler, creq *ctrlRequest) (*ctrlResp
|
||||||
|
|
||||||
// continue assembling the response
|
// continue assembling the response
|
||||||
cresp.HTTPRequest = <-httpch
|
cresp.HTTPRequest = <-httpch
|
||||||
cresp.TCPConnect = make(map[string]ctrlTCPResult)
|
|
||||||
Loop:
|
Loop:
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case tcpconn := <-tcpconnch:
|
case tcpconn := <-tcpconnch:
|
||||||
cresp.TCPConnect[tcpconn.Endpoint] = tcpconn.TCP
|
cresp.TCPConnect[tcpconn.Endpoint] = tcpconn.TCP
|
||||||
|
if tcpconn.TLS != nil {
|
||||||
|
cresp.TLSHandshake[tcpconn.Endpoint] = *tcpconn.TLS
|
||||||
|
if info := cresp.IPInfo[tcpconn.Address]; info != nil && tcpconn.TLS.Failure == nil {
|
||||||
|
info.Flags |= webconnectivity.ControlIPInfoFlagValidForDomain
|
||||||
|
}
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break Loop
|
break Loop
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
//
|
//
|
||||||
// TCP connect measurements
|
// TCP connect (and optionally TLS handshake) measurements
|
||||||
//
|
//
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"crypto/tls"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -18,6 +19,9 @@ import (
|
||||||
// ctrlTCPResult is the result of the TCP check performed by the test helper.
|
// ctrlTCPResult is the result of the TCP check performed by the test helper.
|
||||||
type ctrlTCPResult = webconnectivity.ControlTCPConnectResult
|
type ctrlTCPResult = webconnectivity.ControlTCPConnectResult
|
||||||
|
|
||||||
|
// ctrlTLSResult is the result of the TLS check performed by the test helper.
|
||||||
|
type ctrlTLSResult = webconnectivity.ControlTLSHandshakeResult
|
||||||
|
|
||||||
// tcpResultPair contains the endpoint and the corresponding result.
|
// tcpResultPair contains the endpoint and the corresponding result.
|
||||||
type tcpResultPair struct {
|
type tcpResultPair struct {
|
||||||
// Address is the IP address we measured.
|
// Address is the IP address we measured.
|
||||||
|
@ -28,6 +32,9 @@ type tcpResultPair struct {
|
||||||
|
|
||||||
// TCP contains the TCP results.
|
// TCP contains the TCP results.
|
||||||
TCP ctrlTCPResult
|
TCP ctrlTCPResult
|
||||||
|
|
||||||
|
// TLS contains the TLS results
|
||||||
|
TLS *ctrlTLSResult
|
||||||
}
|
}
|
||||||
|
|
||||||
// tcpConfig configures the TCP connect check.
|
// tcpConfig configures the TCP connect check.
|
||||||
|
@ -35,22 +42,31 @@ type tcpConfig struct {
|
||||||
// Address is the MANDATORY address to measure.
|
// Address is the MANDATORY address to measure.
|
||||||
Address string
|
Address string
|
||||||
|
|
||||||
|
// EnableTLS OPTIONALLY enables TLS.
|
||||||
|
EnableTLS bool
|
||||||
|
|
||||||
// Endpoint is the MANDATORY endpoint to connect to.
|
// Endpoint is the MANDATORY endpoint to connect to.
|
||||||
Endpoint string
|
Endpoint string
|
||||||
|
|
||||||
// NewDialer is the MANDATORY factory for creating a new dialer.
|
// NewDialer is the MANDATORY factory for creating a new dialer.
|
||||||
NewDialer func() model.Dialer
|
NewDialer func() model.Dialer
|
||||||
|
|
||||||
|
// NewTSLHandshaker is the MANDATORY factory for creating a new handshaker.
|
||||||
|
NewTSLHandshaker func() model.TLSHandshaker
|
||||||
|
|
||||||
// Out is the MANDATORY where we'll post the TCP measurement results.
|
// Out is the MANDATORY where we'll post the TCP measurement results.
|
||||||
Out chan *tcpResultPair
|
Out chan *tcpResultPair
|
||||||
|
|
||||||
|
// URLHostname is the MANDATORY URL.Hostname() to use.
|
||||||
|
URLHostname string
|
||||||
|
|
||||||
// Wg is MANDATORY and is used to sync with the parent.
|
// Wg is MANDATORY and is used to sync with the parent.
|
||||||
Wg *sync.WaitGroup
|
Wg *sync.WaitGroup
|
||||||
}
|
}
|
||||||
|
|
||||||
// tcpDo performs the TCP check.
|
// tcpDo performs the TCP check.
|
||||||
func tcpDo(ctx context.Context, config *tcpConfig) {
|
func tcpDo(ctx context.Context, config *tcpConfig) {
|
||||||
const timeout = 10 * time.Second
|
const timeout = 15 * time.Second
|
||||||
ctx, cancel := context.WithTimeout(ctx, timeout)
|
ctx, cancel := context.WithTimeout(ctx, timeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
defer config.Wg.Done()
|
defer config.Wg.Done()
|
||||||
|
@ -58,6 +74,7 @@ func tcpDo(ctx context.Context, config *tcpConfig) {
|
||||||
Address: config.Address,
|
Address: config.Address,
|
||||||
Endpoint: config.Endpoint,
|
Endpoint: config.Endpoint,
|
||||||
TCP: webconnectivity.ControlTCPConnectResult{},
|
TCP: webconnectivity.ControlTCPConnectResult{},
|
||||||
|
TLS: nil, // means: not measured
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
config.Out <- out
|
config.Out <- out
|
||||||
|
@ -67,7 +84,23 @@ func tcpDo(ctx context.Context, config *tcpConfig) {
|
||||||
conn, err := dialer.DialContext(ctx, "tcp", config.Endpoint)
|
conn, err := dialer.DialContext(ctx, "tcp", config.Endpoint)
|
||||||
out.TCP.Failure = tcpMapFailure(newfailure(err))
|
out.TCP.Failure = tcpMapFailure(newfailure(err))
|
||||||
out.TCP.Status = err == nil
|
out.TCP.Status = err == nil
|
||||||
measurexlite.MaybeClose(conn)
|
defer measurexlite.MaybeClose(conn)
|
||||||
|
if err != nil || !config.EnableTLS {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tlsConfig := &tls.Config{
|
||||||
|
NextProtos: []string{"h2", "http/1.1"},
|
||||||
|
RootCAs: netxlite.NewDefaultCertPool(),
|
||||||
|
ServerName: config.URLHostname,
|
||||||
|
}
|
||||||
|
thx := config.NewTSLHandshaker()
|
||||||
|
tlsConn, _, err := thx.Handshake(ctx, conn, tlsConfig)
|
||||||
|
out.TLS = &ctrlTLSResult{
|
||||||
|
ServerName: config.URLHostname,
|
||||||
|
Status: err == nil,
|
||||||
|
Failure: newfailure(err),
|
||||||
|
}
|
||||||
|
measurexlite.MaybeClose(tlsConn)
|
||||||
}
|
}
|
||||||
|
|
||||||
// tcpMapFailure attempts to map netxlite failures to the strings
|
// tcpMapFailure attempts to map netxlite failures to the strings
|
||||||
|
|
|
@ -9,6 +9,9 @@ import (
|
||||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TODO(bassosimone): these struct definitions should be moved outside the
|
||||||
|
// specific implementation of Web Connectivity v0.4.
|
||||||
|
|
||||||
// ControlRequest is the request that we send to the control
|
// ControlRequest is the request that we send to the control
|
||||||
type ControlRequest struct {
|
type ControlRequest struct {
|
||||||
HTTPRequest string `json:"http_request"`
|
HTTPRequest string `json:"http_request"`
|
||||||
|
@ -23,6 +26,14 @@ type ControlTCPConnectResult struct {
|
||||||
Failure *string `json:"failure"`
|
Failure *string `json:"failure"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ControlTLSHandshakeResult is the result of the TLS handshake
|
||||||
|
// attempt performed by the control vantage point.
|
||||||
|
type ControlTLSHandshakeResult struct {
|
||||||
|
ServerName string `json:"server_name"`
|
||||||
|
Status bool `json:"status"`
|
||||||
|
Failure *string `json:"failure"`
|
||||||
|
}
|
||||||
|
|
||||||
// ControlHTTPRequestResult is the result of the HTTP request
|
// ControlHTTPRequestResult is the result of the HTTP request
|
||||||
// performed by the control vantage point.
|
// performed by the control vantage point.
|
||||||
type ControlHTTPRequestResult struct {
|
type ControlHTTPRequestResult struct {
|
||||||
|
@ -67,14 +78,19 @@ const (
|
||||||
|
|
||||||
// ControlIPInfoFlagIsBogon indicates that the address is a bogon
|
// ControlIPInfoFlagIsBogon indicates that the address is a bogon
|
||||||
ControlIPInfoFlagIsBogon
|
ControlIPInfoFlagIsBogon
|
||||||
|
|
||||||
|
// ControlIPInfoFlagValidForDomain indicates that an IP address
|
||||||
|
// is valid for the domain because it works with TLS
|
||||||
|
ControlIPInfoFlagValidForDomain
|
||||||
)
|
)
|
||||||
|
|
||||||
// ControlResponse is the response from the control service.
|
// ControlResponse is the response from the control service.
|
||||||
type ControlResponse struct {
|
type ControlResponse struct {
|
||||||
TCPConnect map[string]ControlTCPConnectResult `json:"tcp_connect"`
|
TCPConnect map[string]ControlTCPConnectResult `json:"tcp_connect"`
|
||||||
HTTPRequest ControlHTTPRequestResult `json:"http_request"`
|
TLSHandshake map[string]ControlTLSHandshakeResult `json:"tls_handshake"`
|
||||||
DNS ControlDNSResult `json:"dns"`
|
HTTPRequest ControlHTTPRequestResult `json:"http_request"`
|
||||||
IPInfo map[string]*ControlIPInfo `json:"ip_info"`
|
DNS ControlDNSResult `json:"dns"`
|
||||||
|
IPInfo map[string]*ControlIPInfo `json:"ip_info"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Control performs the control request and returns the response.
|
// Control performs the control request and returns the response.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user