Git Product home page Git Product logo

smokescreen's Introduction

Smokescreen Test Coverage Status

Smokescreen is a HTTP CONNECT proxy. It proxies most traffic from Stripe to the external world (e.g., webhooks).

Smokescreen restricts which URLs it connects to:

  • It uses a pre-configured hostname ACL to only allow requests addressed to certain allow-listed hostnames, to ensure that no malicious code is attempting to make requests to unexpected services.
  • It also resolves each domain name that is requested, and ensures that it is a publicly routable IP address and not an internal IP address. This prevents a class of attacks where, for instance, our own webhooks infrastructure is used to scan Stripe’s internal network. Smokescreen can also be further configured to allow or deny specific IP addresses or ranges.

Smokescreen also allows us to centralize egress from Stripe, allowing us to give financial partners stable egress IP addresses and abstracting away the details of which Stripe service is making the request.

In typical usage, clients contact Smokescreen over mTLS. Upon receiving a connection, Smokescreen authenticates the client's certificate against a configurable set of CAs and CRLs, extracts the client's identity, and checks the client's requested CONNECT destination against a configurable per-client ACL.

By default, Smokescreen will identify clients by the "common name" in the TLS certificate they present, if any. The client identification function can also be easily replaced; more on this in the usage section.

Dependencies

Smokescreen uses go modules to manage dependencies. The linked page contains documentation, but some useful commands are reproduced below:

  • Adding a dependency: go build go test go mod tidy will automatically fetch the latest version of any new dependencies. Running go mod vendor will vendor the dependency.
  • Updating a dependency: go get [email protected] or go get dep@commit-hash will bring in specific versions of a dependency. The updated dependency should be vendored using go mod vendor.

Smokescreen uses a custom fork of goproxy to allow us to support context passing and setting granular timeouts on proxy connections.

Generally, Smokescreen will only support the two most recent Go versions. See the test configuration for details.

Usage

CLI

Here are the options you can give Smokescreen:

   --help                                      Show this help text.
   --config-file FILE                          Load configuration from FILE.  Command line options override values in the file.
   --listen-ip IP                              Listen on interface with address IP.
                                                 This argument is ignored when running under Einhorn. (default: any)
   --listen-port PORT                          Listen on port PORT.
                                                 This argument is ignored when running under Einhorn. (default: 4750)
   --timeout DURATION                          Time out after DURATION when connecting. (default: 10s)
   --proxy-protocol                            Enable PROXY protocol support.
   --deny-range RANGE                          Add RANGE(in CIDR notation) to list of blocked IP ranges.  Repeatable.
   --allow-range RANGE                         Add RANGE (in CIDR notation) to list of allowed IP ranges.  Repeatable.
   --deny-address value                        Add IP[:PORT] to list of blocked IPs.  Repeatable.
   --allow-address value                       Add IP[:PORT] to list of allowed IPs.  Repeatable.
   --egress-acl-file FILE                      Validate egress traffic against FILE
   --expose-prometheus-metrics                 Exposes metrics via a Prometheus scrapable endpoint.
   --prometheus-endpoint ENDPOINT              Specify endpoint to host Prometheus metrics on. (default: "/metrics")
                                                 Requires `--expose-prometheus-metrics` to be set.
   --prometheus-port PORT                      Specify port to host Prometheus metrics on. (default "9810")
                                                 Requires `--expose-prometheus-metrics` to be set.
   --resolver-address ADDRESS                  Make DNS requests to ADDRESS (IP:port).  Repeatable.
   --statsd-address ADDRESS                    Send metrics to statsd at ADDRESS (IP:port). (default: "127.0.0.1:8200")
   --tls-server-bundle-file FILE               Authenticate to clients using key and certs from FILE
   --tls-client-ca-file FILE                   Validate client certificates using Certificate Authority from FILE
   --tls-crl-file FILE                         Verify validity of client certificates against Certificate Revocation List from FILE
   --additional-error-message-on-deny MESSAGE  Display MESSAGE in the HTTP response if proxying request is denied
   --disable-acl-policy-action POLICY ACTION   Disable usage of a POLICY ACTION such as "open" in the egress ACL
   --stats-socket-dir DIR                      Enable connection tracking. Will expose one UDS in DIR going by the name of "track-{pid}.sock".
                                                 This should be an absolute path with all symlinks, if any, resolved.
   --stats-socket-file-mode FILE_MODE          Set the filemode to FILE_MODE on the statistics socket (default: "700")
   --version, -v                               print the version

