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

iptables 太他妈难用了

  •  
  •   huiyanpohundh123 · 112 天前 · 7925 次点击
    这是一个创建于 112 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

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

    不理解原理就调试不了,就卡住了
    huiyanpohundh123
        11
    huiyanpohundh123  
    OP
       112 天前
    @seaguest 我看了,或许可以,但是就「不透明」了,我希望是只改 iptables ,这也是我这么执着要把 iptables 搞明白的原因
    zedpass
        12
    zedpass  
       112 天前   ❤️ 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
       112 天前
    @zedpass 这个倒是知道,透明代理已经成功了,但是 docker 服务访问不了了,在解决这个问题
    crysislinux
        14
    crysislinux  
       112 天前 via Android
    docker 本身改了一些网络的配置,导致常规的 iptables 不按预期工作了。我是把配置改回来了,就是不知道 docker 还能不能工作。具体改的啥忘了,你搜索应该能找到,这个问题
    rekulas
        15
    rekulas  
       112 天前
    虚拟机实现倒是简单,docker 要搞感觉网络确实会比较麻烦

    非常赞同你的标题 iptables 确实 tm 难用 只是简单开关个端口还要,做更底层的操作就知道多蛋疼了
    documentzhangx66
        16
    documentzhangx66  
       112 天前   ❤️ 4
    iptables 难用的原因很简单:

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

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

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

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

    也就是一台机器专门跑 iptables ,一台机器跑 docker 。
    defunct9
        17
    defunct9  
       112 天前 via iPhone   ❤️ 6
    开 ssh ,让我上去试试
    0o0O0o0O0o
        18
    0o0O0o0O0o  
       112 天前 via iPhone
    是 tproxy 实现的吗? docker 的网络遇上 tproxy 透明代理就是有点麻烦的,网上也有文章介绍,简言之,net.bridge.bridge-nf-call-iptables
    digimoon
        19
    digimoon  
       112 天前
    docker 本身也有几种网络,你折腾完 iptables 后有重启一下 docker 的网络吗? docker 会往 iptables 里面插一堆规则的
    2503
        20
    2503  
       112 天前
    huiyanpohundh123
        21
    huiyanpohundh123  
    OP
       112 天前
    @0o0O0o0O0o 没用 tproxy 就是用了 nat 表
    huiyanpohundh123
        22
    huiyanpohundh123  
    OP
       112 天前
    @digimoon 我用的是桥接模式,他桥接的实现就是用了 iptables 所以我想看懂 好改
    huiyanpohundh123
        23
    huiyanpohundh123  
    OP
       112 天前
    @2503 这个太简单了 还没 chatgpt 懂得多
    cest
        24
    cest  
       112 天前
    可以用 network host 就
    每个 docker 自己一个 lxc ,接下来随便你了
    docker 的网路就是一坨
    wwbfred
        25
    wwbfred  
       112 天前
    iptables 对新手极其不友好,这也是后来要改版的一个重要原因。
    不过习惯了之后新出的那个我都不敢用,因为不知道到底是发生了什么😂
    deorth
        26
    deorth  
       112 天前 via Android
    建议用 nftables
    life90
        27
    life90  
       112 天前 via Android
    透明代理有两种模式,"tproxy"和"redirect"。我觉得后一种好配置一点。只要做好了标记,就很方便。
    网上的教程大部分抄袭不全。如果你能玩懂 mikrotik ROS 这个不会太难。
    cubecube
        28
    cubecube  
       112 天前
    @wwbfred 新的规则更像一坨屎。。云里雾里需要理解的概念更多
    lovelylain
        29
    lovelylain  
       112 天前 via Android
    你可以给 docker 加 iptables=False 启动参数,自己手工去添加 iptables 规则,都是自己添加的,要弄懂就容易了,我以前用 openwrt 因为它网络变化后会重启 iptables 导致 docker 添加的规则失效,所以都是手工添加,让事情在掌控中。另外针对你的目的,要实现部分网站走代理,部分直连,还要对本机、局域网、桥容器、host 容器都做到透明代理,本身就是很复杂的。
    wwbfred
        30
    wwbfred  
       112 天前
    @cubecube 最怕的就是这个,从一坨屎强制转移到另一坨屎,学习成本还贼高。
    ermeow
        31
    ermeow  
       112 天前 via iPad
    建议执行 iptables -L 的时候加个-v
    flush9f
        32
    flush9f  
       112 天前
    不是可以设置 network namespace ,这样 docker 就可以设置自己的路由了
    vonsy
        33
    vonsy  
       112 天前   ❤️ 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/[email protected]
    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  
       112 天前
    你是没试过用 pf 转吧
    germain
        35
    germain  
       112 天前
    Docker 和网络基础概念没搞清楚却怪 iptables 难用。
    dcoder
        36
    dcoder  
       111 天前
    @huiyanpohundh123
    你理解得没错. iptables 和 Docker 都难用. 混在一起更难用了.
    Docker 那些复杂的网络配置, 网络扩展, 简直惨不忍睹...
    ltkun
        37
    ltkun  
       111 天前 via Android
    直接改 docker 的主机网关指向透明代理不行吗 我就是这么干的
    huiyanpohundh123
        38
    huiyanpohundh123  
    OP
       111 天前 via iPhone
    @vonsy 大佬,能帮我解释下我题目描述的这个 docker 链为什么生效不,我看第一条规则已经能匹配所有数据包了,target 又是 return ,那么后面的几条规则案例说就没意义了,但是后面这几天规则又是实现网桥功能的关键规则
    huiyanpohundh123
        39
    huiyanpohundh123  
    OP
       111 天前 via iPhone
    @vonsy 这个感觉还要用到网络,我感觉吃不动,怕到时候出了问题都不会改
    Yuanandyuan
        40
    Yuanandyuan  
       111 天前 via Android
    @huiyanpohundh123 可以用 iptables -t nat -S 看看完全的规则是什么
    xicole
        41
    xicole  
       111 天前
    刚好搞了几天的 clash ,iptables 搞通了但是用一段时间会断不知何解,后来转用 Tun 模式关了 iptables ,暂时可用没有发现什么大问题,用的 clash.meta ,docker 里面安装的,另外还使用了 mosdns ,也是 docker ,
    硬件:N1 刷的 F 大的固件,
    huiyanpohundh123
        42
    huiyanpohundh123  
    OP
       111 天前
    @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
       111 天前
    -A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER 这条规则也很怪匹配本地地址,但非环回地址,那 127.0.0.1 岂不是没法进入 docker 链,但是测试是可以的
    xuanbg
        44
    xuanbg  
       111 天前
    docker 我都直接--network host ,直接挂宿主机。这样只要宿主机网络搞定就万事大吉了。
    zhyl
        45
    zhyl  
       111 天前
    @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  
       111 天前
    没太懂你透明代理怎么搞的,看上面的回复应该是在 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 '[email protected]' 0x0.st
    qwq11
        47
    qwq11  
       111 天前 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  
       111 天前
    iptables 不是给普通用户用的,总归是得有点基础才行,要不然怎么会还有 firewared 和 ufw 这些应用

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

    想手动干涉 DOCKER chains ,用 iptables -I 插入到 RETURN 前面
    liuxu
        49
    liuxu  
       111 天前
    firewalld
    adoal
        50
    adoal  
       111 天前
    iptables 固然不亲善,docker 则是另一坨屎。需要自己配置防火墙规则的应用,不建议凑热闹放到 docker 里。有条件的话还是用虚拟机来跑吧。
    koplonjaslon02
        51
    koplonjaslon02  
       111 天前
    现在在折腾 nftables ,资料比 iptables 还少,但感觉上手后能和 iptables 拉开差距
    yinmin
        52
    yinmin  
       111 天前
    换一种思路,不折腾 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  
       111 天前
    换一种思路,不折腾 iptables 。在 Docker 里安装 openwrt 旁路由。
    zhzy0077
        54
    zhzy0077  
       111 天前
    在世上还没有 docker 和 cgroup 之前 iptables 就已经特别难用了 而且还没得选

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

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


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