国产成人精品无码青草_亚洲国产美女精品久久久久∴_欧美人与鲁交大毛片免费_国产果冻豆传媒麻婆精东

18143453325 在線咨詢 在線咨詢
18143453325 在線咨詢
所在位置: 首頁 > 營(yíng)銷資訊 > 建站知識(shí) > Java Netty框架自建DNS代理服務(wù)器教程

Java Netty框架自建DNS代理服務(wù)器教程

時(shí)間:2023-02-10 15:33:01 | 來源:建站知識(shí)

時(shí)間:2023-02-10 15:33:01 來源:建站知識(shí)

前言

DNS協(xié)議作為著互聯(lián)網(wǎng)客戶端-服務(wù)器通信模式得第一關(guān),在當(dāng)下每天都有成千上億上網(wǎng)記錄產(chǎn)生得當(dāng)今社會(huì),其重要性自然不可言喻。在國(guó)內(nèi)比較有名得DNS服務(wù)器有電信得114.114.114.114、阿里云得223.5.5.5,DNSPod得119.29.29.29,配置一個(gè)好的DNS服務(wù)器可以縮短請(qǐng)求響應(yīng)時(shí)間、降低DNS劫持概率,提升上網(wǎng)體驗(yàn)。
上面這些都是互聯(lián)網(wǎng)公用DNS服務(wù)器,本文博主教大家使用 Java Netty 自建DNS代理服務(wù)器,目前網(wǎng)上對(duì)于使用Netty自建DNS服務(wù)器得教程良莠不齊,大多沒有代理步驟,達(dá)不到博主想要得代理效果,因而創(chuàng)建此文。

一、自建DNS代理服務(wù)器有哪些優(yōu)勢(shì)

  1. 域名控制:對(duì)于特定域名可以自由控制訪問權(quán)限(屏蔽對(duì)特定網(wǎng)站訪問)
  2. 域名記錄:記錄局域網(wǎng)內(nèi)各個(gè)主機(jī)得域名訪問(記錄員工上網(wǎng)記錄)
  3. 配置內(nèi)網(wǎng)域名:通過自建DNS服務(wù)器可以配置內(nèi)網(wǎng)域名,節(jié)約成本
  4. DNS負(fù)載均衡:通過自建DNS服務(wù)器可以輕松實(shí)現(xiàn)對(duì)于訪問域名得負(fù)載均衡配置
  5. ...

二、自建DNS代理服務(wù)器代碼

  1. 添加域名黑名單文件,resources 文件夾下添加 black_list.txt 文件
google.com.facebook.com.初始化 BLACK_LIST_DOMAIN

private static final List<String> 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); } }
  1. 使用 UDP 協(xié)議綁定本機(jī)53端口,并初始化 ProxyUdp DNS請(qǐng)求代理對(duì)象
@Slf4jpublic final class DnsServer { private static final List<String> 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<NioDatagramChannel>() { @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()); } }); }}
  1. nioDatagramChannel.pipeline() 添加 ChannelHandler
nioDatagramChannel.pipeline().addLast(new DatagramDnsQueryDecoder()); nioDatagramChannel.pipeline().addLast(new SimpleChannelInboundHandler<DatagramDnsQuery>() { @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.<DatagramDnsQuery>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<DatagramDnsQuery>() 中 解析客戶端DNS查詢報(bào)文, 獲取訪問域名信息,如果訪問域名在黑名單中,則通過 getDatagramDnsResponse() 直接返回 192.168.1.1 的DNS響應(yīng)報(bào)文,反之則通過 proxyUdp 對(duì)象轉(zhuǎn)發(fā)DNS查詢。

  1. ProxyUdp 作為DNS查詢代理類會(huì)通過 send(String domain, int id, Channel serverChannel) 方法傳入DnsServer類收到的訪問域名、DNS事務(wù)ID、serverChannel。隨后包裝訪問域名請(qǐng)求DNS服務(wù)器114.114.114.114,最后通過 new SimpleChannelInboundHandler<DatagramDnsResponse>() 將收到的DNS響應(yīng)報(bào)文通過上一步傳入得 serverChannel 輸出到客戶端。
@Slf4jclass 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<DatagramChannel>() { @Override protected void initChannel(DatagramChannel ch) { ChannelPipeline p = ch.pipeline(); p.addLast(new DatagramDnsQueryEncoder()) .addLast(new DatagramDnsResponseDecoder()) .addLast(new SimpleChannelInboundHandler<DatagramDnsResponse>() { @Override public void channelActive(ChannelHandlerContext ctx) { log.info(ctx.channel().toString()); } @Override protected void channelRead0(ChannelHandlerContext ctx, DatagramDnsResponse msg) { DatagramDnsQuery dnsQuery = localChannel.attr(AttributeKey.<DatagramDnsQuery>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); }}
  1. 自建DNS服務(wù)器全部代碼
@Slf4jpublic final class DnsServer { private static final List<String> 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<NioDatagramChannel>() { @Override protected void initChannel(NioDatagramChannel nioDatagramChannel) { nioDatagramChannel.pipeline().addLast(new DatagramDnsQueryDecoder()); nioDatagramChannel.pipeline().addLast(new SimpleChannelInboundHandler<DatagramDnsQuery>() { @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.<DatagramDnsQuery>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()); } }); }}@Slf4jclass 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<DatagramChannel>() { @Override protected void initChannel(DatagramChannel ch) { ChannelPipeline p = ch.pipeline(); p.addLast(new DatagramDnsQueryEncoder()) .addLast(new DatagramDnsResponseDecoder()) .addLast(new SimpleChannelInboundHandler<DatagramDnsResponse>() { @Override public void channelActive(ChannelHandlerContext ctx) { log.info(ctx.channel().toString()); } @Override protected void channelRead0(ChannelHandlerContext ctx, DatagramDnsResponse msg) { DatagramDnsQuery dnsQuery = localChannel.attr(AttributeKey.<DatagramDnsQuery>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); }}

三、本地測(cè)試

1.修改本機(jī)DNS設(shè)置(win11),修改首選、備選DNS地址為127.0.0.1

2.打開命令行工具,執(zhí)行DNS緩存清除命令 ipconfig/flushdns

自此就可以打開瀏覽器訪問常用網(wǎng)站,看是否能正常訪問,來驗(yàn)證自建的DNS服務(wù)器效果了

關(guān)鍵詞:代理,服務(wù),教程

74
73
25
news

版權(quán)所有? 億企邦 1997-2025 保留一切法律許可權(quán)利。

為了最佳展示效果,本站不支持IE9及以下版本的瀏覽器,建議您使用谷歌Chrome瀏覽器。 點(diǎn)擊下載Chrome瀏覽器
關(guān)閉