Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Add a "discover" strategy

Add a discover strategy for choosing the source IP address of the DNS
query. Whenever snuff sees a new DNS packet, it will notify spoof of the
destination address. NOTE: the real source IP address of the client will
always be used.

The discovered IP addresses don't have an expiry yet, so as clients
leave the network, requests may timeout.

Fix the random selection of the source ip from the list. It would
never choose the final entry before.

Some uncommitted changes for the sniff -> snuff module rename.
  • Loading branch information...
commit 68dd281384b57b9999b1fe8ed685381b88bc5347 1 parent a0c4a12
@msantos authored
Showing with 51 additions and 15 deletions.
  1. +3 −3 src/dns.erl
  2. +4 −2 src/snuff.erl
  3. +4 −4 src/spood.erl
  4. +40 −6 src/spoof.erl
View
6 src/dns.erl
@@ -47,7 +47,7 @@
send(Port, Data) when is_integer(Port), is_binary(Data) ->
- gen_server:call(?MODULE, {sniff, Port, Data}).
+ gen_server:call(?MODULE, {snuff, Port, Data}).
start_link() ->
start_link(?DNS_PORT).
@@ -71,9 +71,9 @@ init([Port]) ->
% Sniffed reply
-handle_call({sniff, Port, Data}, _From, #state{s = Socket} = State) ->
+handle_call({snuff, Port, Data}, _From, #state{s = Socket} = State) ->
ok = gen_udp:send(Socket, {127,0,0,1}, Port, Data),
- error_logger:error_report([
+ error_logger:info_report([
{port, Port},
{decode, inet_dns:decode(Data)}
]),
View
6 src/snuff.erl
@@ -60,7 +60,8 @@ loop(Socket, NS) ->
filter(NS, [
#ether{},
#ipv4{
- saddr = NS
+ saddr = NS,
+ daddr = IP
},
#udp{
sport = 53,
@@ -69,7 +70,8 @@ filter(NS, [
},
Payload
]) when Len > 0, Len < 512 ->
- dns:send(Port, Payload);
+ dns:send(Port, Payload),
+ spoof:source(IP);
filter(_,_) ->
ok.
View
8 src/spood.erl
@@ -36,16 +36,16 @@
start() ->
- start("eth0",
+ start("ath0",
% Client
- {{16#00,16#15,16#af,16#59,16#08,16#26}, {list, [{192,168,213,110}, {192,168,213,94}]}},
+ {{16#00,16#15,16#af,16#59,16#08,16#26}, discover},
% Nameserver
{{16#00,16#16,16#b6,16#b5,16#3e,16#c6}, {192,168,213,1}}
).
start(Dev, Client, Nameserver) ->
- dns:start_link(),
spoof:start_link(Dev, Client, Nameserver),
- spawn(sniff, service, [Dev]).
+ dns:start_link(),
+ spawn(snuff, service, [Dev]).
View
46 src/spoof.erl
@@ -34,7 +34,7 @@
-include("epcap_net.hrl").
-define(SERVER, ?MODULE).
--export([start_link/3, send/2]).
+-export([start_link/3, send/2, source/1]).
-export([dns_query/3]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
@@ -51,6 +51,9 @@
send(Port, Data) when is_integer(Port), is_binary(Data) ->
gen_server:call(?MODULE, {dns_query, Port, Data}).
+source(IP) when is_tuple(IP) ->
+ gen_server:call(?MODULE, {sourceip, IP}).
+
start_link(Dev, Client, NS) ->
gen_server:start_link({local, ?SERVER}, ?MODULE, [Dev, Client, NS], []).
@@ -59,11 +62,19 @@ init([Dev, {ClientMAC, Strategy}, {NSMAC, NSIP}]) ->
crypto:start(),
{ok, Socket} = packet:socket(),
Ifindex = packet:ifindex(Socket, Dev),
+
+ Source = case Strategy of
+ discover ->
+ {SA1,SA2,SA3,SA4} = packet:ipv4address(Socket, Dev),
+ {learn, [{SA1,SA2,SA3,SA4}]};
+ N -> N
+ end,
+
{ok, #state{
s = Socket,
i = Ifindex,
shost = ClientMAC,
- saddr = Strategy,
+ saddr = Source,
dhost = NSMAC,
daddr = NSIP
@@ -78,6 +89,18 @@ handle_call({dns_query, Port, Data}, _From, #state{s = Socket, i = Ifindex} = St
{packet, inet_dns:decode(Data)}
]),
{reply, ok, State};
+% Add a new source IP address
+handle_call({sourceip, IP}, _From, #state{saddr = {learn, IPList}} = State) ->
+ N = case lists:member(IP, IPList) of
+ true -> IPList;
+ false -> [IP|IPList]
+ end,
+ {reply, ok, State#state{
+ saddr = {learn, N}
+ }};
+handle_call({sourceip, _IP}, _From, State) ->
+ {reply, ok, State};
+
handle_call(_Request, _From, State) ->
{reply, ok, State}.
@@ -164,15 +187,26 @@ dns_query(SourcePort, Data, #state{
Data/binary
>>.
+%%
+%% Strategies for choosing a source IP address
+%%
+
+% Single source IP address
strategy(Address) when is_list(Address) ->
{ok, SA} = inet_parse:address(Address),
SA;
strategy({_,_,_,_} = SA) ->
SA;
-strategy({list, [IPList]}) when is_tuple(IPList) ->
- error_logger:info_report([{iplist, IPList}]),
- IPList;
+
+% A manually specified list
strategy({list, IPList}) when is_list(IPList) ->
error_logger:info_report([{shuffle, IPList}]),
- lists:nth(crypto:rand_uniform(1, length(IPList)), IPList).
+ lists:nth(crypto:rand_uniform(1, length(IPList)+1), IPList);
+
+% Learn what's on the network
+% XXX should add a timeout to force removal of stale entries
+strategy({learn , IPList}) when is_list(IPList) ->
+ error_logger:info_report([{discovered, IPList}]),
+ lists:nth(crypto:rand_uniform(1, length(IPList)+1), IPList).
+
Please sign in to comment.
Something went wrong with that request. Please try again.