范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

JavaNetty框架自建DNS代理服务器教程

  前言
  DNS协议作为着互联网客户端-服务器通信模式得第一关,在当下每天都有成千上亿上网记录产生得当今社会,其重要性自然不可言喻。在国内比较有名得DNS服务器有电信得114.114.114.114、阿里云得223.5.5.5,DNSPod得119.29.29.29,配置一个好的DNS服务器可以缩短请求响应时间、降低DNS劫持概率,提升上网体验。
  上面这些都是互联网公用DNS服务器,本文博主教大家使用 Java Netty 自建DNS代理服务器,目前网上对于使用Netty自建DNS服务器得教程良莠不齐,大多没有代理步骤,达不到博主想要得代理效果,因而创建此文。一、自建DNS代理服务器有哪些优势域名控制:对于特定域名可以自由控制访问权限(屏蔽对特定网站访问)域名记录:记录局域网内各个主机得域名访问(记录员工上网记录)配置内网域名:通过自建DNS服务器可以配置内网域名,节约成本DNS负载均衡:通过自建DNS服务器可以轻松实现对于访问域名得负载均衡配置...二、自建DNS代理服务器代码添加域名黑名单文件,resources 文件夹下添加 black_list.txt 文件google.com. facebook.com.
  初始化 BLACK_LIST_DOMAINprivate static final List BLACK_LIST_DOMAIN = new ArrayList<>();     static {         String s;         try (InputStream is = DnsServer.class.getClassLoader().getResourceAsStream("black_list.txt");              BufferedReader br = new BufferedReader(new InputStreamReader(is))) {             while (StrUtil.isNotBlank(s = br.readLine())) {                 BLACK_LIST_DOMAIN.add(s);             }         } catch (Exception e) {             log.error(e.getMessage(), e);         }     }
  2.使用 UDP 协议绑定本机53端口,并初始化 ProxyUdp DNS请求代理对象@Slf4j public final class DnsServer {     private static final List BLACK_LIST_DOMAIN = new ArrayList<>();     static {        ...     }      public static void main(String[] args) throws Exception {         ProxyUdp proxyUdp = new ProxyUdp();         proxyUdp.init();         final int[] num = {0};         final NioEventLoopGroup group = new NioEventLoopGroup();         Bootstrap bootstrap = new Bootstrap();         bootstrap.group(group).channel(NioDatagramChannel.class)                 .handler(new ChannelInitializer() {                     @Override                     protected void initChannel(NioDatagramChannel nioDatagramChannel) {                         nioDatagramChannel.pipeline().addLast(...);                     }                 }).option(ChannelOption.SO_BROADCAST, true);          int port = 53;         ChannelFuture future = bootstrap.bind(port).addListener(future1 -> {             log.info("server listening port:{}", port);         });          future.channel().closeFuture().addListener(future1 -> {             if (future.isSuccess()) {                 log.info(future.channel().toString());             }         });     } }
  3.给 nioDatagramChannel.pipeline() 添加 ChannelHandlernioDatagramChannel.pipeline().addLast(new DatagramDnsQueryDecoder());                         nioDatagramChannel.pipeline().addLast(new SimpleChannelInboundHandler() {                             @Override                             protected void channelRead0(ChannelHandlerContext ctx, DatagramDnsQuery msg) {                                 try {                                     DefaultDnsQuestion dnsQuestion = msg.recordAt(DnsSection.QUESTION);                                     String name = dnsQuestion.name();                                     log.info(name + ++num[0]);                                     Channel channel = ctx.channel();                                     int id = msg.id();                                     channel.attr(AttributeKey.valueOf(String.valueOf(id))).set(msg);                                     if (BLACK_LIST_DOMAIN.contains(name)) {                                         DnsQuestion question = msg.recordAt(DnsSection.QUESTION);                                         DatagramDnsResponse dnsResponse = getDatagramDnsResponse(msg, id, question);                                         channel.writeAndFlush(dnsResponse);                                         return;                                     }                                     proxyUdp.send(name, msg.id(), channel);                                 } catch (Exception e) {                                     log.error(e.getMessage(), e);                                 }                             }                              private DatagramDnsResponse getDatagramDnsResponse(DatagramDnsQuery msg, int id, DnsQuestion question) {                                 DatagramDnsResponse dnsResponse = new DatagramDnsResponse(msg.recipient(), msg.sender(), id);                                 dnsResponse.addRecord(DnsSection.QUESTION, question);                                 DefaultDnsRawRecord queryAnswer = new DefaultDnsRawRecord(                                         question.name(),                                         DnsRecordType.A, 600, Unpooled.wrappedBuffer(new byte[]{(byte) 192, (byte) 168, 1, 1}));                                 dnsResponse.addRecord(DnsSection.ANSWER, queryAnswer);                                 return dnsResponse;                             }                              @Override                             public void exceptionCaught(ChannelHandlerContext ctx, Throwable e) {                                 log.error(e.getMessage(), e);                             }                         });                         nioDatagramChannel.pipeline().addLast(new DatagramDnsResponseEncoder());
  在 new SimpleChannelInboundHandler() 中 解析客户端DNS查询报文, 获取访问域名信息,如果访问域名在黑名单中,则通过 getDatagramDnsResponse() 直接返回 192.168.1.1 的DNS响应报文,反之则通过 proxyUdp 对象转发DNS查询。
  4.ProxyUdp 作为DNS查询代理类会通过 send(String domain, int id, Channel serverChannel) 方法传入DnsServer类收到的访问域名、DNS事务ID、serverChannel。随后包装访问域名请求DNS服务器114.114.114.114,最后通过 new SimpleChannelInboundHandler() 将收到的DNS响应报文通过上一步传入得 serverChannel 输出到客户端。@Slf4j class ProxyUdp {     private Channel serverChannel;     private Channel proxyChannel;      public void init() throws InterruptedException {         EventLoopGroup proxyGroup = new NioEventLoopGroup();         Bootstrap b = new Bootstrap();         b.group(proxyGroup)                 .channel(NioDatagramChannel.class)                 .handler(new ChannelInitializer() {                     @Override                     protected void initChannel(DatagramChannel ch) {                         ChannelPipeline p = ch.pipeline();                         p.addLast(new DatagramDnsQueryEncoder())                                 .addLast(new DatagramDnsResponseDecoder())                                 .addLast(new SimpleChannelInboundHandler() {                                     @Override                                     public void channelActive(ChannelHandlerContext ctx) {                                         log.info(ctx.channel().toString());                                     }                                      @Override                                     protected void channelRead0(ChannelHandlerContext ctx, DatagramDnsResponse msg) {                                         DatagramDnsQuery dnsQuery = localChannel.attr(AttributeKey.valueOf(String.valueOf(msg.id()))).get();                                         DnsQuestion question = msg.recordAt(DnsSection.QUESTION);                                         DatagramDnsResponse dnsResponse = new DatagramDnsResponse(dnsQuery.recipient(), dnsQuery.sender(), msg.id());                                         dnsResponse.addRecord(DnsSection.QUESTION, question);                                          for (int i = 0, count = msg.count(DnsSection.ANSWER); i < count; i++) {                                             DnsRecord record = msg.recordAt(DnsSection.ANSWER, i);                                             if (record.type() == DnsRecordType.A) {                                                 // just print the IP after query                                                 DnsRawRecord raw = (DnsRawRecord) record;                                                 DefaultDnsRawRecord queryAnswer = new DefaultDnsRawRecord(                                                         question.name(),                                                         DnsRecordType.A, 600, Unpooled.wrappedBuffer(ByteBufUtil.getBytes(raw.content())));                                                 dnsResponse.addRecord(DnsSection.ANSWER, queryAnswer);                                             }                                         }                                          serverChannel.writeAndFlush(dnsResponse);                                     }                                      @Override                                     public void exceptionCaught(ChannelHandlerContext ctx, Throwable e) {                                         log.error(e.getMessage(), e);                                     }                                 });                      }                 });         proxyChannel = b.bind(0).sync().addListener(future1 -> {             log.info("绑定成功");         }).channel();     }      public void send(String domain, int id, Channel serverChannel) {         this.serverChannel = serverChannel;         DnsQuery query = new DatagramDnsQuery(null, new InetSocketAddress("114.114.114.114", 53), id).setRecord(                 DnsSection.QUESTION,                 new DefaultDnsQuestion(domain, DnsRecordType.A));         this.proxyChannel.writeAndFlush(query);     } }
  5.自建DNS服务器全部代码@Slf4j public final class DnsServer {     private static final List BLACK_LIST_DOMAIN = new ArrayList<>();     static {         String s;         try (InputStream is = DnsServer.class.getClassLoader().getResourceAsStream("black_list.txt");              BufferedReader br = new BufferedReader(new InputStreamReader(is))) {             while (StrUtil.isNotBlank(s = br.readLine())) {                 BLACK_LIST_DOMAIN.add(s);             }         } catch (Exception e) {             log.error(e.getMessage(), e);         }     }      public static void main(String[] args) throws Exception {         ProxyUdp proxyUdp = new ProxyUdp();         proxyUdp.init();         final int[] num = {0};         final NioEventLoopGroup group = new NioEventLoopGroup();         Bootstrap bootstrap = new Bootstrap();         bootstrap.group(group).channel(NioDatagramChannel.class)                 .handler(new ChannelInitializer() {                     @Override                     protected void initChannel(NioDatagramChannel nioDatagramChannel) {                         nioDatagramChannel.pipeline().addLast(new DatagramDnsQueryDecoder());                         nioDatagramChannel.pipeline().addLast(new SimpleChannelInboundHandler() {                              @Override                             protected void channelRead0(ChannelHandlerContext ctx, DatagramDnsQuery msg) {                                 try {                                     DefaultDnsQuestion dnsQuestion = msg.recordAt(DnsSection.QUESTION);                                     String name = dnsQuestion.name();                                     log.info(name + ++num[0]);                                     Channel channel = ctx.channel();                                     int id = msg.id();                                     channel.attr(AttributeKey.valueOf(String.valueOf(id))).set(msg);                                     if (BLACK_LIST_DOMAIN.contains(name)) {                                         DnsQuestion question = msg.recordAt(DnsSection.QUESTION);                                         DatagramDnsResponse dnsResponse = getDatagramDnsResponse(msg, id, question);                                         channel.writeAndFlush(dnsResponse);                                         return;                                     }                                     proxyUdp.send(name, msg.id(), channel);                                 } catch (Exception e) {                                     log.error(e.getMessage(), e);                                 }                             }                              private DatagramDnsResponse getDatagramDnsResponse(DatagramDnsQuery msg, int id, DnsQuestion question) {                                 DatagramDnsResponse dnsResponse = new DatagramDnsResponse(msg.recipient(), msg.sender(), id);                                 dnsResponse.addRecord(DnsSection.QUESTION, question);                                  // just print the IP after query                                 DefaultDnsRawRecord queryAnswer = new DefaultDnsRawRecord(                                         question.name(),                                         DnsRecordType.A, 600, Unpooled.wrappedBuffer(new byte[]{(byte) 192, (byte) 168, 1, 1}));                                 dnsResponse.addRecord(DnsSection.ANSWER, queryAnswer);                                 return dnsResponse;                             }                              @Override                             public void exceptionCaught(ChannelHandlerContext ctx, Throwable e) {                                 log.error(e.getMessage(), e);                             }                         });                         nioDatagramChannel.pipeline().addLast(new DatagramDnsResponseEncoder());                      }                 }).option(ChannelOption.SO_BROADCAST, true);          int port = 553;         ChannelFuture future = bootstrap.bind(port).addListener(future1 -> {             log.info("server listening port:{}", port);         });          future.channel().closeFuture().addListener(future1 -> {             if (future.isSuccess()) {                 log.info(future.channel().toString());             }         });     } }  @Slf4j class ProxyUdp {     private Channel localChannel;     private Channel proxyChannel;      public void init() throws InterruptedException {         EventLoopGroup proxyGroup = new NioEventLoopGroup();         Bootstrap b = new Bootstrap();         b.group(proxyGroup)                 .channel(NioDatagramChannel.class)                 .handler(new ChannelInitializer() {                     @Override                     protected void initChannel(DatagramChannel ch) {                         ChannelPipeline p = ch.pipeline();                         p.addLast(new DatagramDnsQueryEncoder())                                 .addLast(new DatagramDnsResponseDecoder())                                 .addLast(new SimpleChannelInboundHandler() {                                     @Override                                     public void channelActive(ChannelHandlerContext ctx) {                                         log.info(ctx.channel().toString());                                     }                                      @Override                                     protected void channelRead0(ChannelHandlerContext ctx, DatagramDnsResponse msg) {                                         DatagramDnsQuery dnsQuery = localChannel.attr(AttributeKey.valueOf(String.valueOf(msg.id()))).get();                                         DnsQuestion question = msg.recordAt(DnsSection.QUESTION);                                         DatagramDnsResponse dnsResponse = new DatagramDnsResponse(dnsQuery.recipient(), dnsQuery.sender(), msg.id());                                         dnsResponse.addRecord(DnsSection.QUESTION, question);                                          for (int i = 0, count = msg.count(DnsSection.ANSWER); i < count; i++) {                                             DnsRecord record = msg.recordAt(DnsSection.ANSWER, i);                                             if (record.type() == DnsRecordType.A) {                                                 // just print the IP after query                                                 DnsRawRecord raw = (DnsRawRecord) record;                                                 DefaultDnsRawRecord queryAnswer = new DefaultDnsRawRecord(                                                         question.name(),                                                         DnsRecordType.A, 600, Unpooled.wrappedBuffer(ByteBufUtil.getBytes(raw.content())));                                                 dnsResponse.addRecord(DnsSection.ANSWER, queryAnswer);                                             }                                         }                                          localChannel.writeAndFlush(dnsResponse);                                     }                                      @Override                                     public void exceptionCaught(ChannelHandlerContext ctx, Throwable e) {                                         log.error(e.getMessage(), e);                                     }                                 });                      }                 });         proxyChannel = b.bind(0).sync().addListener(future1 -> {             log.info("绑定成功");         }).channel();     }      public void send(String domain, int id, Channel localChannel) {         this.localChannel = localChannel;         DnsQuery query = new DatagramDnsQuery(null, new InetSocketAddress("114.114.114.114", 53), id).setRecord(                 DnsSection.QUESTION,                 new DefaultDnsQuestion(domain, DnsRecordType.A));         this.proxyChannel.writeAndFlush(query);     } }三、本地测试
  1.修改本机DNS设置(win11),修改首选、备选DNS地址为127.0.0.1
  2.打开命令行工具,执行DNS缓存清除命令 ipconfig/flushdns
  自此就可以打开浏览器访问常用网站,看是否能正常访问,来验证自建的DNS服务器效果了

2022人才迁徙趋势互联网岗位缩招五成,新能源汽车求职人数增长两倍以上2022年,就业市场达到U型周期底部,但同时也迎来回升曲线。在市场回暖之际,脉脉人才智库发布抢滩数字时代人才迁徙报告2023,通过平台大数据分析,盘点2022年人才流动趋势。报告针拿下收视第一,湖南卫视跨年晚会,三大优势击败四大卫视夺冠!一年一度的跨年晚会落下帷幕!七台跨年晚会,每一家都各出奇招,当然从收视上来看,央视一骑绝尘,毕竟有着雄厚的观众基础,而从卫视跨年晚会来说,自然湖南卫视拿下第一,收视最高破2,一路领全国政协常委马正其稳外贸稳外资促进经济平稳健康发展稳外贸稳外资事关经济全局。从全国看,我国有进出口业务的存续外贸企业约641万家,创造就业岗位超过2000万个,带动就业约1。8亿人,对我国经济平稳健康增长意义重大。中央经济工作会议冬游贵州,走一条不寻常的暖心探秘之旅浙里黔行话共富宣传推广活动今日启程秋风吹尽旧庭柯,黄叶丹枫客里过。贵州冬游地图贵州省文化和旅游厅供图初冬的贵州,虽没有银装素裹的景象,但在这个以山地为特色的公园省,同样有着令人神往的魅力,隐藏在绿水青山中的村庄颜值团岛山公园更新亮相半岛全媒体记者孟达12月29日,团岛山公园里,一些市民在这里感受新环境带来的全新体验。伴随着青岛市公园城市建设的推进,团岛山公园前期经过了一系列施工改造,目前已经亮相在市民眼前。团记录报临阵变卦,本菲卡不满切尔西对恩佐正式报价低于解约金直播吧1月5日讯据记录报报道,切尔西对恩佐费尔南德斯的正式报价低于当初所承诺的报价,而本菲卡拒绝以低于球员解约金的价格出售恩佐。报道称,恩佐费尔南德斯已经离加盟切尔西越来越远,因为泰国预计明年中国游客达500万人次泰国预计明年有望接待300万至500万人次的中国游客。图为12月7日泰国一处海滩上的游客。(法新社)(曼谷讯)随着中国逐步解除冠病防御措施,泰国预计明年有望接待300万至500万人浓浓烟火气日接待游客超3万人次!海南迎客流高峰视频加载中(央视财经天下财经)元旦假期,围绕冰雪运动赏灯夜游等主题,多地举办了形式多样的特色活动,推动文旅相关产业复苏回暖。元旦期间,河北崇礼各大雪场迎来冬奥会后首个雪季,冬奥场景40度,50度高温扎堆2022年!2023年地球会更热?人类该何去何从?2022年全球的气候变化,再次让我们看到了极端性的气候表现非常强烈。无论是高温,干旱,降雨等气候现象,都让我们见识到了,2022年的气候或许真的是一个临界点,极端性气候现象表现真的2023年天象预报2022年的天宇是非常热闹的,我们一起见证了千年一遇的红月亮掩天王星2018年以来最大的火星绚烂的双子座流星雨那么,2023年又有哪些精彩天象是值得我们期待的呢?我们一起看看这份天回顾2022这一年的手机圈,几个关键词被大家一直吐槽的2022年,这下,真的结束了。机哥一刷朋友圈,大家发的内容都很统一。不是在晒网易云QQ音乐年度报告的,就是在晒美团饿了么的年度账单。(看完发现只有我是个穷鬼)而机哥
联想ThinkPhone渲染图和规格曝光IT之家12月16日消息,此前消息称联想计划近期推出ThinkPhone品牌的智能手机,代号为Bronco,相关渲染图已经曝光,并通过了国内的3C认证,显示支持68W快充。现在国外行情国内可穿戴腕带设备市场排名华为第1小米第2研究机构Canalys公布了2022年第三季度中国大陆可穿戴腕带市场报告整体出货1210万台,同比下滑7。0。具体智能手表品类同比增长16。8至340万台,手环连续八个季度同比下跌华帝售后怎么样?华帝售后电话有人用过吗?华帝售后服务怎么样?这个问题只有认真体验过的用户才有发言权。作为家里刚刚装完华帝燃气灶的真实用户,个人认为这个问题,我还是有一定的发言权。作为国内厨电行业的前三的知名品牌,经过30抖音图片怎么去水印下载一点击分享按钮,再点复制链接,把图片链接复制下来二打开微信,在发现栏搜一只猫去水印小程序三进入程序后,先把刚才复制的链接,粘贴到解析框内,然后点击解析,完成后即可下载原图笔者寄语官Win11学院如何强制让Windows11设备蓝屏IT之家12月15日消息,在Win11系统中蓝屏(BSoD)也称为停止错误(StopError)和错误检查(BugCheck),通常情况下只有在遇到关键问题的时候才会出现。显然你希一分价钱一分货?官翻机你会买吗?华为nova9官翻机今日开售购买电子产品,大家总是怕买到二手翻新的!就是怕品质有问题,售后没保证!,不过现在不少厂家都有官翻的机器了,性价比其实很高的,比如笔者现在经常用一台MacBookPro就是购买的官翻华为在日本正将重心转向智能手表在日本的智能手表市场,华为技术等中国企业正在加强攻势。通过价格比美国苹果更适中的商品来充实产品线。抢占因新冠疫情下健康意识增强而增长的市场。由于美国限制用于智能手机的尖端半导体的对华为小米官宣之后,微信也做了这个大动作微信的体积占用问题,我们已经讨论过太多次,也讨论得相当深入了。无论是长期使用后聊天产生的数据日积月累下来的,还是越来越多的工作生活交流和办事流程转移到微信中,亦或是微信自身业务规模市值蒸发超1300亿,史玉柱重回台前,巨人网络还能崛起吗?60岁的史玉柱,重新回到了巨人网络的台前。据媒体报道,已经退休多年的史玉柱,在今年8月决定重返巨人网络的研发一线,不但当起了新游戏原始征途的产品经理,还亲自指导了这款产品的改进工作国家级先进制造业集群增至45个数据来源工信部制图汪哲平记者近日从工信部获悉伴随着武汉市光电子信息集群等20个集群在工信部第三轮先进制造业集群决赛中胜出,我国重点培育的国家级先进制造业集群增至45个。国家级集群成土耳其首个移动卫星网络计划HelloSpace准备进入太空HelloSpace将生产一颗拥有世界最新技术和卫星领域最小卫星标准的袖珍卫星。作为土耳其第一个和世界第三个移动卫星网络倡议,HelloSpace准备向伊斯坦布尔发送其第一颗卫星,