分类
其它综合

常见的DNS域名劫持方式及解决方法

DNS劫持又称域名劫持,是指在劫持的网络范围内拦截域名解析的请求,分析请求的域名,把审查范围以外的请求放行,否则返回假的IP地址或者什么都不做使请求失去响应,其效果就是对特定的网络不能访问或访问的是假网址。

DNS劫持方法

方式一:利用DNS服务器进行DDOS攻击

正常的DNS服务器递归询问过程可能被利用成DDOS攻击。假设攻击者已知被攻击机器IP地址,然后攻击者使用该地址作为发送解析命令的源地址。这样当使用DNS服务器递归查询后,DNS服务器响应给最初用户,而这个用户正是被攻击者。那么如果攻击者控制了足够多的肉鸡,反复地进行如上操作,那么被攻击者就会受到来自于DNS服务器的响应信息DDOS攻击。

方式二:DNS缓存感染

攻击者使用DNS请求,将数据放入一个具有漏洞的DNS服务器的缓存当中。这些缓存信息会在客户进行DNS访问时返回给用户,从而把用户客户对正常域名的访问引导到入侵者所设置挂马、钓鱼等页面上,或者通过伪造的邮件和其他的server服务获取用户口令信息,导致客户遭遇进一步的侵害。

方式三:DNS信息劫持

原则上TCP/IP体系通过序列号等多种方式避免仿冒数据的插入,但入侵者如果通过监听客户端和DNS服务器的对话,就可以猜测服务器响应给客户端的DNS查询ID。每个DNS报文包括一个相关联的16位ID号,DNS服务器根据这个ID号获取请求源位置。攻击者在DNS服务器之前将虚假的响应交给用户,从而欺骗客户端去访问恶意的网站。假设当提交给某个域名服务器的域名解析请求的数据包被截获,然后按截获者的意图将一个虚假的IP地址作为应答信息返回给请求者。这时,原始请求者就会把这个虚假的IP地址作为它所要请求的域名而进行连接,显然它被欺骗到了别处而根本连接不上自己想要连接的那个域名。

方式四:DNS重定向

攻击者如果将DNS名称查询重定向到恶意DNS服务器。那么被劫持域名的解析就完全置于攻击者的控制之下。

方式五:ARP欺骗

ARP攻击就是通过伪造IP地址和MAC地址实现ARP欺骗,能够在网络中产生大量的ARP通信量使网络阻塞,攻击者只要持续不断的发出伪造的ARP响应包就能更改目标主机ARP缓存中的IP-MAC条目,造成网络中断或中间人攻击。

ARP攻击主要是存在于局域网网络中,局域网中若有一台计算机感染ARP木马,则感染该ARP木马的系统将会试图通过"ARP欺骗”手段截获所在网络内其它计算机的通信信息,并因此造成网内其它计算机的通信故障。ARP欺骗通常是在用户局网中,造成用户访问域名的错误指向,但在IDC机房被入侵后,则也可能出现攻击者采用ARP包压制正常主机、或者压制DNS服务器,而李代桃僵,以使访问导向错误指向的情况。

方式六:本机劫持

在计算机系统被木马或流氓软件感染后可能会出现部分域名的访问异常,如访问挂马或者钓鱼站点、无法访问等情况,本机劫持有hosts文件篡改、本机DNS劫持、SPI链注入、BHO插件等方式,虽然并非都通过DNS环节完成,但都会造成无法按照用户意愿获得正确的地址或者内容的后果。

如何防止DNS劫持

1、互联网公司准备两个以上的域名,一旦黑客进行DNS攻击,用户还可以访问另一个域名。

2、手动修改DNS:

在地址栏中输入:http://192.168.1.1 (如果页面不能显示可尝试输入:http://192.168.0.1)。

填写您路由器的用户名和密码,点击“确定”。

在“DHCP服务器—DHCP”服务中,填写主DNS服务器为更可靠的114.114.114.114地址,备用DNS服务器为8.8.8.8,点击保存即可。

3、修改路由器密码:

在地址栏中输入:http://192.168.1.1 (如果页面不能显示可尝试输入:http://192.168.0.1)

