在 kubernetes 中透明地代理到 nodeport

在 kubernetes 中透明地代理到 nodeport

我设置了一个 kubernetes,其中的 pod 包含以下容器:

  1. 鱿鱼容器
  2. transocks(类似 redsocks);透明的 SOCKS 代理

我在 Linux PC 上的 k3s 本地运行它,并希望通过此透明代理透明地代理来自 PC 的所有传出流量。因此,传出的主机流量被强制到 kubernetes pod 上的 transocks 端口。现在它不起作用,连接只是超时。

我知道我正在使用的 iptables 规则是好的,因为当我使用主机网络直接在 docker 中运行上述容器时它们起作用了。squid 和 transocks 用户分别是 uid 31 和 32。我创建了以下 iptables 规则:

#iptables -t nat -A OUTPUT -m owner --uid-owner 31 -j ACCEPT
#iptables -t nat -A OUTPUT -m owner --uid-owner 32 -j ACCEPT
#iptables -t nat -A OUTPUT -p tcp --dport 80 -j REDIRECT --to-port 12345
#iptables -t nat -A OUTPUT -p tcp --dport 443 -j REDIRECT --to-port 12345

其中 12345 是 transocks 监听的端口。同样,这些规则在使用主机网络的 docker 下运行良好。transocks 转发到 127.0.0.1:3128(squid 端口),并且它是透明代理的。但是,当我尝试使用带有节点端口(transocks 为 30345,squid 为 30128)的 kubernetes pod 时,它似乎不起作用。连接只是挂起,直到超时。

我应该提到,我也尝试过对 dns 进行同样的操作,我将发往 53 的输出流量重定向到端口 9053(docker 中映射的 dns 端口),并且它可以工作,但是当我在 kubernetes 中使用它并重定向到节点端口(30053)时,它会以同样的方式挂起。因此,出于某种原因,当您将流量重定向到节点端口时,它们似乎不起作用。我想知道是否有人可以告诉我我在这里遗漏了什么。我一定不太了解 kubernetes 网络。

如果有人想看看我的 kuebrnetes 清单,它们就在这里。

部署

{
  "apiVersion": "apps/v1",
  "kind": "Deployment",
  "metadata": {
    "name": "webfilter",
    "labels": {
      "app": "webfilter"
    }
  },
  "spec": {
    "replicas": 1,
    "selector": {
      "matchLabels": {
        "app": "webfilter"
      }
    },
    "template": {
      "metadata": {
        "labels": {
          "app": "webfilter"
        }
      },
      "spec": {
        "containers": [
          {
            "name": "squid",
            "image": "jusschwa/squid-ssl:latest",
            "ports": [
              {
                "containerPort": 3128
              }
            ]
          }, {
            "name": "transocks",
            "image": "jusschwa/transocks-proxy:latest",
            "ports": [
              {
                "containerPort": 12345
              }
            ]
          }
        ]
      }
    }
  }
}

服务

{
  "apiVersion": "v1",
  "kind": "Service",
  "metadata": {
    "name": "webfilter",
    "labels": {
      "app": "webfilter"
    }
  },
  "spec": {
    "type": "NodePort",
    "selector": {
      "app": "webfilter"
    },
    "ports": [
      {
        "name": "squid",
        "protocol": "TCP",
        "port": 3128,
        "targetPort": 3128,
        "nodePort": 30128
      },
      {
        "name": "transocks",
        "protocol": "TCP",
        "port": 12345,
        "targetPort": 12345,
        "nodePort": 30345
      }
    ]
  }
}

iptables 规则

iptables -t nat -A OUTPUT -m owner --uid-owner root -j ACCEPT
iptables -t nat -A OUTPUT -m owner --uid-owner 31 -j ACCEPT # squid user
iptables -t nat -A OUTPUT -m owner --uid-owner 32 -j ACCEPT # transocks user
iptables -t nat -A OUTPUT -m owner --uid-owner 32 -j ACCEPT # unbound user
iptables -t nat -A OUTPUT -p tcp --dport 80 -j REDIRECT --to-ports 30345
iptables -t nat -A OUTPUT -p tcp --dport 443 -j REDIRECT --to-ports 30345
iptables -t nat -A OUTPUT -p udp --dport 53 -j REDIRECT --to-ports 30053

再次感谢您的帮助。

答案1

如果有人感兴趣的话,我发现尝试使用节点端口太难了,所以我选择将 transocks 移动到它自己的 pod 并使用主机网络,以及上述转发规则来实现这一点。这是我为 transocks pod 使用的清单:

{
  "apiVersion": "v1",
  "kind": "Pod",
  "metadata": {
    "name": "transocks"
  },
  "spec": {
    "hostNetwork": true,
    "dnsPolicy": "ClusterFirstWithHostNet",
    "containers": [
      {
        "name": "transocks",
        "image": "jusschwa/transocks-proxy"
      }
    ]
  }
}

这是我正在使用的 transocks toml:

listen = "0.0.0.0:12345"

# Connect to HTTP Proxy
proxy_url = "http://127.0.0.1:30128"

[log]
level = "error"

30128 是 squid 代理的节点端口。

相关内容