-
Assuming a configuration such as cat <<EOT > $(pwd)/tap/.workerd.capnp
using Workerd = import "/workerd/workerd.capnp";
const config :Workerd.Config = (
services = [
(name = "main", worker = .tapWorker),
],
);
const tapWorker :Workerd.Worker = (
modules = [
(name = "worker", esModule = embed "run-workerd.js")
],
compatibilityDate = "$COMPATIBILITY_DATE",
);
EOT Used for running a library test suite against a mock server like so workerd test --verbose $(pwd)/tap/.workerd.capnp I have the need to access a local running http server on a port 3000 using fetch() from within the worker. I get the following error output from workerd
I'm able to make changes to the setup, e.g. to use an IP or a hostname to access the service if that's needed. Any help and guidance for accessing the local http server is welcome. |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
By default, Workers are only allowed to fetch from the public internet. This is to protect against SSRF attacks, where an application that tries to fetch user-provided URLs could be tricked by an attacker into fetching internal URLs that the attacker isn't supposed to be able to access. Since only public URLs can be fetched, such an attack is not possible by default. There are two ways you can give your worker access to internal servers. I'll show examples below, but remember the full config format is documented in workerd.capnp. Preferred approach: Define a service binding of type using Workerd = import "/workerd/workerd.capnp";
const config :Workerd.Config = (
services = [
(name = "main", worker = .myWorker),
(name = "privateServer", external = .myPrivateServer),
],
);
const myWorker :Workerd.Worker = (
modules = [
(name = "worker", esModule = embed "worker.js")
],
bindings = [
(name = "PRIVATE_SERVER", service = "privateServer")
],
compatibilityDate = "2023-12-18",
);
const myPrivateServer :Workerd.ExternalServer = (
address = "127.0.0.1:3000",
http = ()
); Now in your code you can fetch from your private server: export default {
async fetch(req, env, ctx) {
let resp = await env.PRIVATE_SERVER.fetch("http://127.0.0.1:3000/foo");
// ...
}
} With this approach, you must explicitly use Dangerous approach: Disable SSRF protection. You can redefine the default network for fetch() requests so that it includes private networks. To do this, define a service of using Workerd = import "/workerd/workerd.capnp";
const config :Workerd.Config = (
services = [
(name = "main", worker = .myWorker),
(name = "fullNetwork", network = .myNetwork),
],
);
const myWorker :Workerd.Worker = (
modules = [
(name = "worker", esModule = embed "worker.js")
],
globalOutbound = "fullNetwork",
compatibilityDate = "2023-12-18",
);
const myNetwork :Workerd.Network = (
# Allow all addresses. (You can also list CIDRs here.)
allow = ["public", "private"],
deny = []
); Now you can |
Beta Was this translation helpful? Give feedback.
By default, Workers are only allowed to fetch from the public internet. This is to protect against SSRF attacks, where an application that tries to fetch user-provided URLs could be tricked by an attacker into fetching internal URLs that the attacker isn't supposed to be able to access. Since only public URLs can be fetched, such an attack is not possible by default.
There are two ways you can give your worker access to internal servers. I'll show examples below, but remember the full config format is documented in workerd.capnp.
Preferred approach: Define a service binding of type
ExternalServer
.