填写您路由器的用户名和密码,路由器初始用户名为admin,密码也是admin,如果您修改过,则填写修改后的用户名和密码,点击“确定”

填写正确后,会进入路由器密码修改页面,在系统工具——修改登录口令页面即可完成修改(原用户名和口令和2中填写的一致)

分类
其它综合

帝恩思:DNS服务器地址是什么?

说到DNS服务器地址,那么就要先科普一下什么是DNS?

DNS:是域名系统 (Domain Name System)的缩写,是一种组织成域层次结构的计算机和网络服务命名系统。域名系统为Internet上的主机分配域名地址和IP地址。用户使用域名地址,该系统就会自动把域名地址转为IP地址。域名服务是运行域名系统的Internet工具。执行域名服务的服务器称之为DNS服务器,通过DNS服务器来应答域名服务的查询。

DNS服务器地址:

域名解释服务器,打比方,当你在地址栏输入 www.dns.com 时,电脑不是直接就连接到百度的服务器里的,而是先向这个DNS服务器查询www.dns.com的IP地址,然后再按照这个IP地址转到百度的服务器里.一般都是每个地区有一个特定的DNS服务器的,由ISP提供的.

DNS地址是一个域名服务器地址,它负责把用户的网站地址解析成IP地址。如果这个服务器出现问题,那么你就可能上不了网了。我估计世界上没有哪个强人能记住所有自己经常去的网站的IP地址吧。

DNS 全名叫 Domain Name Server,中文俗称“域名服务器”,在说明 DNS Server 之前,可能要先说明什么叫 Domain Name(域名)。正如上面所讲,在网上辨别一台电脑的方法是利用 IP地址,但是 IP用数字表示,没有特殊的意义,很不好记,因此,我们一般会为网上的电脑取一个有某种含义又容易记忆的名字,这个名字我们就叫它“Domain Name"。

例如:著名的域名解析服务提供商 DNS.COM 来说,一般使用者在浏览这个网站时,都会输入http://www.dns.com,很少有人会记住这台Server的 IP 是多少?所以http://www.dns.com 就是DNS.COM站点的 Domain Name。这正如我们在跟朋友打招呼时,一定是叫他的名字,几乎没有人是叫对方身份证号码的吧!但是由于在 Internet 上真实辨认机器的还是IP,所以当使用者在浏览器中输入Domain Name 后,浏览器必须先到一台有 Domain Name 和 IP 对应信息的主机去查询这台电脑的 IP,而这台被查询的主机,我们称它为 Domain Name Server,简称 DNS.

例如:当你输入http://www.dns.com时,浏览器会将http://www.dns.com这个名字传送到离它最近的 DNS Server 去做辨认,如果查询到结果,则会传回这台主机的 IP地址,进而跟它发生连接,但如果没有查询到,就会出现类似 DNS NOT FOUND 等告警信息。所以一旦你的电脑的DNS Server 设置不正确,就好比是路标错了,电脑也就不知道该把信息送到哪里。

由于ISP的拨号服务器一般都有缺省的DNS,所以你可以不用设置DNS,如果你需要指定一台DNS,你一定要了解这台DNS的准确IP(比如福州的163用户的DNS为202.101.98.55)。DNS设置方法如下:在“控制面板”下打开“网络”里的“TCP/IP"的“属性”,在“DNS设置”栏目选择“启用DNS",并将DNS的IP地址添加即可。

IP192.168.X.X一般都是带有路由的IP,网关默认最后1位肯定是1,子网掩码 255.255.255.0简单说C类的IP,子网都可以这样设置

分类
其它综合

c#得到本机IP的函数

收集客户机信息时,需要得到客户机的IP,那么客户端就需要提供自己的本机IP:

using System;
using System.Net;
using System.Windows.Forms;

namespace Mynet
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            MessageBox.Show(GetMyIP());
        }
        
        /// <summary>
        /// 得到本机IP
        /// </summary>
        /// <returns></returns>
        public string GetMyIP()
        {
            try
            {
                string computername = Dns.GetHostName();
                IPHostEntry ipall = Dns.GetHostEntry(computername);
                for (int i = 0; i < ipall.AddressList.Length; i++)
                {
                    string theip = ipall.AddressList[i].ToString();
                    if (theip.LastIndexOf(".") != -1)
                    {
                        return theip;
                    }
                }
                return "未得到IP地址";
            }
            catch (Exception ErrMsg)
            {
                return ErrMsg.ToString();
            }
        }
    }
}

