camo-rs is a frontend-compatible Rust-re-implementation of the now archived NodeJS-based atmos/camo - an HTTP proxy for assets (mainly images) to route requests through an always-encrypted connection.
While initially designed for use in diaspora*, asset proxies like this are useful for all applications that display, for example, image files from external sources based on user input and want to avoid mixed-content warnings and reduce the number of external hosts the end-user has to connect to.
To prevent abuse, only authorized URLs can be proxied through Camo. URLs requested from the application need to have the following format:
https://camo.example.org/<digest>/<asset-url>
Where
- the
digestis a 40-character hexadecimal-encoded SHA1 HMAC digest computed with the shared secret key, - the
asset-urlis a hexadecimal representation of the target URL, for example687474703a2f2f65786d61706c652e636f6d2f6578616d706c652e6a7067forhttp://exmaple.com/example.jpg.
There are some differences to the original projects, namely:
- passing the
image-urlvia a query parameter is not supported. camo-rswill not follow redirects. Instead, if a redirect is encountered upstream, the redirect response will be passed to the client, but with thelocationheader modified to show a Camo-proxied version of the original location. This allows clients (and server-side logic) to cache permanent redirects.- In addition to
GETrequests,camo-rsalso acceptsHEADandOPTIONSrequests and passes them through accordingly. This is useful if you want to verify the availability of URLs through Camo on the server side, or if CORS is relevant.
Camo allows users to proxy essentially arbitrary files through it. If your application is vulnerable, Camo could be used to bypass cross-origin boundaries for assets. To reduce the risk a bit, camo-rs will always set the following headers in all of its proxied responses:
content-security-policy: default-src 'none'; img-src data:; style-src 'unsafe-inline'x-content-type-options: nosniffx-frame-options: denyx-xss-protection: 1; mode=block
Which will reduce the amount of things you can do with the proxied resources significantly. In addition, camo-rs filters responses by content-type. Administrators can set flags to allow audio/*, image/*, and video/* MIME types in the config. Other content types will be rejected. camo-rs will reject to proxy resources without a content-type headers set. While providing this header is not required by the spec, real-world observations show that the vast majority of servers do, at least for static files, correctly set the content-type header. If this behavior is not desired, a setting to bypass all content-type checks is available.
In addition to the security-relevant response header changes mentioned above, Camo will make some additional changes to the headers:
- Requests to the upstream will always have the
user-agentandviaheaders set to the configured value. - Responses will, in addition to the headers from the upstream, always have a
x-camo-original-urlheader, showing the original URL without any encoding.
Configuration can be done via environment variables and CLI flags. The available configuration can be listed by running Camo with --help, but they're also documented at /docs/configuration.md.
Please see the additional documentation in the docs folder for details on
- using released binaries
- deploying
camo-rswith Docker - building
camo-rsfrom source - running
camo-rswithsystemd
MIT. This projects takes heavy inspiration from atmos/camo, which also was licensed under the MIT license.