Ok, I have done an initial implementation (just country geolocation for now). It is available at <a href="https://github.com/owlsec/suricata/tree/geoip">https://github.com/owlsec/suricata/tree/geoip</a><br><br>When checking a packet, I take into account the flow source and destination IPs for the match-on condition, if a flow exists. However in my tests I have seen it is not working well... a geoip:src,US; rule will be triggered as well when talking HTTP to <a href="http://google.com">google.com</a> from a non US source IP address.<br>
<br>I am not sure about the reason of this behavior, so perhaps somebody could let me know what is wrong here.<br><br><a href="https://github.com/owlsec/suricata/blob/geoip/src/detect-geoip.c">https://github.com/owlsec/suricata/blob/geoip/src/detect-geoip.c</a><br>
<br>The relevant function is this one:<br><br><pre><div class="line" id="LC165"><span class="k">static</span> <span class="kt">int</span> <span class="nf">DetectGeoipMatch</span><span class="p">(</span><span class="n">ThreadVars</span> <span class="o">*</span><span class="n">t</span><span class="p">,</span> <span class="n">DetectEngineThreadCtx</span> <span class="o">*</span><span class="n">det_ctx</span><span class="p">,</span></div>
<div class="line" id="LC166">                             <span class="n">Packet</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="n">Signature</span> <span class="o">*</span><span class="n">s</span><span class="p">,</span> <span class="n">SigMatch</span> <span class="o">*</span><span class="n">m</span><span class="p">)</span></div>
<div class="line" id="LC167"><span class="p">{</span></div><div class="line" id="LC168">    <span class="n">DetectGeoipData</span> <span class="o">*</span><span class="n">geoipdata</span> <span class="o">=</span> <span class="p">(</span><span class="n">DetectGeoipData</span> <span class="o">*</span><span class="p">)</span><span class="n">m</span><span class="o">-></span><span class="n">ctx</span><span class="p">;</span></div>
<div class="line" id="LC169">    <span class="kt">int</span> <span class="n">match</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span></div><div class="line" id="LC170">    <span class="kt">int</span> <span class="n">matches</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span></div>
<div class="line" id="LC171">    <span class="kt">uint32_t</span> <span class="n">ip</span><span class="p">;</span></div><div class="line" id="LC172"><br></div><div class="line" id="LC173">    <span class="k">if</span> <span class="p">(</span><span class="n">PKT_IS_IPV4</span><span class="p">(</span><span class="n">p</span><span class="p">))</span></div>
<div class="line" id="LC174">    <span class="p">{</span></div><div class="line" id="LC175">        <span class="k">if</span> <span class="p">(</span><span class="n">geoipdata</span><span class="o">-></span><span class="n">flags</span> <span class="o">&</span> <span class="n">GEOIP_MATCH_SRC_FLAG</span> <span class="o">||</span> <span class="n">geoipdata</span><span class="o">-></span><span class="n">flags</span> <span class="o">&</span> <span class="n">GEOIP_MATCH_BOTH_FLAG</span><span class="p">)</span></div>
<div class="line" id="LC176">        <span class="p">{</span>        </div><div class="line" id="LC177">            <span class="cm">/* if there is a flow get SRC IP of the flow, not packet */</span>            </div><div class="line" id="LC178">
            <span class="k">if</span> <span class="p">(</span><span class="n">p</span><span class="o">-></span><span class="n">flowflags</span> <span class="o">&</span> <span class="n">FLOW_PKT_TOCLIENT</span><span class="p">)</span></div>
<div class="line" id="LC179">                <span class="n">ip</span> <span class="o">=</span> <span class="n">GET_IPV4_DST_ADDR_U32</span><span class="p">(</span><span class="n">p</span><span class="p">);</span> <span class="cm">/* the dst (from server to client) is our src */</span></div>
<div class="line" id="LC180">            <span class="k">else</span> </div><div class="line" id="LC181">                <span class="n">ip</span> <span class="o">=</span> <span class="n">GET_IPV4_SRC_ADDR_U32</span><span class="p">(</span><span class="n">p</span><span class="p">);</span></div>
<div class="line" id="LC182">            <span class="n">match</span> <span class="o">=</span> <span class="n">CheckGeoMatchIPv4</span><span class="p">(</span><span class="n">geoipdata</span><span class="p">,</span> <span class="n">ip</span><span class="p">);</span></div>
<div class="line" id="LC183">            <span class="k">if</span> <span class="p">(</span><span class="n">match</span> <span class="o">&&</span> <span class="n">geoipdata</span><span class="o">-></span><span class="n">flags</span> <span class="o">&</span> <span class="n">GEOIP_MATCH_BOTH_FLAG</span><span class="p">)</span></div>
<div class="line" id="LC184">                <span class="n">matches</span><span class="o">++</span><span class="p">;</span></div><div class="line" id="LC185">            <span class="k">else</span>                    </div>
<div class="line" id="LC186">                <span class="k">return</span> <span class="mi">1</span><span class="p">;</span></div><div class="line" id="LC187">        <span class="p">}</span></div><div class="line" id="LC188">
        <span class="k">if</span> <span class="p">(</span><span class="n">geoipdata</span><span class="o">-></span><span class="n">flags</span> <span class="o">&</span> <span class="n">GEOIP_MATCH_DST_FLAG</span> <span class="o">||</span> <span class="n">geoipdata</span><span class="o">-></span><span class="n">flags</span> <span class="o">&</span> <span class="n">GEOIP_MATCH_BOTH_FLAG</span><span class="p">)</span></div>
<div class="line" id="LC189">        <span class="p">{</span>     </div><div class="line" id="LC190">            <span class="cm">/* if there is a flow get DST IP of the flow, not packet */</span>            </div><div class="line" id="LC191">
            <span class="k">if</span> <span class="p">(</span><span class="n">p</span><span class="o">-></span><span class="n">flowflags</span> <span class="o">&</span> <span class="n">FLOW_PKT_TOCLIENT</span><span class="p">)</span></div>
<div class="line" id="LC192">                <span class="n">ip</span> <span class="o">=</span> <span class="n">GET_IPV4_SRC_ADDR_U32</span><span class="p">(</span><span class="n">p</span><span class="p">);</span> <span class="cm">/* the src (from server to client) is our dst */</span></div>
<div class="line" id="LC193">            <span class="k">else</span> </div><div class="line" id="LC194">                <span class="n">ip</span> <span class="o">=</span> <span class="n">GET_IPV4_DST_ADDR_U32</span><span class="p">(</span><span class="n">p</span><span class="p">);</span></div>
<div class="line" id="LC195">            <span class="n">match</span> <span class="o">=</span> <span class="n">CheckGeoMatchIPv4</span><span class="p">(</span><span class="n">geoipdata</span><span class="p">,</span> <span class="n">ip</span><span class="p">);</span></div>
<div class="line" id="LC196">            <span class="k">if</span> <span class="p">(</span><span class="n">match</span> <span class="o">&&</span> <span class="n">geoipdata</span><span class="o">-></span><span class="n">flags</span> <span class="o">&</span> <span class="n">GEOIP_MATCH_BOTH_FLAG</span><span class="p">)</span></div>
<div class="line" id="LC197">                <span class="n">matches</span><span class="o">++</span><span class="p">;</span></div><div class="line" id="LC198">            <span class="k">else</span>                    </div>
<div class="line" id="LC199">                <span class="k">return</span> <span class="mi">1</span><span class="p">;</span></div><div class="line" id="LC200">        <span class="p">}</span></div><div class="line" id="LC201">
<br></div><div class="line" id="LC202">        <span class="cm">/* if matches == 2 is because match-on is "both" */</span></div><div class="line" id="LC203">        <span class="k">if</span> <span class="p">(</span><span class="n">matches</span> <span class="o">==</span> <span class="mi">2</span><span class="p">)</span> </div>
<div class="line" id="LC204">            <span class="k">return</span> <span class="mi">1</span><span class="p">;</span></div><div class="line" id="LC205">    <span class="p">}</span></div><div class="line" id="LC206">    </div>
<div class="line" id="LC207">    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span></div><div class="line" id="LC208"><span class="p">}<br></span></div></pre><br><br><div class="gmail_quote">On Fri, Oct 12, 2012 at 11:35 AM, I. Sanchez <span dir="ltr"><<a href="mailto:sanchezmartin.ji@gmail.com" target="_blank">sanchezmartin.ji@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Yes, I forgot to mention it. Negation will be supported.<div class="HOEnZb"><div class="h5"><br><br><div class="gmail_quote">
On Fri, Oct 12, 2012 at 10:03 AM, Peter Manev <span dir="ltr"><<a href="mailto:petermanev@gmail.com" target="_blank">petermanev@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Excellent - thank you.<br>comments bellow ...<br><br><div class="gmail_quote"><div>On Thu, Oct 11, 2012 at 10:07 PM, I. Sanchez <span dir="ltr"><<a href="mailto:sanchezmartin.ji@gmail.com" target="_blank">sanchezmartin.ji@gmail.com</a>></span> wrote:<br>


