V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
huiyanpohundh123
V2EX  ›  程序员

iptables 太他妈难用了

  •  
  •   huiyanpohundh123 ·
    tinuv · 2023-02-11 19:05:58 +08:00 · 9823 次点击
    这是一个创建于 411 天前的主题,其中的信息可能已经有所发展或是发生改变。

    搞了一下午,想在部署了 docker 的机器上搞个透明代理,看了一天也没看懂 docker 的 nat 是怎么配的,模拟怎么也跑不通

    话说有了第一条规则后,后面的规则还有屁用啊

    68 条回复    2023-04-12 09:51:34 +08:00
    yaott2020
        1
    yaott2020  
       2023-02-11 19:24:08 +08:00 via Android   ❤️ 12
    你是没见过 nftables 的规则吧
    huiyanpohundh123
        2
    huiyanpohundh123  
    OP
       2023-02-11 19:26:45 +08:00
    @yaott2020 没见过
    PendingOni
        3
    PendingOni  
       2023-02-11 19:30:55 +08:00
    可以试下 ip route
    duke807
        4
    duke807  
       2023-02-11 19:31:21 +08:00 via Android
    有没有一种可能,是 docker 本身难用
    huiyanpohundh123
        5
    huiyanpohundh123  
    OP
       2023-02-11 19:36:05 +08:00
    @PendingOni 这不是路由能解决的吧 我的要求是 docker ,本机,和局域网的其他机器都能走代理
    PendingOni
        6
    PendingOni  
       2023-02-11 19:38:07 +08:00
    @huiyanpohundh123 说实话 我以为你需要用 iptables 做路由, 我也不是很清楚你现在的需求是什么,或许 docker inspect 看下呢?
    choury
        7
    choury  
       2023-02-11 19:41:31 +08:00 via Android
    你这需求要用策略路由才行吧
    huiyanpohundh123
        8
    huiyanpohundh123  
    OP
       2023-02-11 19:48:14 +08:00
    差不多就是做个 nat 转换 所有流量都通过 tcp 和 udp 代理
    seaguest
        9
    seaguest  
       2023-02-11 19:53:22 +08:00
    huiyanpohundh123
        10
    huiyanpohundh123  
    OP
       2023-02-11 19:58:11 +08:00
    @PendingOni 我的需求说白了就是把这个机器做个旁路由,只要把局域网内其他机器的网关设置为这台机器就能直接科学,然后网上找了个教程,透明代理倒是成了,但是我的 docker 服务没法访问了,然后又开始折腾。

    透明代理并不是用 docker 搭建的,所以可能没法通过路由来解决,iptables 配置不太熟悉,只能看懂 78 成,但是 iptables 麻烦就麻烦在它还有个几个表还有一套调用顺序,我自己推演模拟始终觉得有问题。具体是 return 这个指令匹配规则后到底是执行下一条规则还是直接跳过链路,我的推演是只有执行下一条规则 docker 的 nat 才有可能,但是网上搜了很多东西,也大概率是不执行下面的规则,而是使用默认策略跳到下一层链路。

    不理解原理就调试不了,就卡住了
    huiyanpohundh123
        11
    huiyanpohundh123  
    OP
       2023-02-11 20:00:18 +08:00
    @seaguest 我看了,或许可以,但是就「不透明」了,我希望是只改 iptables ,这也是我这么执着要把 iptables 搞明白的原因
    zedpass
        12
    zedpass  
       2023-02-11 20:02:51 +08:00   ❤️ 1
    可以问 chatgpt 试试:

    需要将外网访问本地 IP(192.168.75.5)的 80 端口转换为访问 192.168.75.3 的 8000 端口,提供 iptables 配置
    --------
    iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.75.3:8000
    huiyanpohundh123
        13
    huiyanpohundh123  
    OP
       2023-02-11 20:04:01 +08:00
    @zedpass 这个倒是知道,透明代理已经成功了,但是 docker 服务访问不了了,在解决这个问题
    crysislinux
        14
    crysislinux  
       2023-02-11 20:11:58 +08:00 via Android
    docker 本身改了一些网络的配置,导致常规的 iptables 不按预期工作了。我是把配置改回来了,就是不知道 docker 还能不能工作。具体改的啥忘了,你搜索应该能找到,这个问题
    rekulas
        15
    rekulas  
       2023-02-11 20:46:01 +08:00
    虚拟机实现倒是简单,docker 要搞感觉网络确实会比较麻烦

    非常赞同你的标题 iptables 确实 tm 难用 只是简单开关个端口还要,做更底层的操作就知道多蛋疼了
    documentzhangx66
        16
    documentzhangx66  
       2023-02-11 21:25:39 +08:00   ❤️ 4
    iptables 难用的原因很简单:

    1.这玩意的设计,违背了 Linux 的一物一用的原则。它混杂了太多功能与设定,调试又极其麻烦。

    2.这玩意的作者偷懒,很多必要功能都没设计,比如规则去重。

    3.这玩意的作者想搞事,比如它提供了一个虚拟交换机的功能,但设计这玩意的人又没多少交换机的经验,设计的一塌糊涂。

    给个建议,如果需要使用 iptables 做复杂的功能,建议专机专用,别与 docker 混在一起。

    也就是一台机器专门跑 iptables ,一台机器跑 docker 。
    defunct9
        17
    defunct9  
       2023-02-11 22:50:49 +08:00 via iPhone   ❤️ 6
    开 ssh ,让我上去试试
    0o0O0o0O0o
        18
    0o0O0o0O0o  
       2023-02-11 22:57:03 +08:00 via iPhone
    是 tproxy 实现的吗? docker 的网络遇上 tproxy 透明代理就是有点麻烦的,网上也有文章介绍,简言之,net.bridge.bridge-nf-call-iptables
    digimoon
        19
    digimoon  
       2023-02-11 23:00:30 +08:00
    docker 本身也有几种网络,你折腾完 iptables 后有重启一下 docker 的网络吗? docker 会往 iptables 里面插一堆规则的
    2503
        20
    2503  
       2023-02-11 23:01:01 +08:00
    huiyanpohundh123
        21
    huiyanpohundh123  
    OP
       2023-02-11 23:09:40 +08:00
    @0o0O0o0O0o 没用 tproxy 就是用了 nat 表
    huiyanpohundh123
        22
    huiyanpohundh123  
    OP
       2023-02-11 23:10:15 +08:00
    @digimoon 我用的是桥接模式,他桥接的实现就是用了 iptables 所以我想看懂 好改
    huiyanpohundh123
        23
    huiyanpohundh123  
    OP
       2023-02-11 23:10:59 +08:00
    @2503 这个太简单了 还没 chatgpt 懂得多
    cest
        24
    cest  
       2023-02-11 23:20:09 +08:00
    可以用 network host 就
    每个 docker 自己一个 lxc ,接下来随便你了
    docker 的网路就是一坨
    wwbfred
        25
    wwbfred  
       2023-02-11 23:52:16 +08:00
    iptables 对新手极其不友好,这也是后来要改版的一个重要原因。
    不过习惯了之后新出的那个我都不敢用,因为不知道到底是发生了什么😂
    deorth
        26
    deorth  
       2023-02-12 00:04:51 +08:00 via Android
    建议用 nftables
    life90
        27
    life90  
       2023-02-12 00:08:29 +08:00 via Android
    透明代理有两种模式,"tproxy"和"redirect"。我觉得后一种好配置一点。只要做好了标记,就很方便。
    网上的教程大部分抄袭不全。如果你能玩懂 mikrotik ROS 这个不会太难。
    cubecube
        28
    cubecube  
       2023-02-12 00:27:48 +08:00
    @wwbfred 新的规则更像一坨屎。。云里雾里需要理解的概念更多
    lovelylain
        29
    lovelylain  
       2023-02-12 00:31:58 +08:00 via Android
    你可以给 docker 加 iptables=False 启动参数,自己手工去添加 iptables 规则,都是自己添加的,要弄懂就容易了,我以前用 openwrt 因为它网络变化后会重启 iptables 导致 docker 添加的规则失效,所以都是手工添加,让事情在掌控中。另外针对你的目的,要实现部分网站走代理,部分直连,还要对本机、局域网、桥容器、host 容器都做到透明代理,本身就是很复杂的。
    wwbfred
        30
    wwbfred  
       2023-02-12 00:35:08 +08:00
    @cubecube 最怕的就是这个,从一坨屎强制转移到另一坨屎,学习成本还贼高。
    ermeow
        31
    ermeow  
       2023-02-12 00:54:08 +08:00 via iPad
    建议执行 iptables -L 的时候加个-v
    flush9f
        32
    flush9f  
       2023-02-12 01:02:22 +08:00
    不是可以设置 network namespace ,这样 docker 就可以设置自己的路由了
    vonsy
        33
    vonsy  
       2023-02-12 03:03:54 +08:00   ❤️ 2
    试了试,docker 可以当透明网关 /代理
    用的是斐讯 N1,刷的 NDM, linux 应该也可以, macos 不行,好像 macvlan 有问题
    # 创建网络,网卡混杂模式
    ip link set eth0 promisc on
    docker network create -d macvlan --subnet=2.2.2.0/24 --gateway=2.2.2.1 -o parent=eth0 macnet

    # 转发用的 clash redir
    docker run -d \
    -it \
    --name=clash \
    --network macnet \
    --ip 2.2.2.77 \
    --mac-address 32:D8:E2:AE:93:77 \
    --ulimit nofile=16384:65536 \
    --cap-add=NET_ADMIN \
    --privileged=true \
    -e TZ=Asia/Shanghai \
    -p 7892:7892 \
    golang:latest \
    /bin/sh

    # 安装,配置 clash
    go install github.com/Dreamacro/clash@latest
    vi ./bin/config.yaml
    bin/clash -f bin/config.yaml

    # 来自 https://github.com/shadowsocks/shadowsocks-libev#transparent-proxy
    iptables -t nat -N SHADOWSOCKS
    iptables -t mangle -N SHADOWSOCKS
    # VPS 服务器不转发
    iptables -t nat -A SHADOWSOCKS -d 54.250.148.164 -j RETURN
    # 局域网地址不转发
    iptables -t nat -A SHADOWSOCKS -d 0.0.0.0/8 -j RETURN
    iptables -t nat -A SHADOWSOCKS -d 10.0.0.0/8 -j RETURN
    iptables -t nat -A SHADOWSOCKS -d 127.0.0.0/8 -j RETURN
    iptables -t nat -A SHADOWSOCKS -d 169.254.0.0/16 -j RETURN
    iptables -t nat -A SHADOWSOCKS -d 172.16.0.0/12 -j RETURN
    iptables -t nat -A SHADOWSOCKS -d 192.168.0.0/16 -j RETURN
    iptables -t nat -A SHADOWSOCKS -d 224.0.0.0/4 -j RETURN
    iptables -t nat -A SHADOWSOCKS -d 240.0.0.0/4 -j RETURN
    iptables -t nat -A SHADOWSOCKS -d 2.2.2.0/24 -j RETURN

    # TCP
    iptables -t nat -A SHADOWSOCKS -p tcp -j REDIRECT --to-ports 7892
    # UDP
    ip route add local default dev lo table 100
    ip rule add fwmark 1 lookup 100
    iptables -t mangle -A SHADOWSOCKS -p udp --dport 53 -j TPROXY --on-port 7892 --tproxy-mark 0x01/0x01
    # 生效
    iptables -t nat -A PREROUTING -p tcp -j SHADOWSOCKS
    iptables -t mangle -A PREROUTING -j SHADOWSOCKS

    # 可能用到的包
    apt update
    apt install -y vim iptables iproute2 iputils-ping curl net-tools ca-certificates
    update-ca-certificates

    # 安装包可能要临时翻
    export http_proxy=http://2.2.2.77:7890
    export https_proxy=http://2.2.2.77:7890
    unset http_proxy
    unset https_proxy

    # 测试有没有生效
    curl https://ipinfo.io/
    curl https://ifconfig.co/
    StevenRCE0
        34
    StevenRCE0  
       2023-02-12 03:49:30 +08:00
    你是没试过用 pf 转吧
    germain
        35
    germain  
       2023-02-12 04:11:12 +08:00
    Docker 和网络基础概念没搞清楚却怪 iptables 难用。
    dcoder
        36
    dcoder  
       2023-02-12 07:50:05 +08:00
    @huiyanpohundh123
    你理解得没错. iptables 和 Docker 都难用. 混在一起更难用了.
    Docker 那些复杂的网络配置, 网络扩展, 简直惨不忍睹...
    ltkun
        37
    ltkun  
       2023-02-12 08:34:59 +08:00 via Android
    直接改 docker 的主机网关指向透明代理不行吗 我就是这么干的
    huiyanpohundh123
        38
    huiyanpohundh123  
    OP
       2023-02-12 09:33:38 +08:00 via iPhone
    @vonsy 大佬,能帮我解释下我题目描述的这个 docker 链为什么生效不,我看第一条规则已经能匹配所有数据包了,target 又是 return ,那么后面的几条规则案例说就没意义了,但是后面这几天规则又是实现网桥功能的关键规则
    huiyanpohundh123
        39
    huiyanpohundh123  
    OP
       2023-02-12 09:35:48 +08:00 via iPhone
    @vonsy 这个感觉还要用到网络,我感觉吃不动,怕到时候出了问题都不会改
    Yuanandyuan
        40
    Yuanandyuan  
       2023-02-12 09:54:25 +08:00 via Android
    @huiyanpohundh123 可以用 iptables -t nat -S 看看完全的规则是什么
    xicole
        41
    xicole  
       2023-02-12 10:01:41 +08:00
    刚好搞了几天的 clash ,iptables 搞通了但是用一段时间会断不知何解,后来转用 Tun 模式关了 iptables ,暂时可用没有发现什么大问题,用的 clash.meta ,docker 里面安装的,另外还使用了 mosdns ,也是 docker ,
    硬件:N1 刷的 F 大的固件,
    huiyanpohundh123
        42
    huiyanpohundh123  
    OP
       2023-02-12 10:11:56 +08:00
    @Yuanandyuan -P PREROUTING ACCEPT
    -P INPUT ACCEPT
    -P POSTROUTING ACCEPT
    -P OUTPUT ACCEPT
    -N LIBVIRT_PRT
    -N DOCKER
    -A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
    -A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
    -A POSTROUTING -j LIBVIRT_PRT
    -A POSTROUTING -s 172.17.0.3/32 -d 172.17.0.3/32 -p tcp -m tcp --dport 9443 -j MASQUERADE
    -A POSTROUTING -s 172.17.0.3/32 -d 172.17.0.3/32 -p tcp -m tcp --dport 9000 -j MASQUERADE
    -A POSTROUTING -s 172.17.0.3/32 -d 172.17.0.3/32 -p tcp -m tcp --dport 8000 -j MASQUERADE
    -A POSTROUTING -s 172.17.0.2/32 -d 172.17.0.2/32 -p tcp -m tcp --dport 6969 -j MASQUERADE
    -A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
    -A LIBVIRT_PRT -s 192.168.122.0/24 -d 224.0.0.0/24 -j RETURN
    -A LIBVIRT_PRT -s 192.168.122.0/24 -d 255.255.255.255/32 -j RETURN
    -A LIBVIRT_PRT -s 192.168.122.0/24 ! -d 192.168.122.0/24 -p tcp -j MASQUERADE --to-ports 1024-65535
    -A LIBVIRT_PRT -s 192.168.122.0/24 ! -d 192.168.122.0/24 -p udp -j MASQUERADE --to-ports 1024-65535
    -A LIBVIRT_PRT -s 192.168.122.0/24 ! -d 192.168.122.0/24 -j MASQUERADE
    -A DOCKER -i docker0 -j RETURN
    -A DOCKER ! -i docker0 -p tcp -m tcp --dport 9443 -j DNAT --to-destination 172.17.0.3:9443
    -A DOCKER ! -i docker0 -p tcp -m tcp --dport 9000 -j DNAT --to-destination 172.17.0.3:9000
    -A DOCKER ! -i docker0 -p tcp -m tcp --dport 8000 -j DNAT --to-destination 172.17.0.3:8000
    -A DOCKER ! -i docker0 -p tcp -m tcp --dport 6969 -j DNAT --to-destination 172.17.0.2:6969
    huiyanpohundh123
        43
    huiyanpohundh123  
    OP
       2023-02-12 10:18:19 +08:00
    -A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER 这条规则也很怪匹配本地地址,但非环回地址,那 127.0.0.1 岂不是没法进入 docker 链,但是测试是可以的
    xuanbg
        44
    xuanbg  
       2023-02-12 10:21:45 +08:00
    docker 我都直接--network host ,直接挂宿主机。这样只要宿主机网络搞定就万事大吉了。
    zhyl
        45
    zhyl  
       2023-02-12 14:32:02 +08:00
    @huiyanpohundh123
    `-A DOCKER -i docker0 -j RETURN`
    只有 docker0 接口的流量 RETURN 不会走 DOCKER 表,并不是所有的 DOCKER 表流量都 RETURN

    127.0.0.1 能进 docker 有一篇文章说的很清楚 https://www.ipspace.net/kb/DockerSvc/40-userland-proxy.html
    简单的说就是 docker 监听了::port ,请求 127.0.0.1:port 会被 docker 处理,docker 内部再转发到 docker 容器内的 ip 段
    qwq11
        46
    qwq11  
       2023-02-12 14:59:28 +08:00
    没太懂你透明代理怎么搞的,看上面的回复应该是在 prerouting 表里 dnat 到了你的代理端口上。那那这样你就得在 prerouting 表里匹配然后 accpet ,让他进到你本机里,规则优先级要比你之前那条高,大概是

    iptables -t nat -A PREROUTING -s 192.168.1.1/24 -d 192.168.1.2 -j accept

    这样?

    建议把整个 iptables 配置发上来
    sudo iptables -L -v -n | curl -F 'file=@-' 0x0.st
    qwq11
        47
    qwq11  
       2023-02-12 15:04:22 +08:00 via Android
    @qwq11 #46
    忘了加 dport 了
    iptables -t nat -A PREROUTING -s 192.168.1.1/24 -d 192.168.1.2 --dport 9000 -j accept
    liuxu
        48
    liuxu  
       2023-02-12 15:38:46 +08:00
    iptables 不是给普通用户用的,总归是得有点基础才行,要不然怎么会还有 firewared 和 ufw 这些应用

    docker 只是在 iptables 插入自己的 chain 而已,正常不需要自己处理 iptables

    想手动干涉 DOCKER chains ,用 iptables -I 插入到 RETURN 前面
    liuxu
        49
    liuxu  
       2023-02-12 15:40:04 +08:00
    firewalld
    adoal
        50
    adoal  
       2023-02-12 16:08:59 +08:00
    iptables 固然不亲善,docker 则是另一坨屎。需要自己配置防火墙规则的应用,不建议凑热闹放到 docker 里。有条件的话还是用虚拟机来跑吧。
    koplonjaslon02
        51
    koplonjaslon02  
       2023-02-12 16:26:54 +08:00
    现在在折腾 nftables ,资料比 iptables 还少,但感觉上手后能和 iptables 拉开差距
    yinmin
        52
    yinmin  
       2023-02-12 18:05:04 +08:00
    换一种思路,不折腾 iptables 。你在 Docker 容器里的 /root/.bashrc 文件最后加上 4 行:
    export use_proxy=on
    export http_proxy=http://ip:port
    export https_proxy=http://ip:port
    export all_proxy=http://ip:port

    然后容器里的应用都会走代理了,是不是也能解决实际问题?
    yinmin
        53
    yinmin  
       2023-02-12 18:15:48 +08:00
    换一种思路,不折腾 iptables 。在 Docker 里安装 openwrt 旁路由。
    zhzy0077
        54
    zhzy0077  
       2023-02-12 18:29:51 +08:00
    在世上还没有 docker 和 cgroup 之前 iptables 就已经特别难用了 而且还没得选

    难学 难调试 难开发 难部署
    ccming
        55
    ccming  
       2023-02-12 19:36:54 +08:00
    请注意文明用语
    zhanlanhuizhang
        56
    zhanlanhuizhang  
       2023-02-12 20:50:36 +08:00
    研究一下,不难的,不要一下子去看网上的文章,直接看教程。就能自己组合了。
    emeab
        57
    emeab  
       2023-02-12 20:52:47 +08:00
    主要是调试麻烦..
    HungryOrangeCat
        58
    HungryOrangeCat  
       2023-02-13 08:49:45 +08:00
    @yinmin 这个只能限定那些走 http 代理的,没法限定比如直接 tcp ,udp 或者不按照代理走的,前些时间我也在研究 OP 的这个问题
    julyclyde
        59
    julyclyde  
       2023-02-13 08:56:31 +08:00
    说白了这事其实是你误以为可以无基础使用 docker ,结果使用了 docker 带来无尽的麻烦的问题

    用 network=host 就行了!!
    zero01
        60
    zero01  
       2023-02-13 09:35:51 +08:00
    docker 透明代理可以用 v2rayA 非常好用
    https://v2raya.org/
    huiyanpohundh123
        61
    huiyanpohundh123  
    OP
       2023-02-13 11:17:01 +08:00
    @zero01 感谢推荐 回到家去试试
    julyclyde
        62
    julyclyde  
       2023-02-13 11:26:00 +08:00
    @adoal 我现在都 network=host 了
    fatlao
        63
    fatlao  
       2023-02-13 11:45:09 +08:00
    network=host 正解
    opengg
        64
    opengg  
       2023-02-13 11:48:49 +08:00
    直接 KVM 虚拟机分开,透明代理单独一个环境,就简单了。
    opengg
        65
    opengg  
       2023-02-13 11:51:07 +08:00
    docker 就是个方便管理 cgroup, route, iptables 的工具,在符合需求的范围内用。
    如果你环境已经非常复杂了,与其追求 all in one ,不如把特殊需求独立出去,比如虚拟机。
    Aaron325
        66
    Aaron325  
       2023-02-13 11:51:13 +08:00
    这时候就体现 chatgpt 的优势了
    azuginnen
        67
    azuginnen  
       2023-02-14 14:28:39 +08:00
    -A DOCKER -i docker0 -j RETURN 这条是给 OUTPUT 用的吧。


    incoming packet 匹配的都是 !docker0 规则。
    humbass
        68
    humbass  
       351 天前
    也是同样的问题,我是配了一个旁路 VPN 服务器,用来科学,搞了 3 天没搞成,去闲鱼找高手搞定。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3234 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 34ms · UTC 14:21 · PVG 22:21 · LAX 07:21 · JFK 10:21
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.