Client Identification

In order to override how Smokescreen identifies its clients, you must:

  • Create a new go project
  • Import Smokescreen
  • Create a Smokescreen configuration using cmd.NewConfiguration
  • Replace smokescreen.Config.RoleFromRequest with your own func(request *http.Request) (string, error)
  • Call smokescreen.StartWithConfig
  • Build your new project and use the resulting executable through its CLI

Here is a fictional example that would split a client certificate's OrganizationalUnit on commas and use the first particle as the service name.

package main

import (...)

func main() {
	// Here is an opportunity to pass your logger
	conf, err := cmd.NewConfiguration(nil, nil)
	if err != nil {
		log.Fatal(err)
	}
	if conf == nil {
		os.Exit(1)
	}

	conf.RoleFromRequest = func(request *http.Request) (string, error) {
		fail := func(err error) (string, error) { return "", err }

		subject := request.TLS.PeerCertificates[0].Subject
		if len(subject.OrganizationalUnit) == 0 {
			fail(fmt.Errorf("warn: Provided cert has no 'OrganizationalUnit'. Can't extract service role."))
		}
		return strings.SplitN(subject.OrganizationalUnit[0], ".", 2)[0], nil
	}

	smokescreen.StartWithConfig(conf, nil)
}

IP Filtering

To control the routing of requests to specific IP addresses or IP blocks, use the deny-address, allow-address, deny-range, and allow-range options in the config.

Hostname ACLs

A hostname ACL can be described in a YAML formatted file. The ACL, at its top-level, contains a list of services as well as a default behavior.

Three policies are supported:

Policy Behavior
Open Allows all traffic for this service
Report Allows all traffic for this service and warns if client accesses a remote host which is not in the list
Enforce Only allows traffic to remote hosts provided in the list. Will warn and deny if remote host is not in the list

⚠️ The ACL is only applied to hostnames as they appear in the request! If you want to allow or deny traffic based on the destination IP address after DNS resolution, you should be using the config options instead (see the IP Filtering section above).

A host can be specified with or without a globbing prefix. The host (without the globbing prefix) must be in Punycode to prevent ambiguity.

host valid
example.com yes
*.example.com yes
api.*.example.com no
*example.com no
ex*ample.com no
éxämple.com no
example.* hell no

Here is a sample ACL.

Global Hostname Allow/Deny Lists

Optionally, you may specify a global allow list and a global deny list for hostnames in your ACL config.

These lists override the policy, but do not override the allowed_domains list for each role.

For example, specifying example.com in your global_allow_list will allow traffic for that domain on that role, even if that role is set to enforce and does not specify example.com in its allowed domains.

Similarly, specifying malicious.com in your global_deny_list will deny traffic for that domain on a role, even if that role is set to report or open. However, if the host specifies malicious.com in its allowed_domains, traffic to malicious.com will be allowed on that role, regardless of policy.

⚠️ The global_deny_list will only block specific hostnames, not entire destinations. For example, if malicious.com is in the global_deny_list but the IP address that it resolves to is not, roles with an open policy will still be able to access the destination by using its IP address directly. For this reason, we recommend using allowlists instead of denylists whenever it is possible to do so, and blocking IP addresses via config options, not the ACL (see the IP Filtering section above).

If a domain matches both the global_allow_list and the global_deny_list, the global_deny_list behavior takes priority.

Here is a sample ACL specifying these options.

Development and Testing

Running locally

To run Smokescreen locally, you can provide a minimal configuration file and use curl as a client. For example:

# config.yaml
---
allow_missing_role: true  # skip mTLS client validation
statsd_address: 127.0.0.1:8200

If you want to see metrics Smokescreen emits, listen on a local port:

$ nc -uklv 127.0.0.1 8200

Build and run Smokescreen:

$ go run . --config-file config.yaml
{"level":"info","msg":"starting","time":"2022-11-30T15:19:08-08:00"}

Make a request using curl:

$ curl --proxytunnel -x localhost:4750 https://stripe.com/

Testing

$ go test ./...

Contributors

  • Aditya Mukerjee
  • Andreas Fuchs
  • Andrew Dunham
  • Andrew Metcalf
  • Aniket Joshi
  • Ben Ransford
  • Carl Jackson
  • Craig Shannon
  • Evan Broder
  • Marc-André Tremblay
  • Ryan Koppenhaver

smokescreen's People

Contributors

adunham-stripe avatar ajj-stripe avatar alexmv avatar andrew-stripe avatar anktjsh-stripe avatar antifuchs avatar cds2-stripe avatar chimeracoder avatar cmoresco-stripe avatar dependabot[bot] avatar dougbarth-stripe avatar eastebry avatar evan-stripe avatar hans-stripe avatar jjiang-stripe avatar julia-stripe avatar kevinv-stripe avatar lewandowski-stripe avatar pspieker-stripe avatar qaisjp avatar ransford-stripe avatar raylu-stripe avatar rlk-stripe avatar rwg-stripe avatar sergeyrud-stripe avatar sheng-stripe avatar stripecodahale avatar tdesrosiers-stripe avatar tremblay-stripe avatar xieyuxi-stripe avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

smokescreen's Issues

--resolver-address is accepted multiple times, but causes an error at runtime

The docs suggest that the --resolver-address flag can be provided multiple times, e.g.

   --resolver-address ADDRESS                  Make DNS requests to ADDRESS (IP:port).  Repeatable.

However, trying to start smokescreen with multiple resolvers fails:

{"level":"fatal","msg":"Could not create configuration: only one resolver address allowed, 2 provided","time":"2024-02-01T23:20:40.712120055Z"}

It appears support for multiple resolvers hasn't been implemented in the code yet:

// TODO: support round-robin between multiple addresses

Perhaps the docs should be updated first to reflect this, as I suspect the feature itself is nontrivial to implement?

Sample config returns errors

Using a clean installation and without touching the sample configuration file, the following error occurs:

$ git clone [email protected]:stripe/smokescreen.git
Cloning into 'smokescreen'...
remote: Enumerating objects: 9067, done.
remote: Counting objects: 100% (1744/1744), done.
remote: Compressing objects: 100% (955/955), done.
remote: Total 9067 (delta 947), reused 1123 (delta 711), pack-reused 7323
Receiving objects: 100% (9067/9067), 21.03 MiB | 10.16 MiB/s, done.
Resolving deltas: 100% (4297/4297), done.

$ cd smokescreen
$ nano smokescreen.yaml
$ go run . --config-file smokescreen.yaml

{
   "level":"fatal",
   "msg":"Could not create configuration: Couldn't load file \"smokescreen.yaml\" specified by --config-file: yaml: unmarshal errors:\n  line 2: field version not found in type smokescreen.yamlConfig\n  line 3: field services not found in type smokescreen.yamlConfig\n  line 28: field default not found in type smokescreen.yamlConfig",
   "time":"2024-05-28T16:03:05.811872+02:00"
}
exit status 1

Running version: go version go1.22.2 darwin/amd64 (exact same result for go version go1.20.14 darwin/amd64)

Mutual TLS failure

I was hoping to be able to authenticate with this proxy using client tls auth. So I generated a server cert+key from my custom ca, and generated a client+key from the same custom ca. I then started the application which the following args:

--tls-server-bundle-file /server.pem
--tls-client-ca-file /ca.crt

I then connected using openssl's s_client, using the client cert and key, and saw that it worked.

I then removed the client and key to get rid of the client auth and repeated the experiment with s_client. It still worked. It was not denying my access due to the lack of client TLS.

So I re-read the docs and noticed that you're supposed to supply a crl file too. So I generated one for the CA using easyrsa gencrl and restarted the server with the args:

--tls-crl-file /crl.pem
--tls-server-bundle-file /server.pem
--tls-client-ca-file /ca.crt

No difference. It still allowed proxying whether or not I do client tls. However, this time it spits out an extra error that the CRL doesn't match the CA at startup:

{"level":"info","msg":"warn: CRL loaded for issuer 'ee6a2f448e7c9b7a2b8955a50bc34da7bacc3509' but no such CA loaded: ignoring it\n","time":"2021-12-14T10:56:28.0796894Z"}
0 loaded certs
info: Loaded CA with Authority ID 'ee6a2f448e7c9b7a2b8955a50bc34da7bacc3509'
{"level":"info","msg":"starting","time":"2021-12-14T10:56:28Z"}