<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Good idea, I will implement multiple conditions(countries) in the same rule. Let's use the <match-on><condition>+ syntax where match-on can be src, dst, both or any.<div>


<br><br><div style="margin-left:40px">alert http any any -> any any (msg:"GEOIP: IP located in US/Germany/Canada/France";<b> geoip:src,US,DE,CA,FR</b>; sid:3450002; rev:1;)<br>
</div><br></div>I can also support geoip:US; by assuming geoip:any,US; , for simplicity. <br></blockquote></div><div><br>I agree with the assumption here - i think it is good to assume so. <br>I was thinking further on the matter and I am not sure if i am starting to sound annoying - but wouldn't it be nice if we can also negate geoip? :<br>


alert http any any -> any any (msg:"GEOIP: IP destination  <b>NOT</b> located in US/Canada";<b> </b>geoip:<b>dst,!</b>US,CA; sid:3450002; rev:1;)<br><br><br></div><div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">


<br>Regarding the city support, indeed the MaxMind DBs in their free versions support cities in addition to countries although the accuracy drops from 99.5% (for countries) to 78% in US (for cities), and I guess much less accuracy in other countries. <br>



<br>In the commercial DBs, they apparently support regions, organizations... <a href="http://www.maxmind.com/en/geolocation_landing" target="_blank">http://www.maxmind.com/en/geolocation_landing</a><br><br>For now I will just implement support for countries, but we should take this into account for the keyword syntax. I see some options:<br>



