Wednesday, November 30, 2016

Multicast snooping and bridges

If you are running two containers (LXC, Docker, whatever) on the same machine, and you use IPv6 there, then you might notice, that these machines do not see each other.

You do know about neighbor discovery in IPv6, right? No ARP and all the bells and whistles.

Remember, no IGMP here, just MLD (Multicast Listener Discovery). These two a pretty the same, but there are some issues with MLD in Linux.

Some say that you should disable multicast_snooping on the bridge. It can be done via sysfs:

echo -n 0 > /sys/class/net/%BRIDGE_NAME%/bridge/multicast_snooping

Well, that will work. But you should understand, that now all your network behind that bridge will be flooded by multicast packets. Okay for small installations.

Instead, enable multicast querier:

echo -n 1 /sys/class/net/%BRIDGE_NAME%/bridge/multicast_querier

Querier will update snooping filters by sending broadcast queries.

After that you will need to remove and add again an IPv6 address in your container, so MLD query would be resent.

I would strongly suggest you not to disable multicast snooping. That might be a security flaw and flood your network in a second.

German attack

Have a look at awesome write up about vulnerable DSL routers in Germany: https://isc.sans.edu/forums/diary/Port+7547+SOAP+Remote+Code+Execution+Attack+Against+DSL+Modems/21759/

Looks like another round for Mirai.

Be aware, port 7547 has nothing to do with TR-069, but some kind of a lame webserver.

P.S. If the bad guys were a bit more discrete and not scanning all over the place, that attack might have had a huge impact.

Thursday, November 24, 2016

IPv6 in linux cluster

Imagine quite a usual scheme - bunch of servers in a cluster for web.
It may be two servers with failover IP (keepalived, heartbeat) or a cluster (corosync).


In a scheme like that, to avoid scripting, you probably set the following sysctl value:

net.ipv4.ip_nonlocal_bind=1

Awesomely simple and handy, your favorite web server is able to bind to virtual address, even if it is not on the server now. Cool, right?  

Rotten apple


Beware debian users and all others whose kernel version is <4.3. And I know, there are many of you  out there. Beware, 'cause this trick won't work on IPv6. The same sysctl option for IPv6 (net.ipv6.ip_nonlocal_bind) was introduced just in kernel 4.3.

Here is the commit to Documentation/networking/ip-sysctl.txt: https://github.com/torvalds/linux/commit/35a256fee52c7c207796302681fa95189c85b408 (July 8, 2015)

Interesting thing, almost the same commit was rejected in 2011: http://patchwork.ozlabs.org/patch/130748/

What to do

  1. Upgrade. Version 4.3 was introduced more then a year ago. Debian pain.
  2. Use balancers, move all cluster-fancy-party to one level up in your infrastructure. Keepalived + IPVS is a good choice. It does not bind. Well it does, but you don't need to bind to an absent IP.
  3. Scripting (brrr).

Wednesday, November 23, 2016

python "in" operator

Hello comrade,

recently I had smth like this in my code:

>>> string = 'hdfjghweurj'
>>> sub = 'ghw'
>>> sub in string
True

I have asked myself - how "in" is working? This knowledge might be useless, but knowing how to get this info might help you understand how language works and what algorithms does it use. All examples below are for python 2, basically in python 3 it is pretty the same, but some methods differ.

Here are the steps:

dis

First, lets disassemble.

>>> import dis
>>> def foo():
...     'aaa' in []
... 
>>> dis.dis(foo)
  2           0 LOAD_CONST               1 ('aaa')
              3 LOAD_CONST               2 (())
              6 COMPARE_OP               6 (in)
              9 POP_TOP             
             10 LOAD_CONST               0 (None)
             13 RETURN_VALUE        

We now know, that it is a COMPARE_OP. Let's dive into sources.

ceval.c

Let's have a look at ceval.c loop and find our COMPARE_OP:

        
        TARGET(COMPARE_OP) {
            ...
            else {
              slow_compare:
                x = cmp_outcome(oparg, v, w);
            }
            ...
        }


Looks like all logic is in cmp_outcome. It can be found in the same file, what we interested in is:

      case PyCmp_IN:
        res = PySequence_Contains(w, v);
        if (res < 0)
            return NULL;
        break;

PySequence_Contains is interesting for us.

Objects

Searching the repo we will land at Objects/abstract.c:

int
PySequence_Contains(PyObject *seq, PyObject *ob)
{
    Py_ssize_t result;
    if (PyType_HasFeature(seq->ob_type, Py_TPFLAGS_HAVE_SEQUENCE_IN)) {
        PySequenceMethods *sqm = seq->ob_type->tp_as_sequence;
        if (sqm != NULL && sqm->sq_contains != NULL)
            return (*sqm->sq_contains)(seq, ob);
    }
    result = _PySequence_IterSearch(seq, ob, PY_ITERSEARCH_CONTAINS);
    return Py_SAFE_DOWNCAST(result, Py_ssize_t, int);
}
PySequenceMethods is our guy. As we are talking about strings, we should look for them. This leads us to Objects/stringobject.c:

Objects/stringobject.c:    (objobjproc)string_contains /*sq_contains*/

string_contains could be found in the same file:

...
return stringlib_contains_obj(str_obj, sub_obj);

Now,  of course, we must go to Objects/stringlib/find.h. Not looking through the source, at the header you might see, that it uses fastsearch.h:

#ifndef STRINGLIB_FASTSEARCH_H
#error must include "stringlib/fastsearch.h" before including this module
#endif

Lets have a look at it. The first comment states:

/* fast search/count implementation, based on a mix between boyer-
   moore and horspool, with a few more bells and whistles on the top.
   for some more background, see: http://effbot.org/zone/stringlib.htm */


That is how you know, that "in" operator in Python, when used for strings, uses Boyer-Moore-Horspool algorithm, with some "bells and whistles". 


spron.in paranoid edition

Hello comrade,

on the 26th of October I wrote a post on HSTS preload. Also on that date I have requested to add spron.in to preload list. And finally:


Took almost a month :)