You'll notice that the two hashes are the same and that the CRL error comes before the "Loaded CA" log. Not sure if that's relevant. I tried changing the order of the command line args and it made no difference.

Now, I could be misunderstanding what these args do, or there could be a bug, I'm not sure. I just want to be able to tell the server to only allow proxying when client tls has occurred and the clients cert is signed by the provided CA. Is that an option?

"Failed to connect to remote host: <nil>" error log

I recently upgraded my Docker image to use the latest commit on the master branch of Smokescreen (c86310d).

Right after a connection is allowed through the proxy, I'm occasionally seeing this error log message Failed to connect to remote host: <nil> but of course <nil> doesn't contain any helpful information.

It seems like this problem might be related to the recent change in #194?
I'm not very experienced with Go but reading the code, I'm not sure how e.Error() is returning nil.

Binary releases

First of all, thanks for maintaining this! We've just completed some work to migrate from our internally managed years-old version of this to this upstream version and it squashed a few bugs. We have made a fork that creates binaries for use as a dev dependency and to Dockerize for an ECS service and it's working well for us here at Buildkite. 💙

We'd love to see you officially release static-linked binaries for Smokescreen so that we can depend directly on them without having to maintain a fork. For an example of what we mean, here's some of our own releases: https://github.com/buildkite/smokescreen/releases

Support upstream proxies

Hello! I'm not sure if this project is still maintained, or if this is a feature you are interested in supporting within Smokescreen.

I'd like to be able to configure smokescreen so that it forwards (allowed) requests to an upstream proxy. Go programs generally respect the http_proxy, https_proxy, no_proxy environment variables. Running smokescreen with this invocation almost works:

$ HTTP_PROXY=http://10.0.0.1:9999 HTTPS_PROXY=http://10.0.0.1:9999 ./smokescreen --allow-range 10.0.0.1/32

HTTP connections work, CONNECT requests will give this error:

 level":"error","msg":"Failed to connect to remote host: parse \"192.168.0.12:9999\": first path segment in URL cannot contain colon"

I've traced this error back to stripe/goproxy, and opened a PR: stripe/goproxy#18. CONNECT requests should work after merging this PR.

Thanks! If upstream proxies is not a feature you want to support, no worries, I'll look elsewhere.

Golang 1.17 adds a new IP.IsPrivate function we could use

https://pkg.go.dev/net#IP.IsPrivate