<ul><li>Autodetect city vs country. I could detect whether the condition is a known country code, and assume city otherwise. However this will not work for regions, organizations...</li><li>Allow -for future versions- the check type as an optional param of the <match-on> condition. ie: geoip:src,city,Madrid;</li>


</ul></blockquote></div><div><br>this would be awesome in my opinion. <br></div><div><div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><ul>
</ul>Regards,<div><div><br><br><br><br><br><div class="gmail_quote">On Thu, Oct 11, 2012 at 9:02 PM, Peter Manev <span dir="ltr"><<a href="mailto:petermanev@gmail.com" target="_blank">petermanev@gmail.com</a>></span> wrote:<br>



<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi,<br><br>I think i love that new geoip keyword - thank you for the efforts !<br><br>A couple of suggestions/requests if I may:<br>



<br>1.I agree/like the proposal - but I wonder if it would be possible to include multiples(maybe up to a certain number [32 or something] ) of countries - like:<br>
alert http any any -> any any (msg:"GEOIP: IP located in US/Germany/Canada/France";<b> geoip:src,US,DE,CA,FR</b>; sid:3450002; rev:1;)<br><br>2. As there is - <b>src, dst, both</b> - i think it would be nice if there is also "<b>any</b>" - <br>




alert http any any -> any any (msg:"GEOIP: some traffic to/from the Cayman Islands";<b> geoip:any,KY</b>; sid:3450005; rev:1;)<br>any - meaning either source or destination.<br><br>thanks a bunch!<div>
<div><br><br><div class="gmail_quote">
On Thu, Oct 11, 2012 at 6:42 PM, Victor Julien <span dir="ltr"><<a href="mailto:victor@inliniac.net" target="_blank">victor@inliniac.net</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">




