让主机能和Linux的虚拟机内部SNAT网络互访

前言

学习linux难免不接触docker容器,它是一个和牛逼的容器技术,你可以在里面装各样的软件,就像在独立的环境.比如我可以我的docker里面装了多个的Jdk,tomcat,mysql,甚至多个linux发行版.它的功能超级强大,但是有个问题,我要怎么样在我的主机上很方便的访问到这些装在docker上的服务应用,通常情况下,需要做端口转发,但是这种方式太扰人了,比如我在我docker容器上装了三个linux发行版,用来做linux集群的学习使用,我要为它们每个做ssh端口映射,而且在它里面装其他应用又要重复做一遍.所以我想到了一个办法,就是让我的主机能够和docker内部的网络互通.

前期准备

所需工具:
win10系统,virtualbox,centos虚拟机,docker及liunx的镜像

环境介绍
win10主机:
主机采用的是win10系统,内部ip地址是192.168.1.114.
在这里插入图片描述

虚拟机:
虚拟机使用的软件用的是virtualbox,安装的是centos7发行版,采用的是桥接网卡模式,网段是和win10主机一致的,所以虚拟机和主机一样可以互相访问和请求外部网络,IP:192.168.1.112.
在这里插入图片描述
在这里插入图片描述

docker容器:
在这里插入图片描述mycentos_ssh是我自己打包的带有ssh服务的镜像

创建网桥:docker network create centos-bridge
在这里插入图片描述
创建容器:docker run -dit --name=centos4 --network centos-bridge linux镜像 /bin/bash "

可以查看刚刚创建的网桥:docker inspect centos-bridge
在这里插入图片描述
centos4容器的ip地址是自动分配的,为172.21.0.2

可以attach进去容器里面看看:docker attach centos4
在这里插入图片描述
容器创建完了.

使用docker的网络桥接很简单,不用怎么配置,容器里面的服务是可以请求外部网络的,也可以访问虚拟机的网络(IP:192.168.1.112).但是我要的不只是访问外部网络,我还需要让内部的服务给外面的主机进行访问,所以下一步要做的就是如何让外面的主机能够访问到里面的服务.

下面开始说重点了

实现步骤

我们知道网络层协议里面,除了同个网段的ip,其他的都是通过路由的下一跳做转发的,它首先会寻找自己的路由表,如果存在这个网络的路由,它的下一跳就直接交给这个下一跳指定的地址或接口,如果没有找到,那就抛给默认网关,默认网关找不到,它就会一值网上抛,直到ttl过期.但是,现在我要访问172.21.0.2,本地的主机,会先将它和 255.255.0.0 掩码做&操作,得到172.21.0.0,这个是它的网络号.但是172.21.0.0这个网络是属于内部网络的,外部网络不可能知道的,所以我们需要设置本机的路由,那我为这个网络号指向192.168.1.112的路由,让它能够找到正确的下一跳.
使用win10的命令执行:
1.route -p add 172.21.0.0 mask 255.255.255.0 192.168.1.112 #永久添加路由
输入: route print可以看到我已经添加了一个永久路由
在这里插入图片描述
现在我通过 ping 172.21.0.2是ping得通的,但是我用telnet 172.21.0.2 22是连接不到的,因为192.168.1.112的虚拟机它只是收到了你的数据包而已,它并不会帮你转发给172.21.0.2的centos容器.

扫描二维码关注公众号,回复: 10244529 查看本文章

那么我们下一步就要对linux虚拟机的做一些配置.
我们虚拟机内部其实也有一个网络,叫SNAT网络,它跟NAT很像,下面的这些就是内部网络里面的ip地址
在这里插入图片描述
其实我在192.168.1.112的虚拟机里面,通过ssh -p [email protected]是可以成功的,那为什么外面的主机就不行,我们可能很快就能够想到防火墙了,在centos7种firewall-cmd已经取代了iptables了,所以我们需要配置firewall-cmd.

将docker网桥的接口添加到外部域:
firewall-cmd --permanent --zone=external --change-interface=br-ad14ad9a5b40

zone是防火墙的所在域,它的选项有:
publish 公开的,它允许ssh,ftp等服务
trusted 信任的网络,它是最高级的,允许所有的请求
external 外部网络
rejected 拒绝任何操,但是仍会做响应
drop 丢弃不做任何响应

对172.21.0.0/24网段做伪装IP设置:
firewall-cmd --permanent --zone=external --add-rich-rule=‘rule family=ipv4 source address=172.21.0.0/24 masquerade’
#add-rich-rule是firewall的富语法,它可以做一些非常强大的事情,这里不做详解.

输入:firewall-cmd --zone=external --list-all
查询刚刚添加配置
在这里插入图片描述

网络转发设置:
firewall-cmd --permanent --direct --passthrough ipv4 -t nat -A POSTROUTING -s 172.21.0.0/24 -j SNAT --to-source 172.21.0.1
#direct命令使用的firewall-cmd本身以外的功能,passthrough 是将命令参数传递过去,这里的passthrough 后面部分使用的是iptables命令的,后面的意思是产生的指向172.21.0.0的新包将跳转到snat网络的172.21.0.1主机,ipv4 -t nat (查询nat表时遇到产生新的链接的包时),-A(是加到链末), POSTROUTING (是指修改为出去的),-j是跳转 ,SNAT -to-source是指向SNAT的目标地址,
#备注:不在万不得已的情况下最好少用direct

输入: firewall-cmd --direct --get-all-passthroughs
查询刚刚添加的转发:
在这里插入图片描述

再重启一下:
firewall-cmd --reload

好了我们验证喜悦的时刻到了
在这里插入图片描述

PS:
1.让主机能够访问虚拟机内部的SNAT网络是为了方便学习,使用docker搭建内部集群和节省时间,但是部署很麻烦,每次部署新的项目,都要做端口映射.
2.本实例前提条件是要虚拟机和docker的网络都能够请求外部的情况下的,限于篇幅,这里不对docker的网络方面做过多的介绍.

发布了6 篇原创文章 · 获赞 7 · 访问量 235

猜你喜欢

转载自blog.csdn.net/liuweijin_hot/article/details/105144953