分类
其它综合

?2.6 DNS的客户端

2.6 DNS的客户端

在Linux中,DNS是由BIND(Berkeley Internet Name Domain,伯克莱网间域名)软件实现的。BIND是一个c/s系统。

1.客户端产生对IP与主机名解析的需求

DNS的客户端部分被叫作转换程序(resolver),负责产生域名查询信息,即向域名服务器获得域名解析/反解析服务,将这类信息发送给服务器端。转换程序的功能是内嵌一些程序,需要通过它调用解析库。转换程序在功能上是在标准的C语言库中执行。

2.客户端将无法自行解释的需求,通过53端口送给指定的DNS服务器

DNS客户端和服务器端在大多数情况中使用UDP包通信。UDP通信是迅速的,但包的大小不能比512bytes大。希望DNS查询或者服务器响应超过512bytes,包必须使用减慢的Tcp协议发送。

3.DNS客户端功能上内嵌一些程序

转换程序库使用两个配置文件:/etc/host.conf和/etc/resolv.conf。 host.conf被主要用于指出DNS和hosts文件的原始信息。/etc/resole.conf用于配置搜索行为,指出使用什么名称的服务器并且不管任何一个域被假设为非完全合格域名。

4.返回来的数据也许并不权威

如果域名服务器响应一个查询是有查询执行权威的,那么数据返回的是权威的,也有可能,询问可能从域名服务器的响应缓存而来,这种情况中响应是非权威的。DNS客户端可以或者不可以选择去访问非权威信息。

BIND版本9介绍一个选择的名称解析新方法使用lwresd,轻量级的解析域。这也不太广泛使用和在这儿不详述。

在Linux系统上,客户端一般先检索本地文件/etc/hosts,如果无法得到解析,则根据/etc/resolv.conf决定查询域名服务器。然后送出请求。这个顺序可以在/etc/nsswitch.conf文件设置中更改。

分类
其它综合

你的DNS如何查看

点击“开始”,选择其中的“运行”,输入“cmd”,回车,就会进入dos窗口,然后在里面输入“ipconfig /all”,回车,你就会看到 DNS Servers。

DNS在很多时候都能用上。因为有时候需要配置网络信息等问题。这里给大家的小方法,为了方便大家。

多多支持95年轻人,谢谢!

分类
其它综合

手把手教你在netty中使用TCP协议请求DNS服务器

简介

DNS的全称domain name system,既然是一个系统就有客户端和服务器之分。一般情况来说我们并不需要感知这个DNS客户端的存在,因为我们在浏览器访问某个域名的时候,浏览器作为客户端已经实现了这个工作。

但是有时候我们没有使用浏览器,比如在netty环境中,如何构建一个DNS请求呢?

DNS传输协议简介

在RFC的规范中,DNS传输协议有很多种,如下所示:

  • DNS-over-UDP/53简称”Do53″,是使用UDP进行DNS查询传输的协议。
  • DNS-over-TCP/53简称”Do53/TCP”,是使用TCP进行DNS查询传输的协议。
  • DNSCrypt,对DNS传输协议进行加密的方法。
  • DNS-over-TLS简称”DoT”,使用TLS进行DNS协议传输。
  • DNS-over-HTTPS简称”DoH”,使用HTTPS进行DNS协议传输。
  • DNS-over-TOR,使用VPN或者tunnels连接DNS。

这些协议都有对应的实现方式,我们先来看下Do53/TCP,也就是使用TCP进行DNS协议传输。

DNS的IP地址

先来考虑一下如何在netty中使用Do53/TCP协议,进行DNS查询。

因为DNS是客户端和服务器的模式,我们需要做的是构建一个DNS客户端,向已知的DNS服务器端进行查询。

已知的DNS服务器地址有哪些呢?

除了13个root DNS IP地址以外,还出现了很多免费的公共DNS服务器地址,比如我们常用的阿里DNS,同时提供了IPv4/IPv6 DNS和DoT/DoH服务。

IPv4: 
223.5.5.5

223.6.6.6

IPv6: 
2400:3200::1

2400:3200:baba::1

DoH 地址: 
https://dns.alidns.com/dns-query

DoT 地址: 
dns.alidns.com

再比如百度DNS,提供了一组IPv4和IPv6的地址:

IPv4: 
180.76.76.76

IPv6: 
2400:da00::6666

还有114DNS:

114.114.114.114
114.114.115.115

当然还有很多其他的公共免费DNS,这里我选择使用阿里的IPv4:223.5.5.5为例。

有了IP地址,我们还需要指定netty的连接端口号,这里默认的是53。

然后就是我们要查询的域名了,这里以www.flydean.com为例。

你也可以使用你系统中配置的DNS解析地址,以mac为例,可以通过nslookup进行查看本地的DNS地址:

nslookup  www.flydean.com
Server:     8.8.8.8
Address:    8.8.8.8#53

Non-authoritative answer:
www.flydean.com canonical name = flydean.com.
Name:   flydean.com
Address: 47.107.98.187

Do53/TCP在netty中的使用

有了DNS Server的IP地址,接下来我们需要做的就是搭建netty client,然后向DNS server端发送DNS查询消息。

搭建DNS netty client

因为我们进行的是TCP连接,所以可以借助于netty中的NIO操作来实现,也就是说我们需要使用NioEventLoopGroup和NioSocketChannel来搭建netty客户端:

 final String dnsServer = "223.5.5.5";
        final int dnsPort = 53;

EventLoopGroup group = new NioEventLoopGroup();
            Bootstrap b = new Bootstrap();
            b.group(group)
                    .channel(NioSocketChannel.class)
                    .handler(new Do53ChannelInitializer());

            final Channel ch = b.connect(dnsServer, dnsPort).sync().channel();

netty中的NIO Socket底层使用的就是TCP协议,所以我们只需要像常用的netty客户端服务一样构建客户端即可。

然后调用Bootstrap的connect方法连接到DNS服务器,就建立好了channel连接。

这里我们在handler中传入了自定义的Do53ChannelInitializer,我们知道handler的作用是对消息进行编码、解码和对消息进行读取。因为目前我们并不知道客户端查询的消息格式,所以Do53ChannelInitializer的实现我们在后面再进行详细讲解。

发送DNS查询消息

netty提供了DNS消息的封装,所有的DNS消息,包括查询和响应都是DnsMessage的子类。

每个DnsMessage都有一个唯一标记的ID,还有代表这个message类型的DnsOpCode。

对于DNS来说,opCode有下面这几种:

    public static final DnsOpCode QUERY = new DnsOpCode(0, "QUERY");
    public static final DnsOpCode IQUERY = new DnsOpCode(1, "IQUERY");
    public static final DnsOpCode STATUS = new DnsOpCode(2, "STATUS");
    public static final DnsOpCode NOTIFY = new DnsOpCode(4, "NOTIFY");
    public static final DnsOpCode UPDATE = new DnsOpCode(5, "UPDATE");

因为每个DnsMessage都可能包含4个sections,每个section都以DnsSection来表示。因为有4个section,所以在DnsSection定义了4个section类型:

    QUESTION,
    ANSWER,
    AUTHORITY,
    ADDITIONAL;

每个section里面又包含了多个DnsRecord, DnsRecord代表的就是Resource record,简称为RR,RR中有一个CLASS字段,下面是DnsRecord中CLASS字段的定义:

    int CLASS_IN = 1;
    int CLASS_CSNET = 2;
    int CLASS_CHAOS = 3;
    int CLASS_HESIOD = 4;
    int CLASS_NONE = 254;
    int CLASS_ANY = 255;

DnsMessage是DNS消息的统一表示,对于查询来说,netty中提供了一个专门的查询类叫做DefaultDnsQuery。

先来看下DefaultDnsQuery的定义和构造函数:

public class DefaultDnsQuery extends AbstractDnsMessage implements DnsQuery {

        public DefaultDnsQuery(int id) {
        super(id);
    }

