内部解析ip地址
This commit is contained in:
parent
7c3474afab
commit
d33fe7e540
@ -74,30 +74,57 @@ handle_call(_Request, _From, State = #state{}) ->
|
|||||||
{stop, Reason :: term(), NewState :: #state{}}).
|
{stop, Reason :: term(), NewState :: #state{}}).
|
||||||
handle_cast(handle, State = #state{socket = Sock, src_ip = SrcIp, src_port = SrcPort, packet = Packet}) ->
|
handle_cast(handle, State = #state{socket = Sock, src_ip = SrcIp, src_port = SrcPort, packet = Packet}) ->
|
||||||
case dns:decode_message(Packet) of
|
case dns:decode_message(Packet) of
|
||||||
QueryMsg = #dns_message{qc = 1, questions = [Question|_]} ->
|
QueryMsg = #dns_message{qc = 1, questions = [Question = #dns_query{name = QName, type = QType, class = QClass}|_]} ->
|
||||||
case dns_cache:lookup(Question) of
|
%% 查找是否是内置的域名
|
||||||
{hit, Cache} ->
|
case search_inbuilt_domain(QName) of
|
||||||
lager:debug("[dns_handler] question: ~p, hit cache: ~p", [Question, Cache]),
|
{ok, Ip} ->
|
||||||
RespMsg = build_response(QueryMsg, Cache),
|
Answer = #dns_rr {
|
||||||
|
name = QName,
|
||||||
|
type = QType,
|
||||||
|
class = QClass,
|
||||||
|
ttl = 300,
|
||||||
|
data = #dns_rrdata_a {
|
||||||
|
ip = Ip
|
||||||
|
}
|
||||||
|
},
|
||||||
|
RespMsg = QueryMsg#dns_message{
|
||||||
|
qr = true,
|
||||||
|
ra = true,
|
||||||
|
anc = 1,
|
||||||
|
auc = 0,
|
||||||
|
adc = 0,
|
||||||
|
answers = [Answer],
|
||||||
|
authority = [],
|
||||||
|
additional = []
|
||||||
|
},
|
||||||
gen_udp:send(Sock, SrcIp, SrcPort, dns:encode_message(RespMsg)),
|
gen_udp:send(Sock, SrcIp, SrcPort, dns:encode_message(RespMsg)),
|
||||||
|
|
||||||
{stop, normal, State};
|
{stop, normal, State};
|
||||||
miss ->
|
error ->
|
||||||
lager:debug("[dns_handler] cache is miss"),
|
case dns_cache:lookup(Question) of
|
||||||
Ref = make_ref(),
|
{hit, Cache} ->
|
||||||
forward_to_upstream(Ref, Packet, QueryMsg),
|
lager:debug("[dns_handler] question: ~p, hit cache answers: ~p", [Question, Cache#dns_cache.answers]),
|
||||||
receive
|
RespMsg = build_response(QueryMsg, Cache),
|
||||||
{dns_resolver_reply, Ref, Resp} ->
|
gen_udp:send(Sock, SrcIp, SrcPort, dns:encode_message(RespMsg)),
|
||||||
case dns:decode_message(Resp) of
|
{stop, normal, State};
|
||||||
RespMsg = #dns_message{answers = Answers} ->
|
miss ->
|
||||||
lager:debug("[dns_handler] get a response answers: ~p", [Answers]),
|
lager:debug("[dns_handler] cache is miss"),
|
||||||
dns_cache:insert(Question, RespMsg),
|
Ref = make_ref(),
|
||||||
gen_udp:send(Sock, SrcIp, SrcPort, Resp);
|
forward_to_upstream(Ref, Packet, QueryMsg),
|
||||||
Other ->
|
receive
|
||||||
lager:debug("[dns_handler] parse reply get error: ~p", [Other])
|
{dns_resolver_reply, Ref, Resp} ->
|
||||||
end,
|
case dns:decode_message(Resp) of
|
||||||
{stop, normal, State}
|
RespMsg = #dns_message{answers = Answers} ->
|
||||||
after 5000 ->
|
lager:debug("[dns_handler] get a response answers: ~p", [Answers]),
|
||||||
{stop, normal, State}
|
dns_cache:insert(Question, RespMsg),
|
||||||
|
gen_udp:send(Sock, SrcIp, SrcPort, Resp);
|
||||||
|
Other ->
|
||||||
|
lager:debug("[dns_handler] parse reply get error: ~p", [Other])
|
||||||
|
end,
|
||||||
|
{stop, normal, State}
|
||||||
|
after 5000 ->
|
||||||
|
{stop, normal, State}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
Other ->
|
Other ->
|
||||||
@ -167,4 +194,13 @@ build_response(QueryMsg, #dns_cache{expire_at = ExpireAt, answers = Answers, aut
|
|||||||
adjust_ttl(RR = #dns_rr{}, RemainingTTL) ->
|
adjust_ttl(RR = #dns_rr{}, RemainingTTL) ->
|
||||||
RR#dns_rr{ttl = max(0, RemainingTTL)};
|
RR#dns_rr{ttl = max(0, RemainingTTL)};
|
||||||
adjust_ttl(RR, _RemainingTTL) ->
|
adjust_ttl(RR, _RemainingTTL) ->
|
||||||
RR.
|
RR.
|
||||||
|
|
||||||
|
search_inbuilt_domain(QName) when is_binary(QName) ->
|
||||||
|
Suffix = <<".iot.cn">>,
|
||||||
|
case dns_utils:ends_with(QName, Suffix) of
|
||||||
|
true ->
|
||||||
|
{ok, {192, 168, 1, 101}};
|
||||||
|
false ->
|
||||||
|
error
|
||||||
|
end.
|
||||||
28
apps/dns_proxy/src/dns_utils.erl
Normal file
28
apps/dns_proxy/src/dns_utils.erl
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
%%%-------------------------------------------------------------------
|
||||||
|
%%% @author anlicheng
|
||||||
|
%%% @copyright (C) 2025, <COMPANY>
|
||||||
|
%%% @doc
|
||||||
|
%%%
|
||||||
|
%%% @end
|
||||||
|
%%% Created : 05. 12月 2025 18:06
|
||||||
|
%%%-------------------------------------------------------------------
|
||||||
|
-module(dns_utils).
|
||||||
|
-author("anlicheng").
|
||||||
|
|
||||||
|
%% API
|
||||||
|
-export([ends_with/2, parse_address/1]).
|
||||||
|
|
||||||
|
-spec ends_with(Bin :: binary(), Suffix :: binary()) -> boolean().
|
||||||
|
ends_with(Bin, Suffix) when is_binary(Bin), is_binary(Suffix) ->
|
||||||
|
case binary:match(Bin, Suffix) of
|
||||||
|
{Pos, Len} ->
|
||||||
|
Pos + Len =:= byte_size(Bin);
|
||||||
|
nomatch ->
|
||||||
|
false
|
||||||
|
end.
|
||||||
|
|
||||||
|
-spec parse_address(Ip :: any()) -> {ok, IpAddress :: inet:ip4_address()} | {error, Reason :: any()}.
|
||||||
|
parse_address(Ip = {Ip0, Ip1, Ip2, Ip3}) when is_integer(Ip0), is_integer(Ip1), is_integer(Ip2), is_integer(Ip3) ->
|
||||||
|
{ok, Ip};
|
||||||
|
parse_address(Bin) when is_binary(Bin) ->
|
||||||
|
inet:parse_address(binary_to_list(Bin)).
|
||||||
Loading…
x
Reference in New Issue
Block a user