1.公网地址和内网地址的区别?
1.1 形象比喻
用邮寄系统作比喻。有公网ip,相当于说你有一个详细的地址,你可以写信寄给别人,别人也可以用这个地址和你进行各种通讯。 无公网ip像是住在一个大院里,所有进出邮件都由收发传达室转交。如果是普通的邮件,可以放在传达室,传达室的大爷看到你了就会转交给你。但有一些场景,比如说大学录取通知书,邮局的快递员说:必须本人签收。传达室的大爷就说了:对不起,所有的邮件都要经过我中转。于是邮局的快递员只好把信带回去了,导致收件人收不到。 实际场景中,有一些通讯无法在透明代理机制下顺利进行,如家里的智能安全摄像头,如果采用代理模式,会有隐私泄露的风险,如果是公网IP,用户可以直接通过公网IP连接,不经过代理,避免隐私泄露。
1.2 公网和内网IP的区别
- 访问权限
访问互联网需要公网 IP 作为身份的标识,而私网 IP 则用于局域网,在公网上是不能使用私网 IP 地址来实现互联网访问的。
- 唯一性
外网 IP 是全世界唯一的 IP 地址,仅分配给一个网络设备。而内网 IP 是由路由器分配给每一部内部使用的 IP 地址。不同内网的 IP 可以一样。
- 数量
外网 IP 有限,无法分配给所有人,遵循先到先得,内网 IP 数量很充沛。
- 意义
公有地址 (Public address)由 INIC(Internet Network Information Center 因特网信息中心)负责。这些 IP 地址分配给注册并向 INIC 提出申请的组织机构。通过它直接访问因特网。私有地址(Private address)属于非注册地址,专门为组织机构内部使用。
1.3 内网如何让外部网络访问
- 静态外网IP端口映射
原理很简单,每个用户都会有一个外网IP,这个IP可以在百度里输入ip直接查到
如果别人输入这个ip地址,它会连接到你的路由器的80端口(如果80端口没有被封,通常是路由器的设置页面).也就相当于家里的路由器充当了内网与外网的一个网关,静态外网端口映射可以理解为设置这个网关,让外网通过访问不同的端口来访问内网的服务。
通常主流路由器都有一个功能叫做端口映射,刚好可以满足这个需求.通常设置端口映射就是填一个包含规则名,端口,目标主机ip,目标端口的的表单,填好后激活就可以使用了。其中规则名是这条规则的唯一标识,端口就是路由器开放的端口,目标主机和目标端口则是要映射服务的主机和端口
| 规则名 | 端口 | 目标主机IP | 目标端口 |
|---|---|---|---|
| demo | 2000 | 192.168.1.200 | 60000 |
要做端口映射还有一个条件就是目标主机必须是静态ip,设置静态ip的方法是
- Win 系统
- Linux系统
通过修改/etc/network/interfaces(以ubuntu为例)
# 配置静态IP使用以下内容
auto eth0 # eth0为以太网卡名称,可以使用ifconfig查询
iface eth0 inet static
address 192.168.1.200 # IP地址
netmask 255.255.255.0 # 子网掩码
gateway 192.168.1.1
# 配置动态IP使用以下内容
auto eth0
iface eth0 inet dhcp
这是最简单的一种实现内网让外网访问的方法,其它方式可用搜索引擎搜索内网穿透关键字自行查找。
2. 正向代理和反向代理
2.1 正向代理
正向代理面向的是用户,用户对外访问网络,都会先经过代理服务器,然后由代理服务器访问真实目标服务器。如科学上网、VPN
2.2 反向代理
反向代理面向的是网络(服务器),用户访问到代理服务器后,由代理分发到真实目标服务器,如 nginx 网关 通过代理服务器分发内容到服务器,避免直接访问服务器,用作堡垒机,另外一种用途就是配置负载均衡
- 反向代理模拟
- 需求:假设有两个服务,一个对外暴露,一个不对外暴露只能内部访问,对外暴露的端口是80,在内部访问的端口是9000,通过访问对外暴露的80服务来访问9000服务
# 配置虚拟主机 192.168.1.101
server {
listen 9000;
server_name 127.0.0.1;
location / {
allow 127.0.0.1;
deny all;
root html;
index index.html index.htm;
}
}
#配置对外暴露的反向代理 本机地址是192.168.1.10
server {
listen 80;
location /{
proxy_pass http://127.0.0.1:9000;
}
}
用192.168.1.101:9000直接访问虚拟主机
用127.0.0.1访问虚拟主机
2.3 两个特殊的端口
搭建网站通常有两种协议http和https,外网访问一般使用80端口和443端口。当然也不是绝对的,如果本地网站协议用的是Http,则使用80访问浏览器可以不带端口号(浏览器自动默认http访问时不带端口就是走80);如果本地网站用https协议的,则可以使用443端口访问时,浏览器不用带上端口号(浏览器自动默认https访问时不带端口就是走443)
3 使用Nginx在web应用中获取用户IP原理
在实际应用中,我们可能需要获取用户的ip地址,比如做异地登陆判断,或者统计ip访问次数等,通常情况下我们使用request.getRemoteAddr()就可以获取到客户端ip,但是当我们使用了nginx作为反向代理后,使用request.getRemoteAddr()获取到的就一直是nginx服务器的ip的地址,那这时应该怎么办?
3.1 只有一个代理服务时
经过反向代理后,由于在客户端和web服务器之间增加了中间层,因此web服务器无法直接拿到客户端的ip,通过$remote_addr变量拿到的将是反向代理服务器的ip地址。如果我们想要在web端获得用户的真实ip,就必须在nginx这里作一个赋值操作,如下:
proxy_set_header X-real-ip $remote_addr;
这个X-real-ip是一个自定义的变量名,名字可以随意取,这样做完之后,用户的真实ip就被放在X-real-ip这个变量里了,然后,在web端可以这样获取:request.getAttribute("X-real-ip")
3.2 途经多个代理服务时
当一个请求通过多个代理服务器时,用户的IP将会被代理服务器IP覆盖,不过仍有办法,获取客户真实的ip地址,通过设置X-Forwarded-For
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
$proxy_add_x_forwarded_for变量包含客户端请求头中的 X-Forwarded-For 与 $remote_addr两部分,它们之间用逗号分开。
举个例子,有一个web应用www.xxx.com, 通过了两次nginx转发,即用户访问www.xxx.com 站点通过两台 nginx。
在第一台 nginx 中:设置
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
现在的proxy_add_x_forwarded_for变量的X-Forwarded-For部分是空的,所以只有remote_addr,而$remote_addr的值是用户的ip,于是赋值以后,X-Forwarded-For变量的值就是用户的真实的ip地址了。
到了第二台nginx,设置:
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
现在的proxy_add_x_forwarded_for变量,X-Forwarded-For部分包含的是用户的真实ip,remote_addr部分的值是上一台nginx的ip地址,于是通过这个赋值以后现在的X-Forwarded-For的值就变成了“用户的真实ip,第一台nginx的ip”,以此类推,如果到了第三台nginx,设置了
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
X-Forwarded-For的值就会变成成了“用户的真实ip,第一台nginx的ip,第二台nginx的ip”, 取 X-Forwarded-For字符串第一个逗号之前的值,就是用户的真实ip.
4 TCP三次握手和4次挥手
TCP比UDP传输数据安全可靠,这个可靠就是建立在三次握手和四次挥手上。 要诠释三次握手和四次挥手,就要引入几个概念:
seq:全称sequence,表示当前发送数据报文分段序号,数据报文比较大的时候,传输时会进行分段。一个TCP报文段的最大长度为65495字节ack:表示期望下次收到的数据报文序号- 标志位(Flags):共6个,即URG、ACK、PSH、RST、SYN、FIN等。具体含义如下:
| 名称 | 含义 |
|---|---|
| SYN | 发起一个新连接。 |
| ACK | 确认序号有效 |
| FIN | 释放一个连接 |
| RST | 重置连接。 |
| PSH | 接收方应该尽快将这个报文交给应用层 |
| URG | 紧急指针(urgent pointer)有效。 |
4.1 三次握手
在传输数据前,两台主机需要通过三次会话建立连接,这个过程我们称为三次握手。三次握手主要为了确认客户端和服务端收发数据都没问题。
第一次握手:客户端向服务端请求建立连接,
- SYN=1(客户端发起一个新连接),
- seq=x(序列号),
客户端进入SYN_SENT状态。这一步什么也证明不了。
第二次握手:服务端向客户端返回确认并请求建立连接,
- SYN=1(服务端发起一个新连接),
- ACK=1 (服务器端回复已收到),
- ack=x+1(服务端期望下次收到客户端报文的消息序号)
- seq=y(服务端的发送消息序列号)
服务端进入SYN_RCVD状态。这一步通信正常,说明客户端发送数据没问题,服务端接收数据也没问题。
第三次握手:客户端向服务端发送确认报文,
- ACK=1 (客户端回复已收到),
- ack=y+1(客户端期望下次收到服务端的报文序列号),
- seq=x+1(客户端本次发送消息的序列号),
这一步通信正常,说明服务端发送数据没问题,客户端接收数据也没问题。 三次握手完成以后,2个主机之间,就可以传输数据啦~
状态变化:
- 客户端和服务器刚开始都处于
CLOSED状态 - 客户端发起请求,客户端打开发送
SYN_SENT状态,同时服务器打开监听LISTEN状态; - 服务器在接收到客户端的请求时,服务器切换为回复
SYN_RECVD状态; - 客户端在接收到服务器的响应时,客户端切换为稳定连接
ESTABLISHED状态的同时发送第二次数据包。 - 服务器在接收到客户端的第二次数据时,服务器切换为稳定连接
ESTABLISHED状态。 - 双方建立稳定连接后,开始正常通信数据。
4.2 四次挥手
当我们的应用程序不需要数据通信了,就会发起断开 TCP 连接。终止一个TCP连接需要经过四次挥手。
流程是客户端告诉服务器,我要断开连接了。服务器端回复,收到断开消息。可能服务器还会再向客户端发送消息,消息发送完之后,告诉客户端,可以断开连接了。客户端收到服务端断开消息后进行回复。服务器收到回复后会断开连接,客户端经过2*MSL(Maximum Segment Lifetime,最大段生命周期)后,也会断开连接。
第一次挥手。客户端发起 FIN 包(FIN = 1),客户端进入 FIN_WAIT_1 状态。
- FIN=1(客户端发起一个关闭连接),
- seq=u(序列号)
第二次挥手。服务器端收到 FIN 包,发出确认包 ACK(ack = u + 1),并带上自己的序号 seq=v,服务器端进入了 CLOSE_WAIT 状态。这个时候客户端已经没有数据要发送了,不过服务器端有数据发送的话,客户端依然需要接收。客户端接收到服务器端发送的 ACK 后,进入了 FIN_WAIT_2 状态。
- ACK=1(客户端信息已收到),
- seq=v(服务端回复收到客户端断开连接报文序列号)
- ack=u+1
第三次挥手。服务器端数据发送完毕后,向客户端发送 FIN 包(seq=w ack=u+1),半连接状态下服务器可能又发送了一些数据,假设发送 seq 为 w。服务器此时进入了 LAST_ACK 状态。
- FIN=1(服务端发起一个关闭连接),
- seq=w(半连接状态序列号)
- ack=u+1
第四次挥手。客户端收到服务器的 FIN 包后,发出确认包(ACK=1,ack=w+1),此时客户端就进入了 TIME_WAIT 状态。注意此时 TCP 连接还没有释放,必须经过 2*MSL 后,才进入 CLOSED 状态。而服务器端收到客户端的确认包 ACK 后就进入了 CLOSED 状态,可以看出服务器端结束 TCP 连接的时间要比客户端早一些。
- ACK=1(客户端收到回复信息),
- seq=u+1(客户端报文序列号),
- ack=w+1
5 什么是ARP欺骗?
ARP 欺骗是一种以 ARP 地址解析协议为基础的一种网络攻击方式, 什么是 ARP 地址解析协议: 一台电脑主机要把以太网数据帧发送到同一局域网的另外一台主机, 它的底层是通过 Mac 地址来确定目的主机, 但是我们在应用层是使用 IP 地址来访问目标主机的, 所以 ARP 的作用就是当一台主机访问一个目标 IP 地址的时候, 它为该主机返回目标 IP 主机的 Mac 地址.
ARP欺骗的分类
- 主机欺骗,主机B欺骗局域网中的主机A。
- 网关欺骗,局域网中的主机欺骗网关,获取其它主机的进入流量。
ARP欺骗的危害
- 造成局域网中的其它主机断网。
- 劫持局域网中其它主机或网关的流量,获取敏感信息等。
ARP欺骗举例
Ubuntu下可以直接使用如下命令安装arpspoof :
apt install dsniff
安装好之后先打开IP转发开关:
echo 1 > /proc/sys/net/ipv4/ip_forward
然后使用 arpspoof 命令进行欺骗, 命令使用方法如下:
arpspoof -i <网卡名> -t <欺骗的目标> <我是谁>
加入局域网中的网关地址是192.168.0.1,主机A地址是192.168.0.10, 分别开两个终端:
终端1, 欺骗主机A我是网关
arpspoof -i eth0 -t 192.168.0.10 192.168.0.1
终端2, 欺骗网关我是主机A
arpspoof -i eth0 -t 192.168.0.1 192.168.0.10
欺骗成功之后可以通过抓包工具查看主机 A 所有的流量.
6. 网络协议
有些资料会把应用层、表示层、会话层合并起来简单表示为“应用层”,变成五层协议。
这五层协议的分工,看到过一个形象的总结:
买东西时候要封装打包(应用层)
打包后要在包裹上贴快递单(传输层)
在快递单上要写源地址目的地址(网络层)
让快递小哥来取件(数据链路层)
快递小哥骑车送件到收货人(物理层)