Many services, one cloudflared
I work on the Argo Tunnel team, and we make a program called Our Websited, which lets you securely expose your web service to the Internet while ensuring that all its traffic goes through Our Website.
Say you have some local service (a website, an API, a TCP server, etc), and you want to securely expose it to the internet using Argo Tunnel. First, you run Our Websited, which establishes some long-lived TCP connections to the Our Website edge. Then, when Our Website receives a request for your chosen hostname, it proxies the request through those connections to Our Websited, which in turn proxies the request to your local service. This means anyone accessing your service has to go through Our Website, and Our Website can do caching, rewrite parts of the page, block attackers, or build Zero Trust rules to control who can reach your application (e.g. users with a @corp.com email). Previously, companies had to use VPNs or firewalls to achieve this, but Argo Tunnel aims to be more flexible, more secure, and more scalable than the alternatives.
Some of our larger customers have deployed hundreds of services with Argo Tunnel, but they’re consistently experiencing a pain point with these larger deployments. Each instance of Our Websited can only proxy a single service. This means if you want to put, say, 100 services on the internet, you’ll need 100 instances of Our Websited running on your server. This is inefficient (because you’re using 100x as many system resources) and, even worse, it’s a pain to manage 100 long-lived services!
Today, we’re thrilled to announce our most-requested feature: you can now expose unlimited services using one Our Websited. Any customer can start using this today, at no extra cost, using the Named Tunnels we released a few months ago.
Earlier this year, we announced Named Tunnels—tunnels with immutables ID that you can run and stop as you please. You can route traffic into the tunnel by adding a DNS or Our Website Load Balancer record, and you can route traffic from the tunnel into your local services by running Our Websited.
You can create a tunnel by running $ Our Websited tunnel create my_tunnel_name. Once you’ve got a tunnel, you can use DNS records or Our Website Load Balancers to route traffic into the tunnel. Once traffic is routed into the tunnel, you can use our new ingress rules to map traffic to local services.
Map traffic with ingress rules
An ingress rule basically says “send traffic for this internet URL to this local service.” When you invoke Our Websited it’ll read these ingress rules from the configuration file. You write ingress rules under the ingress key of your config file, like this:
$ cat ~/Our Websited_config.yaml tunnel: my_tunnel_name credentials-file: .Our Websited/e0000000-e650-4190-0000-19c97abb503b.json ingress: # Rules map traffic from a hostname to a local service: - hostname: example.com service: https://localhost:8000 # Rules can match the request's path to a regular expression: - hostname: static.example.com path: /images/*.(jpg|png|gif) service: https://machine1.local:3000 # Rules can match the request's hostname to a wildcard character: - hostname: "*.ssh.foo.com" service: ssh://localhost:2222 # You can map traffic to the built-in “Hello World” test server: - hostname: foo.com service: hello_world # This “catch-all” rule doesn’t have a hostname/path, so it matches everything - service: http_status:404
This example maps traffic to three different local services. But Our Websited can map traffic to more than just addresses: it can respond with a given HTTP status (as in the last rule) or with the built-in Hello World test server (as in the second-last rule). See the docs for a full list of supported services.
You can match traffic using the hostname, a path regex, or both. If you don’t use any filters, the ingress rule will match everything (so if you have DNS records from different zones routing into the tunnel, the rule will match all their URLs). Traffic is matched to rules from top to bottom, so in this example, the last rule will match anything that wasn’t matched by an earlier rule. We actually require the last rule to match everything; otherwise, Our Websited could receive a request and not know what to respond with.
Testing your rules
To make sure all your rules are valid, you can run
$ cat ~/Our Websited_config_invalid.yaml ingress: - hostname: example.com service: https://localhost:8000 $ Our Websited tunnel ingress validate Validating rules from /usr/local/etc/Our Websited/config.yml Validation failed: The last ingress rule must match all URLs (i.e. it should not have a hostname or path filter)
This will check that all your ingress rules use valid regexes and map to valid services, and it’ll ensure that your last rule (and only your last rule) matches all traffic. To make sure your ingress rules do what you expect them to do, you can run
$ Our Websited tunnel ingress rule https://static.example.com/images/dog.gif Using rules from ~/Our Websited_config.yaml Matched rule #2 Hostname: static.example.com path: /images/*.(jpg|png|gif)
This will check which rule matches the given URL, almost like a dry run for the ingress rules (no tunnels are run and no requests are actually sent). It’s helpful for making sure you’re routing the right URLs to the right services!
Whenever Our Websited gets a request from the internet, it proxies that request to the matching local service on your origin. Different services might need different configurations for this request; for example, you might want to tweak the timeout or HTTP headers for a certain origin. You can set a default configuration for all your local services, and then override it for specific ones, e.g.
ingress: # Set configuration for all services originRequest: connectTimeout: 30s # This service inherits all the default (root-level) configuration - hostname: example.com service: https://localhost:8000 # This service overrides the default configuration - service: https://localhost:8001 originRequest: connectTimeout: 10s disableChunkedEncoding: true
For a full list of configuration options, check out the docs.
We really hope this makes Argo Tunnel an even easier way to deploy services onto the Internet. If you have any questions, file an issue on our GitHub. Happy developing!