時(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)建此文。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); } }
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()); } }); }}
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查詢。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); }}
@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); }}
ipconfig/flushdns
關(guān)鍵詞:代理,服務(wù),教程
客戶&案例
營(yíng)銷資訊
關(guān)于我們
客戶&案例
營(yíng)銷資訊
關(guān)于我們
微信公眾號(hào)
版權(quán)所有? 億企邦 1997-2025 保留一切法律許可權(quán)利。