Skip to content

bsycorp/inkfish

Repository files navigation

inkfish

A forward proxy for machines, with access control lists

Build Status

https://hub.docker.com/r/bsycorp/inkfish

About

This is a non-caching forward (aka egress/outbound) proxy, used to implement URL white-listing for applications.

Key features:

  • An outbound proxy designed for machines
  • Can use cloud metadata to determine the identity of an instance
  • Can use Proxy-Authorization header to identify "non-instance" (e.g. codebuild, serverless) workload
  • Per-instance, per-user URL white-lists
  • TLS MITM by default, white-lists all requests at the URL level
  • Optional MITM bypass, by host

Quick Start

You can start the proxy listening on port 8080 with a built-in demo config:

# Start proxy
docker run -p 8080:8080 bsycorp/inkfish:latest /app/inkfish -metadata none -config /config/demo

# Test as anonymous user
export http_proxy=http://localhost:8080
export https_proxy=http://localhost:8080
export no_proxy=127.0.0.1

curl -k https://ifconfig.io/   # This should work for anonymous
curl -k https://google.com/    # This will not work for anonymous user

# Test as an authenticated user
export http_proxy=http://foo:bar@localhost:8080
export https_proxy=http://foo:bar@localhost:8080

curl -k https://google.com/    # This should work

You can find the demo config over here: /testdata/demo_config/. When you are ready to try out your own white-lists, you can mount them into the proxy container from your host:

docker run -v `pwd`/my_config:/config/mine -p 8080:8080 \
    bsycorp/inkfish:latest /app/inkfish -metadata none -config /config/mine

The next step would be to start the proxy in a cloud environment where you can use instance metadata instead of "hard coded" proxy credentials.

How to run

Three distribution mechanisms are offered:

  • Standard docker: bsycorp/inkfish:x.y.z. This is about 30MB and based on minideb. The entry point is a shell.
  • Slim docker: bsycorp/inkfish:x.y.z-slim. A 10MB container with only the static Linux binary. The entry point is the inkfish binary as is customary for containers with no shell.
  • Linux static binary: You can download this from the (releases page)[https://github.com/bsycorp/inkfish/releases].

If you use the slim image, you will also need to mount SSL certificates (configuration of what upstream CAs are trusted) into the container in addition to your proxy configuration files. On a Linux host, this is usually done by volume mounting SSL certs from the host into the container by adding -v /etc/ssl/certs:/etc/ssl/certs to the docker run command.

Command-line arguments

$ docker run bsycorp/inkfish:latest-slim  -h
Usage of /app/inkfish:
  -addr string
    	proxy listen address (default ":8080")
  -cacert string
    	path to CA cert file
  -cakey string
    	path to CA key file
  -client-idle-timeout int
    	client idle timeout (default 300)
  -client-read-timeout int
    	client read timeout
  -client-write-timeout int
    	client write timeout
  -config string
    	path to configuration files (default ".")
  -drain-time int
    	shutdown drain deadline (seconds) (default 30)
  -insecure-test-mode
    	test mode (does not block)
  -metadata string
    	default metadata provider (aws,none) (default "aws")
  -metadata-update-every int
    	metadata update interval (default 10)
  -metrics string
    	metrics provider (none,datadog,prometheus) (default "none")

Configuration file format

The -config argument supplies a path to a directory full of "access control lists" and password file entries.

Passwd files

Passwd files in the config directory must have a .passwd extension. They may contain one or more lines of: <username>:<sha256-of-password> and will be used to verify proxy auth.

It is expected that passwords will generated by infracode / orchestration and have high entropy so a heavyweight password hashing function is not required.

ACL Files

ACL files in the config directory must have a .conf extension. These control what requests will be allowed through the proxy. The general format looks like:

from <user> [user2 user3...]
from ...
url [METHOD,METHOD2] <url-regex> [modifiers]
url ...
s3 <bucket-name> [modifiers]
bypass <host-port-regex>
bypass ...

Blank lines and comments (lines starting with #) are ignored. The from lines gate entry into the ACL. The may be specified as:

  • user:foo - Identifies a client who will supply a proxy-authorization header with a username of foo.
  • tag:foo - Identifies a client whose cloud metadata (e.g. instance ProxyUser tag in AWS) is foo.
  • ANONYMOUS - Identifies a user or system which does not supply a proxy-authorization header and does not have any identifying metadata tags.
  • AUTHENTICATED - Identifies a client with a tag or valid proxy-authorization credentials.
  • ANYONE - Any client. This includes clients with invalid proxy-authorization credentials.

The acl directive is used to permit requests according to a regular expression matching a URL.. You may optionally specify one or more methods in the ACL, causing only requests made with one of the listed methods to match the ACL. Typical "whole-host" acls look like:

  • acl ^http(s)?://foo\.com/

WARNING: it is generally a mistake to forget the trailing /, as this would cause the regular expression to match things like https://foo.com.au/evilthing as well as the intended domain https://foo.com/. Similarly, it is usually a mistake to forget to escape dots with backslashes as this can also cause unintended matches.

A more complex acl example might look like:

  • acl HEAD,GET,POST ^http(s)://api\.foo\.com/v2/

The bypass directive is used to disable TLS MITM for specific hosts. You should supply a regular expression which can be matched directly against the client's CONNECT request. For example:

  • bypass ^my-super-bucket\.ap-southeast-2\.amazonaws\.com:443$

There is also a shorthand for a url regex that includes all AWS S3 URL notations (bucket in path and bucket in host) across all regions

  • s3 my-super-bucket

Modifiers alter the processing of a particular ACL. Currently supported modifiers are:

  • quiet - Suppresses logging of successful requests for the URL pattern or S3 bucket. CONNECT will still be logged, but not individual requests. This is useful for thing like SQS or log upload endpoints where many requests are expected under ordinary circumstances.

Metadata lookup

Rather than distributing proxy credentials, the preferred method of access control in inkfish is via cloud instance metadata.

AWS

For AWS, specify the ProxyUser tag on an instance. So for example if you apply tag of ProxyUser=foo, then in your ACL you would write:

from tag:foo
url ^http(s)?://.*$

To grant instances with that tag unrestricted outbound HTTP(s) access.

Health Check

Configure health checks for the service to hit the listening port on /healthz.

Graceful shutdown

Set drain-time to your shutdown connection drain deadline. The default is 30 seconds. If you have a load balancer forwarding requests to inkfish, your load balancer drain time should be higher than this value.

About

A forward proxy for machines, with access control lists

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages