精华内容
下载资源
问答
  • TCP拦截和网络地址转换 本书将讨论与访问表相关技术,而非访问表本身。这些技术提供了控制网络中数据流 量附加功能。这些功能特性会使读者能够加强进出网络报文附加功能。通过智能地对数 据本身进行操作,...
  • NAT全称是 Network Address Translation, 其实看英文名,就知道它大概意思:网络地址转换严格来说, 这个Address,包括了IP地址和端口。 而这个Translation,则包括来来源地址和目的地址,以及来源端口和目的...

    概要

    NAT的全称是 Network Address Translation, 其实看英文名,就知道它的大概意思:网络地址转换。

    严格来说,

    • 这个Address,包括了IP地址和端口。
    • 而这个Translation,则包括来来源地址和目的地址,以及来源端口和目的端口这4者之间的转换

    那么NAT规则其实定义的就是这4者的映射关系,告诉路由器应该怎么去转换(Translation)

    那么什么时候会用到NAT技术呢,答案是,从一个网络到另外一个网络,有一些文章在写NAT的时候,常讲的是外网(互联网)到私网(私域子网)的通信的时候,其实这只是其中一种场景,实际上,只要是两个网络间需要通信,都可以用NAT来做。

    下面这个图讲的就是互联网和私网这个场景的NAT

        \ | /                  .                               /
       +---------------+  WAN     .           +-----------------+/
       |Regional Router|----------------------|Stub Router w/NAT|---
       +---------------+          .           +-----------------+\
                                  .                      |        \
                                  .                      |  LAN
                                  .               ---------------
                            Stub border
    
            Figure 1: A typical NAT operation scenario
    

    这个图是从NAT的规范rfc.2663 复制过来的,其中WAN就是广域网,LAN是一个局域网,LAN通过路由器连接到WAN,那么要在WAN和LAN之间通信,那就通过的在路由器里面做数据包的NAT转换。

    NAT的地址转换技术有很多种类,但这些技术一般都具备下面这3个特征:

    • 透明地址分配,就是定义外网和内网的地址的映射关系
    • 通过地址转换进行透明路由(这里的路由指的是数据包的转发,而不是指交换路由信息)
    • ICMP的错误包的payload转换

    那么透明地址分配的规则是这个这些技术里面的关键点,这种地址分配又分为:

    • 静态地址分配:这是一种one-to-one的映射关系,这种映射关系明确、简单,不需要在地址转换翻译的过程中管理会话,发出去和回复回来的数据包都有明确的关系。
    • 动态地址分配:非one-to-one的映射关系,一个或者少量的外网地址分配个一个私网的一堆主机,这种情况,则需要通过会话来明确这个映射关系,那么就需要管理会话,这样才知道回复的数据包对应的是哪台主机发出去的(通过会话来查找映射关系,映射关系会话开始的时候就确立了)

    NAT的种类

    NAT根据他的通信种类,又分为4类:

    • 传统NAT或出站NAT: 会话从私有网络发起,是单向的,出站方向的这种会话
    • 双向NAT:会话可以从无论是公有网络还是私有网络发起都行,是双向的
    • 两次NAT:两次NAT是NAT的一个变种,它在转换过程中,把数据包里面源地址和目标地址都给改了,这种情况是因为两个网络的地址有冲突,比如两个网络都是同一个网段,而且主机的地址都一样
    • 多宿主NAT:解决NAT路由的单点故障问题而衍生出来的一种NAT技术

    这么多NAT,对我们最经常需要用到的是传统NAT(出站NAT),下面我们重点讲这种NAT技术

    传统NAT(出站NAT)

    而传统的NAT又分为:

    • Basic NAT,需要一个外部的IP池拿来和做转换,不需要端口参与,要求对每一个当前连接都要对应一个公网IP地址,这种NAT在转换的阶段,指修改IP、ip头的checksum以及一切更高级别和IP相关的checksum(如TCP、UDP、ICMP的header的checksum)的值(使数据包看起来合法),一般来讲你有足够多的外网ip可以用来对应你的内网主机,那就用这种,
    • NAPT, NAPT是Net Address Port Translation, 需要端口参与到映射关系里,为什么需要端口参数呢,因为你的外网ip数量不足以对应到你内网的主机数量,所以需要共享外网IP.

    NAPT的技术有根据地址转换过程阶段分为

    • DNAT,数据包发出去的时候,修改的是目标IP地址,所以叫做Destination NAT,简称DNAT
    • SNAT, 数据包发出去的时候,修改的是源IP地址,所以叫做Source NAT,简称SNAT(但是只看缩写的话,SNAT会有很多其他的定义,有一些厂商,比如WatchGuard,SNAT代表的是Static NAT)

    BASIC NAT

    下面这个图分别演示了路由器在转换过程中的SNAT和DNAT

    image

    SNAT阶段:由于私网对外只有一个IP(一般是拨号拿来的或者运营商给静态分配的),私网的主机A在给公网发出去请求的给Web Server的时候,它的这个请求的数据包先经过路由器,路由器对会把它的地址改为私网对外的唯一的对外的公网地址202.20.65.5,然后在发给Web Server

    DNAT阶段: Web Server收到请求后,开始响应,这个时候它响应的数据包的目标地址就变成了它私网的唯一的对外的公网地址202.20.65.5,但是,路由器收到这个数据包后,要把他转给这个包发起者192.168.1.2,就必须包目的地址改为192.168.1.2然后再发出去,这样主机A才会接受这个包(这里涉及同一个子网到数据链路层包广播的问题)

    那么,这里又有一个问题,在DNAT阶段,路由器是怎么知道,这个报应该把他的目的地址转换位192.168.1.2呢?这里就涉及到上面所说会话管理的问题,路由器(或者说NAT网关)在会话开始的阶段,在第一个个包发出去,它就确认了会话的方向(第一个包的方向就是会话的方向)和对应关系(这里讲的会话的定义是,一小撮用来表达怎么用来完成一个转换的流量集合,这个集合定义为一个会话)

    到这里,又涉及到一个概念是Session flow和packet low的对比(NAT用的Session flow),这里不细讲了,可以直接看rfc规范的这部分

    在传输层里面:

    1. 如果是TCP协议,每个TCP会话的第一个数据包尝试建立一个会话 并包含连接启动信息。(这里涉及到3次握手的过程。TCP Session的确立,是在第一个包含这SYN标志位,而有没有ACK标志位出现后就确认,在TCP的协议里,除了第一个SYNC包,除了其他的包都必须包含ACK标志位)

    2. 如果是UDP又是另外一码事,这里不细讲,看rfc规范吧

    还有关于TCP和UDP详细的会话结束的定义和生命周期,看rfc规范这里

    总的来讲,就是NAT会建立一个session或者connection 跟踪的机制,来跟踪哪个报应该转换到内部的哪个个主机IP

    image

    这个track table 如果,是外网IP足够多的话,那就用静态分配技术,使内外网IP一对一,如果外网IP不够多,那就用动态分配,如何根据这个对照表来动态转换

    NAPT

    大家看上面这个图很快就会发现另外一个问题,如果内网里面有两个主机同时请求Web Server,那怎么转换呢,这个时候,可以把端口作为额外信息加入这个映射表,这个就是NAPT了

    image

    看上图,即使主机A和主机B请求的源端口一样,路由器也可以将他们转换成不一样的的端口,如何在发出去,如何收到Server回复的数据包的时候,再按照转换的规则,原路转换回去就好

    docker和wireshark抓包实例演示

    下面我们用docker建一个有子网络位192.168.5.0的子网的容器,如何在容器它里面去访问一个网站,并通过wireshark来抓这个包看具体是怎么转换的

    # 新建一个桥接子网
    docker network create -d bridge --subnet 192.168.5.0/24 --gateway 192.168.5.1 test_bridge1
    
    # 新建一个名位box 1的容器,并加入这个网络
    docker run --name box1 -p 8082:80 -it --rm  --network=test_bridge1 busybox sh
    

    如何我们在宿主机,看看这个私有网络的网卡是哪个

    route -n
    内核 IP 路由表
    目标            网关            子网掩码        标志  跃点   引用  使用 接口
    192.168.5.0     0.0.0.0    255.255.255.0   U     0      0        0 br-6edc31410314
    

    接着,用wireshark监控这个网卡

    并在box 1这个容器里面区去访问外网

    wget www.baidu.com
    

    然后下面这个截图是wireshark的抓包信息

    image

    可以看到,前面是访问dns,如何接下来就是建立TCP连接,最后是发起http的Get请求

    可以看到info里面是49982->80,这个就是NAPT,主机box1用的端口是49982去访问百度的80

    可以展开这个握手包的传输层看看:

    image

    然后服务器发回握手的第二个包是确认包,我们再看看他的传输层:

    image

    server返回来的包的目的端口是49982,这个就是NAT的映射关系

    实际上,上面这个例子,有几层的NAT,有容器到子网,如何子网到物理机的无线网卡,那么即使你在分别抓这3个地方的包,他们的端口映射是一样的。

    上面这个端口的情况,下面我们来看一下ping 百度的其中一个ip

    ping 182.61.200.6
    

    抓容器的包和子网网桥的包和以及宿主机的包对比一下

    image

    image

    image

    容器本身和网桥里面抓包的source ip 是一样的(这个是容器的veth pair实现的机制所致),IP是192.168.5.2(容器IP)

    而宿主机发出去的source ip以及被NAT网关转换成192.168.3.3,同时也可以看到,回复的ICMP包的地址也同样被按原路转换回去了

    查看宿主机的NAT规则

    上面我们创建容器的时候,绑定了容器box1的80端口到宿主机的8082端口

    docker run --name box1 -p 8082:80 -it --rm  --network=test_bridge1 busybox sh
    

    那这个绑定是怎么回事呢?为什么这样绑定,发给宿主机的8082端口的数据包就会发到容器呢?答案就是NAT,严格来说是宿主机在它的iptables里面增加了DNAT规则,告诉宿主机的iptable,碰到8082的包就发给宿主机的80吧,下面就是这条规则

    > sudo iptables -S -t nat | grep 8082
    -A DOCKER ! -i br-6edc31410314 -p tcp -m tcp --dport 8082 -j DNAT --to-destination 192.168.5.2:80
    

    上面是规则,下面把路由表格列出来

    > sudo iptables -L -t nat
    Chain PREROUTING (policy ACCEPT)
    target     prot opt source               destination         
    KUBE-SERVICES  all  --  anywhere             anywhere             /* kubernetes service portals */
    DOCKER     all  --  anywhere             anywhere             ADDRTYPE match dst-type LOCAL
    
    Chain INPUT (policy ACCEPT)
    target     prot opt source               destination         
    
    Chain OUTPUT (policy ACCEPT)
    target     prot opt source               destination         
    KUBE-SERVICES  all  --  anywhere             anywhere             /* kubernetes service portals */
    DOCKER     all  --  anywhere            !localhost/8          ADDRTYPE match dst-type LOCAL
    ...
    Chain DOCKER (2 references)
    target     prot opt source               destination         
    RETURN     all  --  0.0.0.0/0            0.0.0.0/0                 
    DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:27017 to:172.18.0.2:27017
    DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:8081 to:172.17.0.2:80
    DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:8082 to:192.168.5.2:80
    DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:8083 to:192.168.5.3:80
    DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:8085 to:192.168.6.3:80
    DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:8084 to:192.168.5.4:80
    
    

    用conntrack看当前链接的映射关系

    sudo conntrack -L         
    tcp      6 32841 ESTABLISHED src=192.168.3.3 dst=49.51.200.100 sport=58710 dport=443 src=49.51.200.100 dst=192.168.3.3 sport=443 dport=58710 [ASSURED] mark=0 use=1
    tcp      6 74 TIME_WAIT src=10.1.1.1 dst=10.1.1.32 sport=33634 dport=8082 src=10.1.1.32 dst=10.1.1.1 sport=8082 dport=33634 [ASSURED] mark=0 use=1
    tcp      6 31706 ESTABLISHED src=192.168.3.3 dst=49.51.200.100 sport=55282 dport=443 src=49.51.200.100 dst=192.168.3.3 sport=443 dport=55282 [ASSURED] mark=0 use=1
    ...
    

    欢迎关注我的公众号和我互动

    展开全文
  • 一般虚拟机上网,使用桥接模式配置简单,但如果你的网络环境是ip资源很缺少或对ip管理比较严格的话,那桥接模式就不太适用了,而我们又需要联网。 我们该如何解决呢? 我们需要用到vmware的另一种网络模式:NAT...

    VMware虚拟机三种网络模式详解--NAT(地址转换模式)

    简介                                                                                                              

    一般虚拟机上网,使用桥接模式配置简单,但如果你的网络环境是ip资源很缺少或对ip管理比较严格的话,那桥接模式就不太适用了,而我们又需要联网。

    我们该如何解决呢?

    我们需要用到vmware的另一种网络模式:NAT模式。

     

    NAT(地址转换模式)                                                                                                                                                       

    1、什么是NAT模式?

    NAT模式借助虚拟NAT设备和虚拟DHCP服务器,使得虚拟机可以联网。其网络结构如下图所示:

     

     blob.png

    在NAT模式中,主机网卡直接与虚拟NAT设备相连,然后虚拟NAT设备与虚拟DHCP服务器一起连接在虚拟交换机VMnet8上,这样就实现了虚拟机联网。

    那么我们会觉得很奇怪,为什么需要虚拟网卡VMware Network Adapter VMnet8呢?

    原来我们的VMware Network Adapter VMnet8虚拟网卡主要是为了实现主机与虚拟机之间的通信。

    2、如何设置NAT模式。

    1)设置虚拟机中NAT模式的选项,打开vmware,点击“编辑”下的“虚拟网络编辑器”,设置NAT参数及DHCP参数。

     blob.png

     

     blob.png

    blob.png    

    2)将虚拟机的网络连接模式修改成NAT模式,点击“编辑虚拟机设置”。

     blob.png

    点击“网络适配器”,选择“NAT模式”

     blob.png

     

    3)开机启动系统,编辑网卡配置文件,命令为vi /etc/sysconfig/network-scripts/ifcfg-eth0

     blob.png

    具体配置如下:

     blob.png

    编辑完成,保存退出,然后重启虚拟机网卡,动态获取ip地址

    执行命令ifconfig,无法动态获取ip

     blob.png

    若无法动态获取ip地址的解决方法

    1、  首先确定宿主机 ADSL 能正常上网 ,在控制面板---管理工具----服务中,启动 “VMware DHCP Service”   “VMware NAT Service” (由于VMware的服务拖慢了系统,我把服务改成手动的,需要时再启动)

     blob.png

    2、执行命令dhclient eth0

    3、执行命令ifconfig,发现可以看到ip

     

    3测试

    1)使用ping命令ping外网ip,测试能否联网。

     blob.png

    2)用远程连接工具来测试虚拟机和物理机的连通,发现可以连通

    3)我们现在就来测试一下VMware Network Adapter VMnet8虚拟网卡的作用

    禁用VMware Network Adapter VMnet8

     blob.png

     blob.png

    blob.png

    虚拟机能联通外网,但虚拟机和物理机不能进行通信

    将VMware Network Adapter VMnet8启用之后,发现远程工具可以连接上虚拟机了。

    小结:

    NAT模式,利用虚拟的NAT设备以及虚拟DHCP服务器来使虚拟机连接外网,而VMware Network Adapter VMnet8虚拟网卡是用来与虚拟机通信的。

     

    总结                                                                                                                                                                                             

    设置nat模式上网的注意点

    1、在网络编辑器中设置nat的网关参数和dhcp参数

    2、启用nat模式上网

    3、编辑虚拟机的网卡的ip(可以为静态,可以为动态)

    4、重启网络服务,测试可以联网以及虚拟机和物理机的通信

    展开全文
  • 域名系统( Domain Name System )简称DNS,主要用于主机名字与IP地址之间映射,主机名既可以是一个简单名字,如: solaris或freebsd,也可以是一个全限定域名( Fully Qualified Domain Name, 简称FQDN ),比如...

    from: http://flyinwoods.blog.163.com/blog/static/937640742008991060317/

    域名系统( Domain Name System )简称DNS,主要用于主机名字与IP地址之间的映射,主机名既可以是一个简单名字,如: solaris或freebsd,也可以是一个全限定域名( Fully Qualified Domain Name, 简称FQDN ),比如: Solaris.unpbook.com。

    注意: 严格说来,FQDN也称为绝对名字,而且必须以一个点号结尾,不过用户往往省略结尾的点号。这个点号告知DNS解析器该名字是全限定的,从而不必搜索解析器自己维护的可能域名清单。

    例子:
          freebsd       IN    A         12.106.32.254
                      IN    AAAA      3ffe:b80:1f8d:1:a00:20ff:fea7:686b
                      IN    MX        5 freebsd,unpbook.com.
                      IN    MX        10 mailhost.unpbook.com.

    DNS中的条目称为资源记录(Resource Record 简称RR )。常见的有如下几个:
    A:    A纪录是把一个主机名映射为一个32位的IPv4地址。
           例如:    freebsd IN A 12.106.32.254

    AAAA:     称为“四A(quad A)”记录的AAAA记录把一个主机名映射为一个128位的IPv6地          址。比如: freebsd

    PTR:      “指针记录(pointer record )”,把IP地址映射为主机名。对于IPv4地址,32位地址的4个字节先反转顺序,没个字节都转换成各自的十进制ASCII值(0--255)后,再添上in-addr.arpa, 结果字符串用于PTR查询。    比如上面的freebsd的PTR记录为:254.32.106.12.in-addr.arpa
              对于IPv6地址,128位地址中的32个4位组先反转顺序,每个4位组都被转换成相应的16进制ASCII(0-9,a-f)后,再添上ip6.arpa.如:
              b.6.8.6.7.a.e.f.f.f.0.2..0.a.0.1.0.0.0.d.8.f.1.0.8.b.0.e.f.f.3.ip6.arpa。
            
    MX:       MX记录把右侧给定的主机指定为左侧给定的主机的“邮件交换器(mail.exchanger)”。见上面的例子:第一个优先级为5,第二个优先级为10.当存在多个MX记录时,按照优先级顺序使用,值越小优先级越高。

    CNAME:        代表“canonical name(规范名字)”,它的常见用法是为常用的服务(如ftp和www)指派CNAME记录。如果使用这些服务而不是真实的主机名,那么相应的服务挪到另一个主机时也不必知道。比如: 
                  ftp IN    CNAME     linux.uupbook.com.
                  www IN    CNAME     linux.unpbook.com.
             
    常见的解析器函数是gethostbyname和gethostbyaddr: 前者把主机名映射成IPv4地址,后者执行相反的操作。
    解析器使用UDP向本地名字服务器发出查询,如果本地名字服务器不知道答案,它通常就会使用UDP在整个因特网上查询其他名字服务器。如果答案太长,超出了UDP消息的承载能力,本地名字服务器和解析服务器会自动切换到TCP.


    #include<netdb.h>
    struct    hostent *gethostbyname( const char *hostname );
    成功:返回非空指针
    出错:返回空指针,同时设置h_errno。
    这个函数的局限在于只能返回IPv4地址,但是getaddrinfo函数能够返回同时处理IPv4和IPv6地址。

    结构hostent如下:

    struct    hostent
    {
          char      *h_name;          // 主机官方名,也就是规范名
          char      **h_aliases;      //    主级别名列表
          char      h_addrtype;       //    主机地址类型: AF_INET
          int       h_length;         //    地址长度:4
          char      **h_addr_list;    //    IPv4地址列表
    };

    gethostbyname执行的是对A记录的查询。只能返回IPV4地址。
    注意:所查询的正是主机名和所有别名都是以空字符结尾的C字符串。
    当发生错误时,不设置errno变量,而是将全局整数变量h_errno设置为在头文件<netdb.h>中定义的下列常量之一:
          HOST_NOT_FOUND
          TRY_AGAIN
          NO_RECOVERY
          NO_DATA(等同于NO_ADDRESS)
    NO_DATA错误表示指定的名字有效,但是他没有A记录。只有MX记录的主机名就是这样。

    hstrerror函数以某个h_errno值作为唯一的参数,返回的是一个const char *指针,指向相应的错误的说明。


    #include<netdb>
    struct    hostent *gethostbyaddr( const char *addr, socklen_t len, int family );
    成功: 返回非空指针
    出错: 返回空指针,同时设置h_errno
    该函数试图由一个二进制的IP地址找到相应的主机名,与gethostbyname的行为刚好相反。
    addr参数实际上不是char *类型,而是一个指向存放IPv4地址的某个in_addr结构的指针;len参数实际上不是这个结构的大小;对于IPv4地址为4.family参数为AF_IENT。

    gethostbyaddr在in_addr.arpa域中向一个名字服务器查询PTR记录。


    服务业通常靠名字来认知,getservbyname函数用于根据给定名字查找相应服务。

    #include<netdb.h>
    struct    servent *getservbyname( const char *servname, const char *protoname );
    成功:返回非空指针;
    失败:空指针;
    本函数返回非空指针

    struct    servent
    {
          char      *s_name;          //    服务的正是名字
          char      **s_aliases;      //    别名列表
          int       s_port;           //    服务端口号
          char      *s_proto;         //    使用的协议
    };

    服务名参数servname必须指定。如果同时指定了协议(即protoname参数为非空指针),那么指定的服务必须有匹配的协议。有些因特网服务既用于TCP也用于UDP提供(如DNS)。如果protoname没有指定而servname指定服务支持多个协议,那么返回那个端口号取决于实现。一般来说,支持多个协议的服务旺旺使用相同的TCP端口号和UDP端口号。

    servent结构中关心的主要是端口号。
    注意: 该端口号是以网络字节的顺序返回的,因此把它存放到套接口地质结构时绝对不能调用htons。


    函数getservbyport用于根据给定端口号和可选协议查找相应的服务。
    #include<netdb.h>
    struct    servent *getservbyport( int port, const char *protoname );
    返回: 非空指针表示成功, 空指针表示失败。
    注意: port的值必须为网络字节序,
    ptr = getservbyport( htons(53), "udp");     // DNS using UDP


    getaddrinfo:

    #include<netdb.h>
    int getaddrinfo( const char *hostname, const char *service, const struct addrinfo *hints, struct addrinfo **result );
    返回: 0 -- 成功;    非0 -- 出错。

    本函数通过result指针参数返回一个指向addrinfo结构链表的指针,而addrinfo结构定义在<netdb.h>中。

    struct    addrinfo
    {
          int       ai_flags;
          int       ai_family;                // AF_XXX
          int       ai_socktype;              //    SOCK_XXX
          int       ai_protocol;              //    0 或 IPPROTO_XXX
          socklen_t     ai_addrlen;           //    ai_addr的长度
          char          *ai_canonname;        //  
          struct    sockaddr      *ai_addr;
          struct    addrinfo      *ai_next;
    };

    该函数中hostname参数是一个主机名或地址串,(IPv4 的点分十进制或者IPv6的十六进制数串)。 service参数是一个服务名或十进制端口号数串。
    hints参数可以是一个空指针,也可以是一个指向某个addrinfo结构的指针,调用者在这个结构中填入关于期望返回的信息类型的暗示。比如如果指定的服务既支持TCP也支持UDP,那么调用者可以把hints结构中的ai_socktype成员设置成SOCK_DGRAM,使得返回的仅仅是适用于数据包套接口的信息。

    hints结构中调用这可以设置的成员有:
          ai_flags:     零个或多个在一起的AI_xxx值
          ai_family:    某个AF_xxx值
          ai_socktype:      某个SOCK_xxx值
          ai_protocol
        
    如果hints的参数是一个空指针,本函数就假设ai_flag,ai_socktype和ai_protocol的值均为0,ai_family的值为AF_UNSPEC。

    如果本函数返回成功,那么由result参数指向的变量已被填入一个指针,它指向的是有其中的ai_next成员串接起来的addrinfo结构链表,可以导致返回多个addrinfo结构的情形如下:
          1     如果与hostname参数关联的地址有多个,那么适用于所请求地址簇的每个地址都返回一个对应的结构。
          2     如果service参数指定的服务支持多个套接口类型,那么每个套接口类型都可能返回一个对应的结构,具体取决于hints结构的ai_socktype成员。
        
    在addrinfo结构中返回的信息可现成用于socket调用,随后现成用语是和客户的connect或者sendto调用,或者是适合于服务器的bind调用。
    socket的参数就是addrinfo结构中的ai_family、ai_socktype和ai_protocol成员。connect或bind的第2个和第三个参数就是该结构中的ai_addr(一个指向适当类型套接口地址的指针,地址结构的内容由getaddrinfo函数填写)和ai_addrlen(这个套接口地址结构的大小)成员。

    如果在hints的ai_flags设置了AI_CANONNAME标志,那么本函数返回的第一个addrinfo结构的ai_canonname成员指向所查找的主机的规范名字。例如;
        
          struct    addrinfo      hints, *res;
          bzero( &hints, sizeof(hints) );
          hints.ai_flags = AI_CANONNAME;
          hints.ai_family = AF_INET;
          getaddrinfo( "freebsd4", "domain", &hints, &res );
        
    如果系统没有实现除TCP外的其他SOCK_STREAM(注意: SOCK_STREAM还包括比如SCTP等)协议,那么套接口类型值为SOCK_STREAM的那两个addrinfo结构协议值可为0;同样的,如果系统没有实现UDP外的其他SOCK_DGRAM协议,套接口类型值为SOCK_DGRAM的那两个addrinfo结构协议值可为0.最安全的做法是让getaddrinfo总是返回明确的协议值。

    对于getaddrinfo函数调用一些常见的输入:

    1     指定hostname和service。这是TCP或UDP客户进程调用getaddrinfo的常见输入。该调用返回后,TCP客户在一个循环中针对每个返回的IP地址,逐一调用sock和connect,直到一个连接成功,或者所有的地址尝试完毕为止。而UDP客户,由getaddrinfo填入的套接口地质结构用于调用sendto或connect。如果客户能够判断第一个地址看来不工作,那么可以尝试其余的地址。
    如果客户清楚自己只处理一种类型的套接口,那么应该把hints结构的ai_socktype成员设置成SOCK_STREAM或者SOCK_DGRAM.

    2     典型的服务器进程只值定service而不指定hostname,同时在hints结构中指定AI_PASSIVE标志(表示套接口将被被动打开)。返回的套接口地质结构中应含有一个值为INADDR_ANY(IPv4)或者IN6ADDR_ANY_INIT(IPv6)的IP地址。TCP服务器随后调用socket、bind和listen。如果服务器想要malloc另一个套接口地址结构以从recvfrom获取客户的地址,那么返回的ai_addrlen值给出了这个套接口地址结构的大小。
    同样,如果服务器清楚自己只处理一种套接口,那么应该把hints结构的ai_socktype成员设置成SOCK_STREAM或者SOCK_DGRAM。这样可以避免返回多个结构,其中可能包含错误的ai_socktype值。

    3     服务器程序的另一种设计方法是使用select或者poll函数让服务器进程处理多个套接口。这种情形下,服务器将遍历由getaddrinfo返回的整个addrinfo结构链表,并为每个创建一个套接口,再使用select或者poll。


    gai_strerror:
    #include<netdb.h>
    const char *gai_strerror( int error );
    返回: 指向错误描述消息字符串的指针
    该函数根据getaddrinfo返回的错误返回一个指向对应的出错信息串的字符串的指针。

    freeaddrinfo:

    #include<netdb.h>
    void      freeaddrinfo( struct addrinfo *ai );
    ai参数应指向由getaddrinfo返回的第一个addrinfo结构。这个链表中的所有结构以及由它们所指向的任何动态存储空间(譬如套接口地质结构和规范主机名)都被释放掉。

    加入我们调用getaddrinfo,遍历所返回的addrinfo结构链表后找到所需的结构。如果我们为保存其信息而仅仅复制这个addrinfo结构,然后调用freeaddrinfo,那就引入了一个潜藏的错误。原因在于这个addrinfo结构本身指向动态分配的内存空间(用于存放套接口地质结构和可能有的规范主机名),因此我们保存的结构指向的内存空间已在调用freeaddrinfo时返回给系统,稍后可能用于其他目的。

    一般的流程是:
          struct addrinfo hints, *res, *ressave;
          bzero( &hints, sizeof(hints) );
          hints.ai_flags = AF_xxx;
          ......
          if( getaddrinfo( hostname, service, &hints, &res ) != 0 )
              do_error(...);
            
           ressave = res;
         
           do
           {
           }while( (res = res->ai_next) != NULL );
         
           ....
         
           freeaddrinfo( ressave );   // 这里很重要,不能是res,因为res已经改变了

    getnameinfo:
    getnameinfo是getaddrinfo的互补函数: 它以一个套接口地址为参数,返回描述其中的主机的一个字符串和描述其中的服务的另一个字符串。本函数以协议无关的方式提供了这些信息;也就是说,调用者不必关心存放在套接口地址结构中的协议地址的类型,因为这些细节由本函数自行处理。

    #include<netdb.h>
    int getnameinfo( const struct sockaddr *sockaddr, socklen_t addrlen, char *host, socklen_t hostlen, char *serv, socklen_t servlen, int flags );
    返回:   0----成功;
             非0---出错
            
    sockaddr指向一个套接口地址结构,其中包含带转换成直观可读的字符串的协议地址,addrlen是这个结构的长度。该结构及其长度通常由accept、recvfrom、getsockname、或者getpeername返回。
    带返回的两个直观可读字符串由调用者预先分配存储空间: host和hostlen指定主机字符串, serv和servlen指定服务字符串。如果调用者不想返回主机字符串,那就指定hostlen为0.同样把servlen指定为0就是不想返回服务字符串。<netdb.h>中定义了2个常值用于分配这两个存储空间:NI_MAXHOST给出主机字符串存储空间的最大长度:1025; NI_MAXSERV给出服务名字的最大长度,值为32。

    flags的值:
    NI_DGRAM         数据报服务
    NI_NAMEREQD      如不能从地址解析出名字则返回错误
    NI_NOFQDN        只返回FQDN的主机名部分
    NI_NUMERICHOST   以数串格式返回主机字符串
    NI_NUMBERICSCOPE     以数串格式返回范围标识字符串
    NI_NUMBERICSERV      以数串格式返回服务字符串

    如果知道处理的是数据报套接口时,调用者应该设置NI_DGRAM标志,因为再套接口结构中给出的仅仅是IP地址和端口号,getnameinfo无法就此确定所用协议(TCP/UDP)。


    注意:
    gethostbyname、gethostbyaddr、getservbyname和getservbyport这四个函数是不可重入的,因为它们都返回指向同一个静态结构的指针。

    inet_pton和inet_aton总是可重入的。

    getaddrinfo可重入的原因在于由它调用的函数都可重入;也就是说,它应该调用可重入版本的gethostbyname和getserbyname。本函数返回的结构全部存放在动态分配内存空间的原因之一就是允许它重入。
    getnameinfo可重入的原因在于它调用的函数都是可重入的:也就是说,它应该调用可重入版本的gethostbyname和getserbyname。它的2个结果字符串(分别为主机名和服务名)由调用者分配存储空间,从而允许它可重入。

    Our focus in this chapter has been on hostnames and IP addresses and service names and their port numbers. But looking at the bigger picture, there are four types of information (related to networking) that an application might want to look up: hosts, networks, protocols, and services. Most lookups are for hosts (gethostbyname and gethòstbyaddr), with a smaller number for services (getservbyname and getservbyaddr), and an even smaller number for networks and protocols.

    All four types of information can be stored in a file and three functions are defined for each of the four types:

    1. getXXXent function that reads the next entry in the file, opening the file if necessary.

    2. setXXXent function that opens (if not already open) and rewinds the file.

    3. An endXXXent function that closes the file.

    Each of the four types of information defines its own structure, and the following definitions are provided by including the <netdb.h> header: the hostentnetentprotoent, and serventstructures.

    In addition to the three getset, and end functions, which allow sequential processing of the file, each of the four types of information provides some keyed lookup functions. These functions go through the file sequentially (calling the getXXXent function to read each line), but instead of returning each line to the caller, these functions look for an entry that matches an argument. These keyed lookup functions have names of the form getXXXbyYYY. For example, the two keyed lookup functions for the host information are gethostbyname (look for an entry that matches a hostname) and gethostbyaddr (look for an entry that matches an IP address). Figure 11.21 summarizes this information.

    How does this apply when the DNS is being used? First, only the host and network information is available through the DNS. The protocol and service information is always read from the corresponding file. We mentioned earlier in this chapter (with Figure 11.1) that different implementations employ different ways for the administrator to specify whether to use the DNS or a file for the host and network information.

    Second, if the DNS is being used for the host and network information, then only the keyed lookup functions make sense. You cannot, for example, use gethostent and expect to sequence through all entries in the DNS! If gethostent is called, it reads only the /etc/hosts file and avoids the DNS.

    Although the network information can be made available through the DNS, few people set this up. [Albitz and Liu 2001] describes this feature. Typically, however, administrators build and maintain an /etc/networks file and it is used instead of the DNS. The netstat program with the -i option uses this file, if present, and prints the name for each network. However, classless addressing (Appendix A) makes these functions fairly useless, and these functions do not support IPv6 at all, so new applications should avoid using network names.

    展开全文
  • VMware虚拟机三种网络模式详解--NAT(地址转换模式) 简介 一般虚拟机上网,使用桥接模式配置简单,但如果你的网络环境是ip资源很缺少或对ip管理比较严格的话,那桥接模式...

    VMware虚拟机三种网络模式详解--NAT(地址转换模式)

    简介                                                                                                              

    一般虚拟机上网,使用桥接模式配置简单,但如果你的网络环境是ip资源很缺少或对ip管理比较严格的话,那桥接模式就不太适用了,而我们又需要联网。

    我们该如何解决呢?

    我们需要用到vmware的另一种网络模式:NAT模式。

     

    NAT(地址转换模式)                                                                                                                                                       

    1、什么是NAT模式?

    NAT模式借助虚拟NAT设备和虚拟DHCP服务器,使得虚拟机可以联网。其网络结构如下图所示:

     

     blob.png

    在NAT模式中,主机网卡直接与虚拟NAT设备相连,然后虚拟NAT设备与虚拟DHCP服务器一起连接在虚拟交换机VMnet8上,这样就实现了虚拟机联网。

    那么我们会觉得很奇怪,为什么需要虚拟网卡VMware Network Adapter VMnet8呢?

    原来我们的VMware Network Adapter VMnet8虚拟网卡主要是为了实现主机与虚拟机之间的通信。

    2、如何设置NAT模式。

    1)设置虚拟机中NAT模式的选项,打开vmware,点击“编辑”下的“虚拟网络编辑器”,设置NAT参数及DHCP参数。

     blob.png

     

     blob.png

    blob.png    

    2)将虚拟机的网络连接模式修改成NAT模式,点击“编辑虚拟机设置”。

     blob.png

    点击“网络适配器”,选择“NAT模式”

     blob.png

     

    3)开机启动系统,编辑网卡配置文件,命令为vi /etc/sysconfig/network-scripts/ifcfg-eth0

     blob.png

    具体配置如下:

     blob.png

    编辑完成,保存退出,然后重启虚拟机网卡,动态获取ip地址

    执行命令ifconfig,无法动态获取ip

     blob.png

    若无法动态获取ip地址的解决方法

    1、  首先确定宿主机 ADSL 能正常上网 ,在控制面板---管理工具----服务中,启动 “VMware DHCP Service”   “VMware NAT Service” (由于VMware的服务拖慢了系统,我把服务改成手动的,需要时再启动)

     blob.png

    2、执行命令dhclient eth0

    3、执行命令ifconfig,发现可以看到ip

     

    3测试

    1)使用ping命令ping外网ip,测试能否联网。

     blob.png

    2)用远程连接工具来测试虚拟机和物理机的连通,发现可以连通

    3)我们现在就来测试一下VMware Network Adapter VMnet8虚拟网卡的作用

    禁用VMware Network Adapter VMnet8

     blob.png

     blob.png

    blob.png

    虚拟机能联通外网,但虚拟机和物理机不能进行通信

    将VMware Network Adapter VMnet8启用之后,发现远程工具可以连接上虚拟机了。

    小结:

    NAT模式,利用虚拟的NAT设备以及虚拟DHCP服务器来使虚拟机连接外网,而VMware Network Adapter VMnet8虚拟网卡是用来与虚拟机通信的。

     

    总结                                                                                                                                                                                             

    设置nat模式上网的注意点

    1、在网络编辑器中设置nat的网关参数和dhcp参数

    2、启用nat模式上网

    3、编辑虚拟机的网卡的ip(可以为静态,可以为动态)

    4、重启网络服务,测试可以联网以及虚拟机和物理机的通信

    展开全文
  • 一般虚拟机上网,使用桥接模式配置简单,但如果你的网络环境是ip资源很缺少或对ip管理比较严格的话,那桥接模式就不太适用了,而我们又需要联网。 我们该如何解决呢? 我们需要用到vmware的另一种网络模式:NAT...
  • IP地址转换程序

    2006-02-23 09:05:59
    只要把程序(IP地址转换器V1.0.exe)与数据库(IP.mdb)放在相同目录下,执行“IP地址转换器V1.0.exe”即可。本软件版本未1.0,程序在不断改进,请把改进意见发给我,联系方式:heyinglin@fss.gd。 注意事项:1、...
  • 虚拟机常见网络模型

    2019-09-24 17:54:15
    总的来说,目前有四种常见的网络模型: 桥接 (Bridge Adapter) 使用虚拟交换机(Linux Bridge),将虚拟机和物理机连接...网络地址转换(Network Address Translatation)。这种模型严格来讲,又可以分为 NAT 和 NA...
  • Linux 网络管理

    2018-02-28 10:07:00
    ...前言 前段时间需要配置一台私网 ECS 联外网,阿里云比较推荐...由于我已经拥有一台外网 ECS(不想多掏钱,且我自己的测试环境不需要严格的稳定性要求),因此我决定使用 Iptables 对私网 ECS 的请求进行源地址转换...
  • VMware CentOS网络连接设置

    千次阅读 2015-08-27 16:10:23
    本文使用“网络地址转换(Network Address Transformation, NAT)模式”进行虚拟机与主机连接。 一、介绍 VMware网络适配器三种连接方式: Bridge模式:将虚拟机添加到局域网中,与真实电脑ip等配置相似,如果...
  • 随着ARPANET的建立,各个国家甚至大公司都建立了自己的网络体系结构,如IBM公司研制的分层网络体系结构SNA(System Network Architecture),DEC公司开发的网络体系结构DNS(Digital Network Architecture)。...
  • 基于分组交换的数据通信是实现计算机与计算机之间或计算机与人之间的通信,其通信过程需要定义严格的协议;而基于报文交换的电信通信则是完成人与人之间的通信,因而双方之间的通信规则不必如此严格定义。所以,分组...
  • 一般虚拟机上网,使用桥接模式配置简单,但如果你的网络环境是ip资源很缺少或对ip管理比较严格的话,那桥接模式就不太适用了,而我们又需要联网。 01. 什么是NAT模式 NAT模式借助虚拟NAT设备和虚拟DHCP服务器,使得...
  • 基于分组交换的数据通信是实现计算机与计算机之间或计算机与人之间的通信,其通信过程需要定义严格的协议;而基于报文交换的电信通信则是完成人与人之间的通信,因而双方之间的通信规则不必如此严格定义。所以,分组...
  • 相关说明:NAT用于提供几乎无限地址空间并掩藏内部网络寻址方案,地址管理更加容易,它允许严格控制进入和离开网络的流量;但是静态或动态NAT都存在一个问题,它只能提供一对一的地址转换。使用端口地址转换PAT...
  • 桥接模式因为桥接模式需要为机器设定同网段的IP,为了保证IP的可用性,因而在网络资源管理严格,IP紧张的情况下不适用(学校/公司/实验室)二 NAT模式即地址转换模式如果你的网络ip资源紧缺,但是你又希望你的虚拟机...
  • NAT和PAT

    2020-01-15 18:17:07
    PAT叫端口地址转换,NAT是网络地址转换。 PAT可以看做是NAT的一部分。严格的NAT是一个公有地址替换一个私有地址,而 新的改变 我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,...
  • 它的重点是以主机为中心的家庭网络,其VLAN网络分段和严格的防火墙阻止了对网络的访问。 这样,复杂的网络配置(例如跨接口的共享子网)并不是当前要设置的。 也就是说,它旨在将人为错误减少到最小,并自动运行...
  • NAT基本原理

    2018-02-28 23:04:21
    1.NAT,即网络地址转换技术(Network Address Translation),其适用于四类应用领域:(1)ISP、ADSL与有线电视地址分配;(2)移动无线接入地址分配;(3)电子政务内网等对Internet访问需要严格控制内部网络...
  • NAT(Network Address Translation,网络地址转换),NAT技术使用很广泛,IPv4网络之中,内网与外网有严格边界,即内网主机和公网主机无法实现互访,NAT技术可以转换数据包中外层IP HeaderIP等信息,最终实现私网...
  • 8.5.2 严格的源站选路的traceroute 程序示例 79 8.5.3 宽松的源站选路traceroute程序 的往返路由 80 8.6 小结 81 第9章 IP选路 83 9.1 引言 83 9.2 选路的原理 84 9.2.1 简单路由表 84 9.2.2 初始化路由表 86 ...
  •  Java Bean 是可复用的组件,对Java Bean并没有严格的规范,理论上讲,任何一个Java类都可以是一个Bean。但通常情况下,由于Java Bean是被容器所创建(如Tomcat)的,所以Java Bean应具有一个无参的构造器,另外,...
  • 深入理解 DNS

    2019-11-19 09:43:21
    DNS(Domain Name System)域名系统,它是一个将域名和 IP 地址相互映射一个分布式数据库,把容易记忆主机名转换成主机 IP 地址。 DNS使用 TCP 和 UDP 端口 53。当前,对于每一级域名长度限制是 63 个字符,...
  • Nat种类和p2p打洞

    2020-05-13 20:55:06
    nat (Network Address Translation)是一种吧内网ip端口转换为外网地址端口的网络设备。 一般作为局域网内网的网关。 nat有几种不同的类型 1 full clone 全克隆,一个内网ip,端口映射一组外网ip,端口 2 地址...
  • QQ 1274510382 Wechat JNZ_aming 商业联盟 QQ群538250800 技术搞事 QQ群599020441 解决方案 QQ群152889761 加入我们 QQ群649347320 共享学习 QQ群674240731 ...NAT(地址转换模式) ip资源很缺少或对ip管理比较严格 .
  • 一个功能强悍的网络请求库,使用RxJava2 + Retrofit2 + OKHttp组合进行封装。还不赶紧点击使用说明文档,体验一下吧! 在提issue前,请先阅读【提问的智慧】,并严格按照issue模板进行填写,节约大家的时间。 在使用...

空空如也

空空如也

1 2 3 4 5 6
收藏数 115
精华内容 46
关键字:

严格的网络地址转换