<div>On 10/11/2012 06:16 PM, I. Sanchez wrote:<br>
> Hi,<br>
><br>
> I am implementing support for IP address country geolocation in<br>
> Suricata, and I wanted to ask your opinion about the syntax to be used<br>
> for the geoip keyword options.<br>
><br>
> <a href="https://redmine.openinfosecfoundation.org/issues/559" target="_blank">https://redmine.openinfosecfoundation.org/issues/559</a><br>
><br>
> The keyword options would be:<br>
><br>
</div>>   * Country code. ie: US<br>
>   * Match condition: match on source IP, match on destination IP, or<br>
<div>>     match on both.<br>
><br>
> What do you think would be the best syntax for this?<br>
><br>
> Some possibilities:<br>
><br>
</div>>   * geoip:<src|dst|both>,<countrycode>;<br>
>       o alert http any any -> any any (msg:"GEOIP: IP located in<br>
>         US";*geoip:src,US*;sid:3450002;rev:1;)<br>
>   * geoip:<countrycode>,<src|dst|both>;<br>
>       o alert http any any -> any any (msg:"GEOIP: IP located in<br>
>         US";*geoip:US,src*;sid:3450002;rev:1;)<br>
<br>
Thanks for picking this up!<br>
<br>
Doesn't the geoip also allow for other types of data, such as city? I'm<br>
sure that if we have this in Suricata ppl will be interested in buying<br>
the more detailed databases as well.<br>
<span><font color="#888888"><br>
--<br>
---------------------------------------------<br>
Victor Julien<br>
<a href="http://www.inliniac.net/" target="_blank">http://www.inliniac.net/</a><br>
PGP: <a href="http://www.inliniac.net/victorjulien.asc" target="_blank">http://www.inliniac.net/victorjulien.asc</a><br>
---------------------------------------------<br>
</font></span><div><div><br>
_______________________________________________<br>
Oisf-devel mailing list<br>
<a href="mailto:Oisf-devel@openinfosecfoundation.org" target="_blank">Oisf-devel@openinfosecfoundation.org</a><br>
<a href="https://lists.openinfosecfoundation.org/mailman/listinfo/oisf-devel" target="_blank">https://lists.openinfosecfoundation.org/mailman/listinfo/oisf-devel</a><br>
</div></div></blockquote></div><br><br clear="all"><br></div></div><span><font color="#888888">-- <br><div>Regards,</div>
<div>Peter Manev</div><br>
</font></span><br>_______________________________________________<br>
Oisf-devel mailing list<br>
<a href="mailto:Oisf-devel@openinfosecfoundation.org" target="_blank">Oisf-devel@openinfosecfoundation.org</a><br>
<a href="https://lists.openinfosecfoundation.org/mailman/listinfo/oisf-devel" target="_blank">https://lists.openinfosecfoundation.org/mailman/listinfo/oisf-devel</a><br></blockquote></div><br>
</div></div></blockquote></div></div></div><span><font color="#888888"><br><br clear="all"><br>-- <br><div>Regards,</div>
<div>Peter Manev</div><br>
</font></span></blockquote></div><br>
</div></div></blockquote></div><br>