Permalink
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...
msantos committed Jun 25, 2010
1 parent a0c4a12 commit 68dd281384b57b9999b1fe8ed685381b88bc5347
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
@@ -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
@@ -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
@@ -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
@@ -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).
+

0 comments on commit 68dd281

Please sign in to comment.