60-客户端也能做服务器?

本文的标题预示着接下来我们要做一件有意思的事,之前我们写的客户端程序,也可以拿来做服务器使用。

1. 程序路径

代码托管在 gitos 上,请使用下面的命令获取:

git clone https://git.oschina.net/ivan_allen/unp.git

如果你已经 clone 过这个代码了,请使用 git pull 更新一下。本节程序所使用的程序路径是 unp/program/echo_udp/basic 以及 unp/program/echo_udp/verify

2. 实验思路

  • 找到客户端绑定的套接字地址

要想让客户端成为服务器很简单,只要客户端绑定了套接字地址即可。然而,客户端绑定套接字地址是隐式发生的,即在 sendto 的时候发生的,系统为随机会客户端分配一个端口号。只要我们知道了在 sendto 时的端口号,就可以给客户端发送数据了。

  • 让客户端阻塞到 recvfrom 上

这种我们在上一篇文章中已经学会了,只要给一个不存在的服务器发数据,客户端就能阻塞到 recvfrom 上了。

3. 实验步骤

  • 在 sun 主机开启 tcpdump
sun $ sudo tcpdump -ttt -i ens33 "host mars and host flower" and udp
  • sun 主机上启动客户端,让客户端阻塞到 recvfrom
// mars 主机上的服务器不能启动
sun $ ./echo -h mars

启动客户端后,随便输入一些数据。


这里写图片描述
图1 向 mars 发送 udp 数据报

由于 mars 并没有启动,所以客户端阻塞到了 recvfrom 上。观察 tcpdump 输出,客户端绑定的端口号是 55904.

  • 在 flower 主机上再启动一个客户端
// 准备给 sun 上的 55904 端口发数据
flower $ ./echo -h sun -p 55904


这里写图片描述
图2 sun 的客户端阴差阳错的收到了 flower 发来的数据

4. 结果分析

不知道对此你能联想到什么,漏洞?攻击?

是的,这绝对是客户端的漏洞。如果别人知道了这个客户端的端口号(比如遍历端口),就完全可以给这个客户端发送一些带有恶意的数据,是不是?

幸亏 recvfrom 有一个参数指定的缓冲区的大小,不然还会弄出一个溢出攻击呢。

作为客户端,对收到的数据做验证是相当重要的,因为客户端并不能保证给它发数据的那个人就是它指定的服务器,而是可以是任何人。具体方法很简单,我们只要将 recvfrom 接收到的 ip 地址进行比对即可。

具体我将其封装成了一个 verify 函数:

// 返回 1 表示验证成功,0 表示失败
int verify(struct sockaddr_in *a, int len1, struct sockaddr_in *b, int len2) {
  if (len1 != len2 || memcmp(a, b, len1) != 0) {
    return 0;
  }
  return 1;
}

修正后的程序可以在 unp/program/echo_udp/verify 找到。


这里写图片描述
图3 修正后的程序,对于未知的套接字地址发来的数据不予理会

5. 总结

  • 为什么客户端也能做服务器
  • 如何验证客户端收到的数据确实是指定的服务器发来的
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值