This function could be used instead of our own PrivateRuleRanges,

} else if addrIsInRuleRange(PrivateRuleRanges, addr) && !config.UnsafeAllowPrivateRanges {

https://github.com/stripe/smokescreen/blob/master/pkg/smokescreen/constants.go#L20-L25
https://github.com/stripe/smokescreen/blob/master/pkg/smokescreen/constants.go#L38-L45

As Smokescreen supports the two most recent Go releases, we should wait until 1.18 is released so that we can support both 1.17 and 1.18

smokescreen refuses to use upstream proxy with internal address

Run smokescreen as follows:

$ http_proxy=http://localhost:1234/ ./smokescreen

Now try to tunnel a request through it:

$ http_proxy=http://localhost:4750/ curl http://yahoo.com/
Failed to connect to remote host: proxyconnect tcp: The destination address (127.0.0.1) was denied by rule 'Deny: Not Global Unicast'

The smokescreen log is as follows:

{"level":"info","msg":"starting","time":"2023-06-22T12:09:26+03:00"}
{"address":"localhost:1234","error":"The destination address (127.0.0.1) was denied by rule 'Deny: Not Global Unicast'","level":"error","msg":"unexpected illegal address in dialer","time":"2023-06-22T12:10:39+03:00"}
{"id":"cia103qhq4rca8e50ep0","inbound_remote_addr":"127.0.0.1:52026","level":"error","msg":"Failed to connect to remote host: proxyconnect tcp: The destination address (127.0.0.1) was denied by rule 'Deny: Not Global Unicast'","proxy_type":"http","requested_host":"yahoo.com","start_time":"2023-06-22T09:10:39.498762117Z","time":"2023-06-22T12:10:39+03:00","trace_id":""}
{"allow":true,"content_length":134,"decision_reason":"destination address was denied by rule, see error","dns_lookup_time_ms":9,"enforce_would_deny":false,"error":"proxyconnect tcp: The destination address (127.0.0.1) was denied by rule 'Deny: Not Global Unicast'","id":"cia103qhq4rca8e50ep0","inbound_remote_addr":"127.0.0.1:52026","level":"error","msg":"CANONICAL-PROXY-DECISION","project":"","proxy_type":"http","requested_host":"yahoo.com","role":"","start_time":"2023-06-22T09:10:39.498762117Z","time":"2023-06-22T12:10:39+03:00","trace_id":""}

I think this behavior is incorrect, because the address of the proxy is supplied by the system administrator, and so should be considered trusted. The request should thus be allowed to go through.

Reproduced on 8dd3072.

Prometheus stats naming and histogram cleanup

The default Prometheus metrics contain histograms for in and out byte counts. However, they use the default histogram buckets, which means that they measure up to 10 bytes, and down to 0.005 bytes:

# HELP cn_bytes_in
# TYPE cn_bytes_in histogram
cn_bytes_in_bucket{role="",le="0.005"} 0
cn_bytes_in_bucket{role="",le="0.01"} 0
cn_bytes_in_bucket{role="",le="0.025"} 0
cn_bytes_in_bucket{role="",le="0.05"} 0
cn_bytes_in_bucket{role="",le="0.1"} 0
cn_bytes_in_bucket{role="",le="0.25"} 0
cn_bytes_in_bucket{role="",le="0.5"} 0
cn_bytes_in_bucket{role="",le="1"} 0
cn_bytes_in_bucket{role="",le="2.5"} 0
cn_bytes_in_bucket{role="",le="5"} 0
cn_bytes_in_bucket{role="",le="10"} 0
cn_bytes_in_bucket{role="",le="+Inf"} 1
cn_bytes_in_sum{role=""} 22925
cn_bytes_in_count{role=""} 1
# HELP cn_bytes_out
# TYPE cn_bytes_out histogram
cn_bytes_out_bucket{role="",le="0.005"} 0
cn_bytes_out_bucket{role="",le="0.01"} 0
cn_bytes_out_bucket{role="",le="0.025"} 0
cn_bytes_out_bucket{role="",le="0.05"} 0
cn_bytes_out_bucket{role="",le="0.1"} 0
cn_bytes_out_bucket{role="",le="0.25"} 0
cn_bytes_out_bucket{role="",le="0.5"} 0
cn_bytes_out_bucket{role="",le="1"} 0
cn_bytes_out_bucket{role="",le="2.5"} 0
cn_bytes_out_bucket{role="",le="5"} 0
cn_bytes_out_bucket{role="",le="10"} 0
cn_bytes_out_bucket{role="",le="+Inf"} 1
cn_bytes_out_sum{role=""} 516
cn_bytes_out_count{role=""} 1

Per the prometheus best practices, bytes is the canonical unit to use here, which means that we should be adjusting the bucketcount. The same applies to a lesser degree with proxy_duration_ms_timer_bucket -- but in general Prometheus timing metrics use seconds as their unit, rather than shifting the buckets upwards. cn_duration_bucket, by contrast, is in seconds (and doesn't use TimingWithTags, possibly for that reason?)

Based on that same link, the names for the Prometheus metrics are also pretty non-standard -- cn_atpt_total would more canonically be smokescreen_connection_attempt_count, for instance. We could hardcode a mapping of statsd name to prometheus name in sanitisePrometheusMetricName, but I don't love that -- nor polluting the interface with a function per metric name.

Regarding the option configuration of multiple IPs or multiple domain names

When configuring multiple IPs using the --allow-address option, Setting environment variable:

SMOKESCREEN_OPTS=--allow-address=10.20.50.24;10.12.0.21

Then configure it in supervisord:

[program:smokescreen]
command=smokescreen --listen-ip=127.0.0.1 %(ENV_SMOKESCREEN_OPTS)s

I found that smokescreen failed to start, prompting an address parsing error. How to modify this?

Similarly, if i want to set up matching for multiple domain names or generic domain names, how should you configure it?

Unify the ACL interface

Currently smokescreen uses different interfaces to determine if resolved addrs and outbound domains should be allowed. We should unify this behavior behind the acl package.

Use a smokescreen struct over a config pointer to share global state

Currently we pass a pointer to a config object across functions to share global state. It would be more idiomatic to:

  • Use functional options to generate a config object at runtime
  • Use this config to build a Smokescreen struct
  • Have functions which require access to the global smokescreen state implemented as pointer receivers

Add a command-line option to allow destinations by domain name

Currently it seems like the only options to allow internal destinations are by IP address range --allow-range or by IP address (--allow-address). It would be useful if I could allow specific domain names as well (e.g. --allow-domain=my-server, or --allow-domain=*.my-domain.com).

It seems that this is already possible with an ACL file, but it would be nice to be able to set this via command-line options too.

New release?

Hi!

I was wondering whether there is a plan to cut a new release. Looking the last one was 2022, I am specially interested on this issue:

Global allow list should be respected even if the address resolves to an internal IP

disclaimer: I have not tried this yet to see the actual behavior so let me know if I am wrong

In checkIfRequestShouldBeProxied() we can see safeResolve is called on every allow. So if the host resolves to an internal IP it is going to get denied. It would be great if global_allow_list was honored even if the ip resolves to an internal address (either as default or by passing some flag)

My current workaround would be to just use --unsafe-allow-private-ranges when I only want to allow some dynamic ip for a known internal hostname

Tests at HEAD currently fail

At commit 14a7af2

% go version
go version go1.20.6 linux/amd64
--- FAIL: TestInvalidUpstreamProxyConfiguration (0.16s)
    --- FAIL: TestInvalidUpstreamProxyConfiguration/illegal_proxy_with_CONNECT_false (0.15s)
        integration_test.go:258: Executing Request for test case &cmd.TestCase{ExpectAllow:false, Action:0, ExpectStatus:502, OverTLS:false, OverConnect:false, ProxyURL:"http://127.0.0.1:45773", RandomTrace:0, TargetURL:"http://checkip.amazonaws.com:80", RoleName:"open", UpstreamProxy:"http://notaproxy.prxy.svc:80"}
        integration_test.go:253: HTTP Request: &http.Request{Method:"GET", URL:(*url.URL)(0xc0001318c0), Proto:"HTTP/1.1", ProtoMajor:1, ProtoMinor:1, Header:http.Header{"X-Smokescreen-Role":[]string{"egressneedingservice-open"}, "X-Smokescreen-Trace-Id":[]string{"0"}}, Body:io.ReadCloser(nil), GetBody:(func() (io.ReadCloser, error))(nil), ContentLength:0, TransferEncoding:[]string(nil), Close:false, Host:"checkip.amazonaws.com:80", Form:url.Values(nil), PostForm:url.Values(nil), MultipartForm:(*multipart.Form)(nil), Trailer:http.Header(nil), RemoteAddr:"", RequestURI:"", TLS:(*tls.ConnectionState)(nil), Cancel:(<-chan struct {})(nil), Response:(*http.Response)(nil), ctx:(*context.emptyCtx)(0xc000196010)}
        integration_test.go:441: HTTP Response: &http.Response{Status:"200 OK", StatusCode:200, Proto:"HTTP/1.1", ProtoMajor:1, ProtoMinor:1, Header:http.Header{"Connection":[]string{"keep-alive"}, "Content-Length":[]string{"14"}, "Content-Type":[]string{"text/plain; charset=utf-8"}, "Date":[]string{"Sun, 30 Jul 2023 21:35:34 GMT"}, "Server":[]string{"lighttpd/1.4.53"}}, Body:(*http.bodyEOFSignal)(0xc0003067c0), ContentLength:14, TransferEncoding:[]string(nil), Close:false, Uncompressed:false, Trailer:http.Header(nil), Request:(*http.Request)(0xc000328b00), TLS:(*tls.ConnectionState)(nil)}
        integration_test.go:446:
                Error Trace:    /home/raggi/src/github.com/stripe/smokescreen/cmd/integration_test.go:446
                                                        /home/raggi/src/github.com/stripe/smokescreen/cmd/integration_test.go:495
                Error:          Not equal:
                                expected: 502
                                actual  : 200
                Test:           TestInvalidUpstreamProxyConfiguration/illegal_proxy_with_CONNECT_false
{"level":"info","msg":"Loading egress ACL from testdata/sample_config.yaml","time":"2023-07-30T14:35:34.616048332-07:00"}
2 &smokescreen.Config{Ip:"127.0.0.1", Port:0x128e, Listener:net.Listener(nil), DenyRanges:[]smokescreen.RuleRange{smokescreen.RuleRange{Net:net.IPNet{IP:net.IP{0x1, 0x1, 0x1, 0x1}, Mask:net.IPMask{0xff, 0xff, 0xff, 0xff}}, Port:0}, smokescreen.RuleRange{Net:net.IPNet{IP:net.IP{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x1, 0x0, 0x0, 0x1}, Mask:net.IPMask{0xff, 0xff, 0xff, 0xff}}, Port:123}}, AllowRanges:[]smokescreen.RuleRange{smokescreen.RuleRange{Net:net.IPNet{IP:net.IP{0x7f, 0x0, 0x0, 0x1}, Mask:net.IPMask{0xff, 0xff, 0xff, 0xff}}, Port:0}}, Resolver:(*net.Resolver)(0xc0001ce740), ConnectTimeout:1000000000, ExitTimeout:30000000000000, MetricsClient:(*metrics.StatsdMetricsClient)(0xc000165e90), EgressACL:(*acl.ACL)(0xc00058f260), SupportProxyProtocol:false, TlsConfig:(*tls.Config)(nil), CrlByAuthorityKeyId:map[string]*pkix.CertificateList{}, RoleFromRequest:(func(*http.Request) (string, error))(0x9af360), clientCasBySubjectKeyId:map[string]*x509.Certificate{}, AdditionalErrorMessageOnDeny:"additional_error_message_validation_key", Log:(*logrus.Logger)(0xc0000daa80), DisabledAclPolicyActions:[]string(nil), AllowMissingRole:false, StatsSocketDir:"", StatsSocketFileMode:0x1c0, StatsServer:(*smokescreen.StatsServer)(nil), ConnTracker:(*conntrack.Tracker)(0xc0003075c0), Healthcheck:http.Handler(nil), ShuttingDown:atomic.Value{v:interface {}(nil)}, Network:"ip", IdleTimeout:0, TransportMaxIdleConns:0, TransportMaxIdleConnsPerHost:0, TimeConnect:false, ProxyDialTimeout:(func(context.Context, string, string, time.Duration) (net.Conn, error))(nil), RejectResponseHandler:(func(*http.Response))(nil), AcceptResponseHandler:(func(*http.Response))(nil), UnsafeAllowPrivateRanges:false, PostDecisionRequestHandler:(func(*http.Request) error)(nil)}
time="2023-07-30T14:35:34-07:00" level=info msg=CANONICAL-PROXY-DECISION allow=true decision_reason="rule has open enforcement policy" dns_lookup_time_ms=0 enforce_would_deny=false id=cj3df9gb12uv6inebpeg inbound_remote_addr="127.0.0.1:52938" project=test proxy_type=connect requested_host="127.0.0.1:37279" role=egressneedingservice-open start_time="2023-07-30 21:35:34.616427321 +0000 UTC" trace_id=
time="2023-07-30T14:35:34-07:00" level=info msg=CANONICAL-PROXY-CN-CLOSE bytes_in=0xc0002cb1a8 bytes_out=0xc0002cb1b0 conn_establish_time_ms=0 duration=0.0002938 end_time="2023-07-30 21:35:34.616877373 +0000 UTC" error= id=cj3df9gb12uv6inebpeg inbound_remote_addr="127.0.0.1:52938" last_activity="2023-07-30 21:35:34.616859129 +0000 UTC" outbound_remote_addr="127.0.0.1:37279" project=test proxy_type=connect requested_host="127.0.0.1:37279" role=egressneedingservice-open start_time="2023-07-30 21:35:34.616427321 +0000 UTC" trace_id=
FAIL
FAIL    github.com/stripe/smokescreen/cmd       1.034s

Add simple godoc

Golint rightly complains (WIP: #94) about missing comments on public things, go doc github.com/stripe/smokescreen is empty, and go doc github.com/stripe/smokescreen/pkg/smokescreen currently pulls a package comment from logruswriter.go. Happy to volunteer, but adding this to track the effort.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.