    public DefaultDnsQuery(int id, DnsOpCode opCode) {
        super(id, opCode);
    }

DefaultDnsQuery的构造函数需要传入id和opCode。

我们可以这样定义一个DNS查询:

int randomID = (int) (System.currentTimeMillis() / 1000);
            DnsQuery query = new DefaultDnsQuery(randomID, DnsOpCode.QUERY)

既然是QEURY,那么还需要设置4个sections中的查询section:

query.setRecord(DnsSection.QUESTION, new DefaultDnsQuestion(queryDomain, DnsRecordType.A));

这里调用的是setRecord方法向section中插入RR数据。

这里的RR数据使用的是DefaultDnsQuestion。DefaultDnsQuestion的构造函数有两个,一个是要查询的domain name,这里就是”www.flydean.com”,另外一个参数是dns记录的类型。

dns记录的类型有很多种,在netty中有一个专门的类DnsRecordType表示,DnsRecordType中定义了很多个类型,如下所示:

public class DnsRecordType implements Comparable<DnsRecordType> {
    public static final DnsRecordType A = new DnsRecordType(1, "A");
    public static final DnsRecordType NS = new DnsRecordType(2, "NS");
    public static final DnsRecordType CNAME = new DnsRecordType(5, "CNAME");
    public static final DnsRecordType SOA = new DnsRecordType(6, "SOA");
    public static final DnsRecordType PTR = new DnsRecordType(12, "PTR");
    public static final DnsRecordType MX = new DnsRecordType(15, "MX");
    public static final DnsRecordType TXT = new DnsRecordType(16, "TXT");
    ...

因为类型比较多,我们挑选几个常用的进行讲解。

  • A类型,是address的缩写,用来指定主机名或者域名对应的ip地址.
  • NS类型,是name server的缩写,是域名服务器记录,用来指定域名由哪个DNS服务器来进行解析。
  • MX类型,是mail exchanger的缩写,是一个邮件交换记录,用来根据邮箱的后缀来定位邮件服务器。
  • CNAME类型,是canonical name的缩写,可以将多个名字映射到同一个主机.
  • TXT类型,用来表示主机或者域名的说明信息。

以上几个是我们经常会用到的dns record类型。

这里我们选择使用A,用来查询域名对应的主机IP地址。

构建好query之后,我们就可以使用netty client发送query指令到dns服务器了,具体的代码如下:

            DnsQuery query = new DefaultDnsQuery(randomID, DnsOpCode.QUERY)
                    .setRecord(DnsSection.QUESTION, new DefaultDnsQuestion(queryDomain, DnsRecordType.A));
            ch.writeAndFlush(query).sync();

DNS查询的消息处理

DNS的查询消息我们已经发送出去了,接下来就是对消息的处理和解析了。

还记得我们自定义的Do53ChannelInitializer吗?看一下它的实现:

class Do53ChannelInitializer extends ChannelInitializer<SocketChannel> {
    @Override
    protected void initChannel(SocketChannel ch) {
        ChannelPipeline p = ch.pipeline();
        p.addLast(new TcpDnsQueryEncoder())
                .addLast(new TcpDnsResponseDecoder())
                .addLast(new Do53ChannelInboundHandler());
    }
}

我们向pipline中添加了两个netty自带的编码解码器TcpDnsQueryEncoder和TcpDnsResponseDecoder,还有一个自定义用来做消息解析的Do53ChannelInboundHandler。

因为我们向channel中写入的是DnsQuery,所以需要一个encoder将DnsQuery编码为ByteBuf,这里使用的是netty提供的TcpDnsQueryEncoder:

public final class TcpDnsQueryEncoder extends MessageToByteEncoder<DnsQuery> 

TcpDnsQueryEncoder继承自MessageToByteEncoder,表示将DnsQuery编码为ByteBuf。

看下他的encode方法:

    protected void encode(ChannelHandlerContext ctx, DnsQuery msg, ByteBuf out) throws Exception {
        out.writerIndex(out.writerIndex() + 2);
        this.encoder.encode(msg, out);
        out.setShort(0, out.readableBytes() - 2);
    }

可以看到TcpDnsQueryEncoder在msg编码之前存储了msg的长度信息,所以是一个基于长度的对象编码器。

这里的encoder是一个DnsQueryEncoder对象。

看一下它的encoder方法:

    void encode(DnsQuery query, ByteBuf out) throws Exception {
        encodeHeader(query, out);
        this.encodeQuestions(query, out);
        this.encodeRecords(query, DnsSection.ADDITIONAL, out);
    }

DnsQueryEncoder会依次编码header、questions和records。

完成编码之后,我们还需要从DNS server的返回中decode出DnsResponse,这里使用的是netty自带的TcpDnsResponseDecoder:

public final class TcpDnsResponseDecoder extends LengthFieldBasedFrameDecoder

TcpDnsResponseDecoder继承自LengthFieldBasedFrameDecoder,表示数据是以字段长度来进行分割的,这和我们刚刚将的encoder的格式类似。

来看下他的decode方法:

    protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
        ByteBuf frame = (ByteBuf)super.decode(ctx, in);
        if (frame == null) {
            return null;
        } else {
            DnsResponse var4;
            try {
                var4 = this.responseDecoder.decode(ctx.channel().remoteAddress(), ctx.channel().localAddress(), frame.slice());
            } finally {
                frame.release();
            }
            return var4;
        }
    }

decode方法先调用LengthFieldBasedFrameDecoder的decode方法将要解码的内容提取出来,然后调用responseDecoder的decode方法,最终返回DnsResponse。

这里的responseDecoder是一个DnsResponseDecoder。具体decoder的细节这里就不过多阐述了。感兴趣的同学可以自行查阅代码文档。

最后,我们得到了DnsResponse对象。

接下来就是自定义的InboundHandler对消息进行解析了:

class Do53ChannelInboundHandler extends SimpleChannelInboundHandler<DefaultDnsResponse> 

在它的channelRead0方法中,我们调用了readMsg方法对消息进行处理:

    private static void readMsg(DefaultDnsResponse msg) {
        if (msg.count(DnsSection.QUESTION) > 0) {
            DnsQuestion question = msg.recordAt(DnsSection.QUESTION, 0);
            log.info("question is :{}",question);
        }
        int i = 0, count = msg.count(DnsSection.ANSWER);
        while (i < count) {
            DnsRecord record = msg.recordAt(DnsSection.ANSWER, i);
            //A记录用来指定主机名或者域名对应的IP地址
            if (record.type() == DnsRecordType.A) {
                DnsRawRecord raw = (DnsRawRecord) record;
                log.info("ip address is: {}",NetUtil.bytesToIpAddress(ByteBufUtil.getBytes(raw.content())));
            }
            i++;
        }
    }

DefaultDnsResponse是DnsResponse的一个实现,首先判断msg中的QUESTION个数是否大于零。

如果大于零,则打印出question的信息。

然后再解析出msg中的ANSWER并打印出来。

最后,我们可能得到这样的输出:

INFO  c.f.dnstcp.Do53ChannelInboundHandler - question is :DefaultDnsQuestion(www.flydean.com. IN A)
INFO  c.f.dnstcp.Do53ChannelInboundHandler - ip address is: 47.107.98.187

总结

以上就是使用netty创建DNS client进行TCP查询的讲解。

本文的代码,大家可以参考:

learn-netty4

更多内容请参考 http://www.flydean.com/54-netty-dns-over-tcp/

最通俗的解读,最深刻的干货,最简洁的教程,众多你不

欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!

分类
网络相关源码

易语言获取网络IP地址以及DNS

易语言获取网络IP地址以及DNS

.版本 2 .支持库 spec .子程序 __启动窗口_创建完毕 .局部变量 网页地址, 文本型 .局部变量 真实地址, 文本型 .局部变量 真实地址数据, 文本型 .局部变量 处理数据, 文本型 调试输出 (#输出) 网页地址 = 网页_访问S (“http://nstool.netease.com/”) 真实地址 = 文本_取出中间文本 (网页地址, #前面数据, #后面数据) 真实地址数据 = 网页_访问S (真实地址) 处理数据 = 文本_替换 (真实地址数据, , , , “<br>”, #换行符, “网易”, “”) 信息框 (处理数据, 0, , )