= go-camo :toc: macro :hide-uri-scheme: ifdef::env-github[] :toc-title: :tip-caption: :bulb: :note-caption: :bulb: :important-caption: :heavy_exclamation_mark: :caution-caption: :fire: :warning-caption: :warning: endif::[]
// some links :link-atmos-camo: https://github.com/atmos/camo[camo] :link-hmac: https://en.wikipedia.org/wiki/HMAC[HMAC] :link-hsts: https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security[HSTS] :link-asciidoctor: https://asciidoctor.org[asciidoctor] :link-damontools: https://cr.yp.to/daemontools.html[daemontools] :link-runit: https://en.wikipedia.org/wiki/Runit[runit] :link-upstart: https://en.wikipedia.org/wiki/Upstart_(software)[upstart] :link-launchd: https://en.wikipedia.org/wiki/Launchd[launchd] :link-systemd: https://www.freedesktop.org/wiki/Software/systemd/[systemd] :link-daemontools-why: https://cr.yp.to/daemontools/faq/create.html#why[daemontools/why] :link-heroku-buildpack-go: https://github.com/kr/heroku-buildpack-go :link-dns-rebinding: https://en.wikipedia.org/wiki/DNS_rebinding[dns rebinding] :link-ip6-special-addresses: https://en.wikipedia.org/wiki/IPv6_address#Special_addresses :link-docker-containers: https://hub.docker.com/r/cactus4docker/go-camo[docker hub] :link-github-containers: https://github.com/cactus/go-camo/pkgs/container/go-camo[github packages] :link-releases: https://github.com/cactus/go-camo/releases[binary releases] :link-mit-license: https://www.opensource.org/licenses/mit-license.php[MIT license] :link-mrsaints: https://github.com/MrSaints[MrSaints] :link-arachnys-fork: https://github.com/arachnys/go-camo[fork]
image:https://img.shields.io/github/release/cactus/go-camo.svg[Current Release,link=http://github.com/cactus/go-camo/releases] image:https://img.shields.io/docker/image-size/cactus4docker/go-camo?label=container%20size[Container Image Size (latest by date),link=https://hub.docker.com/r/cactus4docker/go-camo] image:https://github.com/cactus/go-camo/workflows/unit-tests/badge.svg[BuildStatus] image:.github/img-readme-license.svg[License,link=https://github.com/cactus/go-camo/blob/master/LICENSE.adoc] // image:https://circleci.com/gh/cactus/go-camo.svg?style=svg[CircleCI,link=https://circleci.com/gh/cactus/go-camo]
ifdef::env-github[] [discrete] == Contents endif::[] toc::[]
== About
go-camo is a go version of a https://github.com/atmos/camo[camo] server.
A camo server is a special type of image proxy that proxies non-secure images over SSL/TLS, in order to prevent mixed content warnings on secure pages. The server works in conjunction with back-end code that rewrites image URLs and signs them with an {link-hmac}.
== How it works
The general steps are as follows:
+----------+ request +-------------+ | -----------------------------> | ||
---|---|---|---|
web-app | |||
img src=https://go-camo/url | |||
<----------------------------- | |||
+-------------+ | |||
client | |||
https://go-camo/url +-------------+ http://some/img | |||
-----------------------------> | ---------------> | ||
go-camo | |||
img data | img data | ||
<----------------------------- | <--------------- | ||
+-------------+ |
Go-Camo supports both hex and base64 encoded urls at the same time.
[%header%autowidth.stretch] |=== | encoding | tradeoffs | hex | longer, case insensitive, slightly faster | base64 | shorter, case sensitive, slightly slower |===
Benchmark results with go1.12.7:
For examples of url generation, see the link:examples/[examples] directory.
While Go-Camo will support proxying HTTPS images as well, for performance reasons you may choose to filter HTTPS requests out from proxying, and let the client simply fetch those as they are. The linked code examples do this.
Note that it is recommended to front Go-Camo with a CDN when possible.
== Differences from Camo
== Installing pre-built binaries
Download the tarball appropriate for your OS/ARCH from {link-releases}. + Extract, and copy files to desired locations.
== Building
Building requires:
Building:
$ git clone git@github.com:cactus/go-camo $ cd go-camo
$ make Available targets: help this help clean clean up all build binaries and man pages check run checks and validators test run tests cover run tests with cover output build build all binaries man build all man pages tar build release tarball cross-tar cross compile and build release tarballs
$ make all
== Running
$ go-camo -k "somekey"
Go-Camo does not daemonize on its own. For production usage, it is recommended to launch in a process supervisor, and drop privileges as appropriate.
Examples of supervisors include: {link-damontools}, {link-runit}, {link-upstart}, {link-launchd}, {link-systemd}, and many more.
For the reasoning behind lack of daemonization, see {link-daemontools-why}. In addition, the code is much simpler because of it.
== Running on Heroku
In order to use this on Heroku with the provided Procfile, you need to:
GOCAMO_HMAC
to the key you are using== Securing an installation
go-camo will generally do what you tell it to with regard to fetching signed urls. There is some limited support for trying to prevent {link-dns-rebinding} attacks.
go-camo will attempt to reject any address matching an rfc1918 network block, or a private scope ipv6 address, be it in the url or via resulting hostname resolution.
Please note, however, that this does not provide protection for a network that uses public address space (ipv4 or ipv6), or some of the {link-ip6-special-addresses}[more exotic] ipv6 addresses.
The list of networks rejected includes...
[%header%autowidth.stretch] |=== | Network | Description
| 127.0.0.0/8
| loopback
| 169.254.0.0/16
| ipv4 link local
| 10.0.0.0/8
| rfc1918
| 172.16.0.0/12
| rfc1918
| 192.168.0.0/16
| rfc1918
| ::1/128
| ipv6 loopback
| fe80::/10
| ipv6 link local
| fec0::/10
| deprecated ipv6 site-local
| fc00::/7
| ipv6 ULA
| ::ffff:0:0/96
| IPv4-mapped IPv6 address
|===
More generally, it is recommended to either:
private-address
functionality).
This is also useful to help prevent dns rebinding in general.== Configuring
=== Environment Vars
GOCAMO_HMAC
- HMAC key to use.HTTPS_PROXY
- Configure an outbound proxy for HTTPS requests. +
Either a complete URL or a host[:port]
, in which case an HTTP scheme
is assumed. See <HTTP_PROXY
- Configure an outbound proxy for HTTP requests. +
Either a complete URL or a host[:port]
, in which case an HTTP scheme
is assumed. See <=== Command line flags
$ go-camo -h Usage: go-camo [flags]
An image proxy that proxies non-secure images over SSL/TLS
A few notes about specific flags:
--filter-ruleset
--
If a filter-ruleset
file is defined,
that file is read and each line is converted into a filter rule.
See link:man/go-camo-filtering.5.adoc[go-camo-filtering(5)
]
for more information regarding the format for the filter file itself.
Regarding evaluation: The ruleset is NOT evaluated in-order. The rules process in two phases: "allow rule phase" where the allow rules are evaluated, and the "deny rule phase" where the deny rules are evaluated. First match in each phase "wins" that phase.
In the "allow phase", an origin request must match at least one allow rule. The first rule to match "wins" and the request moves on to the next phase. If there are no allow rules supplied, this phase is skipped.
In the deny rule phase, any rule that matches results in a rejection. The first match "wins" and the request is failed. If there are no deny rules supplied, this phase is skipped.
filter-ruleset
functionality (both allow and deny) is supplied
predominantly as a fallback safety measure,
for cases where you have previously generated a URL and you need a quick temporary fix,
or where rolling keys takes a while and/or is difficult.--
--max-size
--max-size
value is defined in KB.
Set to 0
to disable size restriction.
The default is 0
.--metrics
metrics
flag is provided, then the service will expose a Prometheus
/metrics
endpoint and a /debug/vars
endpoint from the go expvar
package.--no-debug-vars
no-debug-vars
flag is provided along with the metrics
flag, the
/debug/vars
endpoint is removed.-k
, --key
-H, --header
-- Additional default headers (sent on every response) can also be set. This argument may be specified many times.
The list of default headers sent are:
As an example, if you wanted to return a Strict-Transport-Security
header
by default, you could add this to the command line:
--
--allow-content-video
and --allow-content-audio
--
By default only image/*
content-types are accepted and proxied, all other
content-types are rejected.
Add the --allow-content-video
argument to addtionally allow video/*
content
types.
--allow-content-audio
argument to addtionally allow audio/*
content
types.== Upstream Http Proxying
Care should be taken when using upstream http proxy support. go-camo has several protections against SSRF vectors, for example:
The use of an upstream http proxy may subvert several of these protections, as go-camo will be required to offload certain operations to the upstream http proxy.
Some examples (list is not exhaustive):
Proper configuration of the upstream http proxy may mitigate these issues. + Test your configurations and monitor carefully!
== Monitoring
=== Metrics
When the --metrics
flag is used,
the service will expose a Prometheus-compatible /metrics
endpoint.
This can be used by monitoring systems to gather data.
The endpoint includes all of the default go_
and process_
.
In addition, a number of custom metrics.
[%header%autowidth.stretch] |=== | Name | Type | Help
| camo_response_duration_seconds | Histogram | A histogram of latencies for proxy responses.
| camo_response_size_bytes | Histogram | A histogram of sizes for proxy responses.
| camo_proxy_content_length_exceeded_total | Counter | The number of requests where the content length was exceeded.
| camo_proxy_reponses_failed_total | Counter | The number of responses that failed to send to the client.
| camo_proxy_reponses_truncated_total | Counter | The number of responses that were too large to send.
| camo_responses_total | Counter | Total HTTP requests processed by the go-camo, excluding scrapes. |===
It also includes a camo_build_info
metric that exposes the version.
In addition, you can expose some extra data to metrics via env vars, if desired:
APP_INFO_REVISION
APP_INFO_BRANCH
APP_INFO_BUILD_DATE
APP_INFO_VERSION
A /debug/vars
endpoint is also included with --metrics
by default.
This endpoint returns memstats and some additional data. This endpoint can be
disabled by additionally supplying the --no-debug-vars
flag.
== Additional tools
Go-Camo includes a couple of additional tools.
=== url-tool
The url-tool
utility provides a simple way to generate signed URLs
from the command line.
$ url-tool -h Usage: url-tool [OPTIONS] <decode | encode>
Application Options: -k, --key= HMAC key -p, --prefix= Optional URL prefix used by encode output
Help Options: -h, --help Show this help message
Example usage:
$ url-tool -k "test" encode -p "https://img.example.org" "http://golang.org/doc/gopher/frontpage.png" https://img.example.org/0f6def1cb147b0e84f39cbddc5ea10c80253a6f3/687474703a2f2f676f6c616e672e6f72672f646f632f676f706865722f66726f6e74706167652e706e67
$ url-tool -k "test" decode "https://img.example.org/0f6def1cb147b0e84f39cbddc5ea10c80253a6f3/687474703a2f2f676f6c616e672e6f72672f646f632f676f706865722f66726f6e74706167652e706e67" http://golang.org/doc/gopher/frontpage.png
$ url-tool -k "test" encode -b base64 -p "https://img.example.org" "http://golang.org/doc/gopher/frontpage.png" https://img.example.org/D23vHLFHsOhPOcvdxeoQyAJTpvM/aHR0cDovL2dvbGFuZy5vcmcvZG9jL2dvcGhlci9mcm9udHBhZ2UucG5n
== Containers
There are containers built automatically from version tags, pushed to both {link-docker-containers} and {link-github-containers}.
These containers are untested and provided only for those with specific containerization requirements. When in doubt, prefer the statically compiled {link-releases}, unless you specifically need a container.
== Changelog
See xref:CHANGELOG.adoc[CHANGELOG].
== License
Released under the {link-mit-license}. See xref:LICENSE.adoc[LICENSE] file for details.