Go语言网络编程: 模拟实现DNS服务器
环境: 两台虚拟机,不限系统
写在前面
DNS服务器是干什么的?DNS服务器(Domain Name Server,域名服务器)是进行域名和与之相对应的IP地址进行转换的服务器,保存了一张域名和与之相对应的IP地址 的表,以解析消息的域名。
在Linux上使用nslookup可以查询域名对应的IP
$ nslookup google.com
Server: 114.114.114.114
Address: 114.114.114.114#53
Non-authoritative answer:
Name: google.com
Address: 142.251.43.14
初步环境搭建
目前有一台ubuntu虚拟机将作为DNS服务器,在ubuntu中执行命令 sudo lsof -i:53,查看占用53端口的进程,强行关掉该进程,解除对UDP 53端口的占用。
另一台虚拟机系统为Linux Lite,后续将用来发送DNS请求。在ubuntu的终端中输入ifconfig查看IP地址。
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.53.129 netmask 255.255.255.0 broadcast 192.168.53.255
inet6 fe80::f60:737c:cda6:87b2 prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:92:bc:64 txqueuelen 1000 (Ethernet)
于是ubuntu的IP地址为192.168.53.129,将该地址作为Linux Lite的DNS服务器地址。
在Linux Lite的终端中输入sudo vim /etc/resolv.conf,用管理员权限修改该文件,将nameserver 对应的IP修改为ubuntu的IP地址。
# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
# DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
# 127.0.0.53 is the systemd-resolved stub resolver.
# run "systemd-resolve --status" to see details about the actual nameservers.
nameserver 192.168.53.129
search localdomain
修改后的文件内容如上,这样Linux Lite的DNS查询会发到ubuntu上。
编写DNS服务器
使用github.com/miekg/dns,可通过go get下载
DNS服务器将处理到来的DNS请求,并返回应答。
代码如下
package main
import (
"github.com/miekg/dns"
"log"
"net"
)
// 处理到来的请求
func handler(writer dns.ResponseWriter, req *dns.Msg) {
var resp dns.Msg
resp.SetReply(req) // 创建应答
for _, question := range req.Question {
recordA := dns.A{
Hdr: dns.RR_Header{
Name: question.Name,
Rrtype: dns.TypeA,
Class: dns.ClassINET,
Ttl: 0,
},
A: net.ParseIP("127.0.0.1").To4(), // 全部解析为127.0.0.1
}
resp.Answer = append(resp.Answer, &recordA) // 写入应答
}
err := writer.WriteMsg(&resp) // 回写信息
if err != nil {
return
}
}
func main() {
dns.HandleFunc(".", handler) // 绑定函数
err := dns.ListenAndServe(":53", "udp", nil) // 启动
if err != nil {
log.Println(err)
}
}
如上代码所示,首先调用HandleFunc,该函数的第一个参数是匹配的查询模式,第二个参数是处理函数。查询模式指示了处理函数将处理哪些请求,使用"."意味着handler将处理所有请求。handler函数负责处理到来的请求,具有两个参数: ResponseWriter和请求本身。在该函数内部,首先要使用SetReply创建响应消息并进行设置。
使用for 循环遍历请求中的每一个询问,使用A记录为每一个询问创建应答。使用append函数将指向A记录的指针添加到应答中,然后使用WriteMsg函数将消息写回客户端。
最后调用ListenAndServe启动DNS服务器,将所有的请求解析为127.0.0.1
测试
用管理员权限在ubuntu上运行程序,然后在Linux Lite的终端输入nslookup google.com,即查询google.com的IP地址。
输出结果
Server: 192.168.53.129
Address: 192.168.53.129#53
Non-authoritative answer:
Name: google.com
Address: 127.0.0.1
Name: google.com
Address: 127.0.0.1
被解析为了127.0.0.1
Go语言网络编程: 模拟实现DNS服务器的更多相关文章
- 11. Go 语言网络编程
Go 语言网络编程 Go语言在编写 web 应用方面非常得力.因为目前它还没有 GUI(Graphic User Interface 图形化用户界面)的框架,通过文本或者模板展现的 html 界面是目 ...
- 《Go语言网络编程》第一章:体系
原书地址:http://tumregels.github.io/Network-Programming-with-Go 如果不知道想要构建什么,是不可能创建一个系统的.而且如果不知道它工作的环境,也同 ...
- python学习(九) 网络编程学习--简易网站服务器
python `网络编程`和其他语言都是一样的,服务器这块步骤为:`1. 创建套接字``2. 绑定地址``3. 监听该描述符的所有请求``4. 有新的请求到了调用accept处理请求` Python ...
- C语言网络编程(Linux && Windows)(1)
和朋友一起做课程设计,同时学习C语言的网络编程,以前写的都是python网络编程,但python很多的库都是封装好的,大部分人在使用的时候不会去了解底层的实现,这样对长远的学习不太好,也改正自己这方面 ...
- 《UNIX网络编程》TCP客户端服务器例子
最近在看<UNIX网络编程>(简称unp)和<Linux程序设计>,对于unp中第一个获取服务器时间的例子,实践起来总是有点头痛的,因为作者将声明全部包含在了unp.h里,导致 ...
- Windows网络编程(C/C++服务器编程)
Windows服务器网络编程 Linux服务器网络编程
- 跟着拉大锯大神学Android——网络编程中运行后台服务器端口占用问题
拉大锯网页地址:https://www.sunofbeach.net/u/1153952789488054272 跟着拉大锯大神学Android,在学到网络编程时,使用了大神搭建的用于学习的后台服务器 ...
- Java网络编程(模拟浏览器访问Tomcat服务器)
程序运行结果: HTTP/1.1 404 Not FoundServer: Apache-Coyote/1.1Content-Type: text/html;charset=utf-8Content- ...
- GO语言网络编程
socket编程 Socket是BSD UNIX的进程通信机制,通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄.Socket可以理解为TCP/IP网络的API,它 ...
- linux 网络编程:客户端与服务器通过TCP协议相互通信 + UDP
1.TCP编程的客户端一般步骤: 1.创建一个socket,用函数socket(): 2.设置socket属性,用函数setsockopt():* 可选: 3.绑定IP地址.端口等信息到socket上 ...
随机推荐
- pintia 3-7-5 逆波兰表达式求值 (20 分)
3-7-5 逆波兰表达式求值 (20 分) 逆波兰表示法是一种将运算符(operator)写在操作数(operand)后面 的描述程序(算式)的方法.举个例子,我们平常用中缀表示法描述的算式(1 + ...
- GFF2GTF.py2
import sys inFile = open(sys.argv[1],'r') for line in inFile: #skip comment lines that start with th ...
- 基于Extjs web设计器
通过从左边的树拖入字段到右边,编辑字段属性,在界面所见即所得 进入链接 http://www.e-ipd.com:8080/crk/public/login.aspx?ReturnUrl=%2fcrk ...
- Linux防火墙相关命令
查看以开放端口 firewall-cmd --list-ports 开启端口如6379 firewall-cmd --zone=public --add-port=6379/tcp --permane ...
- 日志注解,基于ruoyi的后置切面改进而来
有次接口响应时间太长,想知道具体接口执行的时间是多少,于是决定通过注解来实现这个想法,刚好ruoyi本身就提供了完善的日志注解,虽然是采用后置通知,但是完全不影响我们改造它. 想要实现接口耗时的功能, ...
- jquery中,某些写法后来更新导致版本不支持的替代方法
等号后面的书写替换前面老的书写方法 $.browser.mozilla = /firefox/.test(navigator.userAgent.toLowerCase());$.browser.we ...
- MIUI 12.5稳定版关闭充电提示音的方法
手机开启开发中模式 将手机连接电脑 打开cmd, 输入命令:adb shell settings put global power_sounds_enabled 0,即可关闭充电时的提示音 输入命令: ...
- What Are You Weighting For?
A basic strength routine can change your life Strength training isn't just about getting six-pack ab ...
- 05-Spring的AOP编程之基于注解开发
Spring的AOP基于注解的开发 首先在AOP配置文件中,开启注解的aop开发 <aop:aspectj-autoproxy></aop:aspectj-autoproxy> ...
- 前端小白启动开源框架vue-element
开发java的我按耐不住想学前端的冲动不想看培训机构的视频,决定自学遇到那种"前端知识图谱"的知识架构,看一眼就完了,不能拿来做入门用入门就得是先把工作环境搭起来,能出活就ok了 ...