微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用 Cloudflare Worker 作为代理时,有没有办法传递原始客户端 IP?

如何解决使用 Cloudflare Worker 作为代理时,有没有办法传递原始客户端 IP?

我有一个 Cloudflare Worker,它充当我的应用程序的代理。我需要这个是因为 Cloudflare 使用 curl 或任何 HTTP 请求库阻止外部请求。因此,在 Cloudflare 网络内部,我能够绕过 http://icanhazip.com/ 的 Cloudflare 验证。

问题是,当我将 Cloudflare 工作器配置为代理并在我的请求库 Python 代码中使用它时,页面获取其真实内容,但 http://icanhazip.com/ 显示的 IP 是 Cloudflare 工作器IP,不是我自己的。

我知道 Cloudflare 使用 CF-Connecting-IP 来传递我的 IP,当我检查 Worker 时,我的 IP 在那里,但是,页面没有获得正确的 IP。

我尝试过 X-Forwarded-For、X-Real-IP、True-Client-IP 和其他标头来尝试传递正确的 IP。

问题是,当代理完成后,我需要在一个真实的应用场景中使用,当工作人员将成为更改身份验证的代理时,但应用程序来自第三方公司,所以我无法控制然后传递带有 IP 的自定义标头。

任何人都有想法,如何转发真实用户的 ip,否则这是不可能的,我看过 Cloudflare Spectrum,但我不知道它是否适合我的问题。

这是我的工人代码

const OLD_URL = ".server.com"
const NEW_URL = ".proxied.com"

class AttributeRewriter {
  constructor(attributeName) {
    this.attributeName = attributeName
  }
  element(element) {
    const attribute = element.getAttribute(this.attributeName)
    if (attribute) {
      element.setAttribute(
        this.attributeName,attribute.replace(OLD_URL,NEW_URL),)
    }
  }
}

const rewriter = new HTMLRewriter()
  .on("a",new AttributeRewriter("href"))
  .on("img",new AttributeRewriter("src"))
  .on("link",new AttributeRewriter("href"))
  .on("object",new AttributeRewriter("src"))

async function forwardReq(request) {
  try{
    let newHdrs = new Headers()
  for (const [key,value] of request.headers) {
    /*if (key.toLowerCase().startsWith('cf-')) {
        continue;
    }*/
    if (key.toLowerCase() == 'x-forwarded-for') {
        continue;
    }
    if (key.toLowerCase() == 'x-real-ip') {
        continue;
    }
    if (key.toLowerCase() == 'content-security-policy') {
        continue;
    }
    newHdrs.set(key,value)
  }
  newHdrs.set('Host',request.url.replace(OLD_URL,NEW_URL))
  newHdrs.set('X-Real-IP',request.headers.get('CF-Connecting-IP'))
  newHdrs.set('X-Fowarded-For',request.headers.get('CF-Connecting-IP'))
  newHdrs.set('True-Client-IP',request.headers.get('CF-Connecting-IP'))
  newHdrs.set('Remote-Addr',request.headers.get('CF-Connecting-IP'))
  newHdrs.set('X-ProxyUser-Ip',request.headers.get('CF-Connecting-IP'))
  newHdrs.set('Via',request.headers.get('CF-Connecting-IP'))

  let address = ''
  const url = new URL(request.url)
  address = request.url.replace(NEW_URL,OLD_URL)

   const init = {
      headers: newHdrs,method: request.method
    }

  if (request.method == 'POST') {
    init.body = await request.arrayBuffer()
    init.method = 'CONNECT'
  }
  else {
    init.body = request.body
  }

  let response = await fetch (address,init);
  let html = await response.text()
  
  html = html.replace(/\.coinbase.com/g,NEW_URL)
    
  /*return new Response(JSON.stringify([...response.headers]),{
    headers: response.headers
  })*/
  let newResponse = new Response(html,{
    headers: response.headers
  })
  if (newResponse.headers.get('Referer')) {
      newResponse.headers.set('Referer',newResponse.headers.get('Referer').replace(request.url.hostname,'www.coinbase.com'))
  }
  if (newResponse.headers.get('Location')) {
      newResponse.headers.set('Location',newResponse.headers.get('Location').replace(request.url.hostname,'www.coinbase.com'))
  }
  newResponse.headers.set('Access-Control-Allow-Origin','*')
  newResponse.headers.delete('Content-Security-Policy')
  return newResponse
  }
  catch (e) {
    return new Response(e.message)
  }
}

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

解决方法

不是 JS 专家,所以对我来说,您的代码对于您要实现的目标来说似乎有点复杂。由于依赖于它的应用程序逻辑,我们也有类似的要求将真实用户 IP 解析到我们的应用程序中,而在迁移到 CF 时,我们也遇到了同样的问题。

但是 CF-Connecting-IP 在我们的例子中工作得很好。我们首先检查 X-Forwarded-For 是否存在,如果不存在,则使用 Cf-Connecting-IP 定义变量。

async function setRealIP(request) 
{
    var ip=""
    // Get the X-Forwarded-For header if it exists
    ip = request.headers.get("X-Forwarded-For")
    if (!ip) {
       //console.log("X-Forwarded-For was null")
       ip = request.headers.get("Cf-Connecting-Ip")
       //console.log("Getting IP from CF-Connecting-IP:"+ip)
    }
    
    // Add Real IP to header
    request = new Request(request)
    request.headers.set('True-Client-IP',ip)
    
    return request
}

为了让事情更简洁,我们只是将它放在一个名为 setRealIP() 的函数中,而 forwardReq() 就像这样:

async function forwardReq(request) {

    request = await setRealIP(request)
    
    //add redirect logic here

}

同样对于重写,尝试看看开箱即用的功能 Cloudflare Transform Rules 是否有帮助。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。