3

We want to turn an Apache proxy into a Cloudflare worker on the edge:

We use the preserve host config:

    ProxyPreserveHost On
    ProxyPass /blog http://wordpress.example.com/blog
    ProxyPassReverse /blog http://wordpress.example.com/blog

So

example.com/blog opens the blog.

We tried this script:

export default {
  async fetch(request, env) {
    var url = new URL(request.url);

    // set hostname to the place we're proxying requests from
    url.protocol = "http"
    url.hostname = "wordpress.example.com"

    let response = await fetch(url,  {"headers":{"Host":"example.com"}}))
    return response;
  }
}

But it causes a 500 server error

I looks like the host header cannot be overwritten in the fetch API? Is this also true for such server side code or only in the browser / for AJAX requests?

Another approach I tried:

addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request))
})

async function handleRequest(request) {
  const url = new URL(request.url);
  url.protocol = 'http';
  url.hostname = '<IP of the wordpress server>';
  console.log(request);

  var req = new Request(request.url, {
    method: request.method,
    headers: request.headers,
    redirect: 'manual'   // let browser handle redirects
});

  req.headers.set('Host', 'www.example.com');

  const data = await fetch(url.toString(),req);
  return data;
}

But I get a permission denied response.

Alex
  • 32,506
  • 16
  • 106
  • 171

2 Answers2

1

It kind of works now ...

addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request))
})

async function handleRequest(request) {
    var url = new URL(request.url);

    // set hostname to the place we're proxying requests from
    url.protocol = "http"
    url.hostname = "wordpress.example.com"

    let response = await fetch(url,  {"headers":{"Host":"www.example.com"}})
    return response;
}

I believe it did something fundamentally wrong at the first try and might not even had deployed the worker :-)

Also I figured out, that there is a error log console on the worker's quick edit page, which helps.

But:

This does not exactly answer that part of the question, how I can emulate ProxyPreserveHost On in a worker, so I leave this open.

Alex
  • 32,506
  • 16
  • 106
  • 171
0

The thing which you want to do is restricted process because of security concerns. It is called as header spoofing and it will not allowed by security policies of browsers. If you need more complex redirection/mapping, you should fix it on serve side. There is no secure solution on client side.

You can use this line on ProxyPass definition

ProxyPreserveHost Off
ProxyPass /blog http://wordpress.example.com/blog
ProxyPassReverse /blog http://wordpress.example.com/blog
RequestHeader set "Host" "www.example.com"

Also there is a different deffiniton. You can set different host names with this notation :

<Location "/blog">
   ProxyPreserveHost Off
   ProxyPass /blog http://wordpress.example.com/blog
   ProxyPassReverse /blog http://wordpress.example.com/blog
   RequestHeader set "Host" "www.example.com"
 </Location>
lazek
  • 189
  • 1
  • 5