Igalia / pflua

Packet filtering in Lua
Other
313 stars 39 forks source link

Pflua doesn't allow libpcap-style keyword elision #157

Open kbara opened 9 years ago

kbara commented 9 years ago

The following are libpcap pflang expressions which pflua doesn't allow, and their pflua equivalents. The root issue is that libpcap-pflang automatically uses the previous keyword if it's elided.

port 3 and 4 (this means port 3 and port 4) src host 127.0.0.1 or 127.0.0.2 (means src host 127.0.0.1 or src host 127.0.0.1).

This is trickier than it appears, due to examples like port 3 and 4 is port 3 and port 4, while port 3 and 4 == 4 is also valid in both pflangs, and means the same thing in both - it does not mean "port 3 and port 4 == 4", which is invalid.

Workarounds: a) Use pflua's bpf front-end (which also compiles to Lua), rather than the pflua's pure-lua pipeline. b) Rewrite pflang expressions to not rely on keyword elision.

Other impact: at least one error message is quite verbose to account for this possibility: see https://github.com/Igalia/pflua/issues/153 .

wingo commented 9 years ago

It's particularly hard to parse with named hosts: "host foo or bar". Is bar a hostname that should be looked up via DNS? Or is it a keyword? :) Likewise for "port ftp or http", is ftp a port or a server? pflang has strange grammar :) Consciously excluding this bit of the grammar might be an OK option, though this feature was lauded by the libpcap creator in some paper I saw last year :/

kbara commented 9 years ago

In the host foo or bar case, does an approach of treating it as a keyword iff it's a known keyword literal work, or is there another subtlety? In the port ftp or http case, how could ftp be a server? Pflang has a very strange grammar; this works: port 3 or src 4! And it doesn't compile to the same thing as port 3 or src port 4 does either.

dpino commented 9 years ago

@kbara I think what happens with those expressions is the following:

port 3 or src 4 is not actually port 3 or src port 4, but port 3 or src host 4. Somewhere in the BPF-syntax doc (http://biot.com/capstats/bpf.html) says that if a keyword is omitted the last keyword is used, but src 4 itself is a valid expression equivalent to src host 4, so I believe that takes precedence.

kbara commented 9 years ago

Good point!

takikawa commented 7 years ago

Sorry for bumping this old issue, but I wanted to note for completeness sake that there's also another form of elision in which the end can be omitted (like the net 192.168.1.1 in the following):

$ sudo tcpdump -d 'ip src and dst net 192.168.1.1'
(000) ldh      [12]
(001) jeq      #0x800           jt 2    jf 7
(002) ld       [26]
(003) jeq      #0xc0a80101      jt 4    jf 7
(004) ld       [30]
(005) jeq      #0xc0a80101      jt 6    jf 7
(006) ret      #262144
(007) ret      #0
$ ../env pflua-compile 'ip src and dst net 192.168.1.1'
luajit: /home/asumu/igalia/pflua/src/pf/utils.lua:162: Not an IPV4 address
stack traceback:
    [C]: in function 'assert'
    /home/asumu/igalia/pflua/src/pf/utils.lua:162: in function 'ipv4_to_int'
    /home/asumu/igalia/pflua/src/pf/expand.lua:388: in function 'expander'
    /home/asumu/igalia/pflua/src/pf/expand.lua:1207: in function 'expand_bool'
    /home/asumu/igalia/pflua/src/pf/expand.lua:1178: in function 'expand_bool'
    /home/asumu/igalia/pflua/src/pf/expand.lua:1214: in function 'expand'
    /home/asumu/igalia/pflua/src/pf.lua:38: in function 'compile_filter'
    /home/asumu/igalia/pflua/tools/pflua-compile:58: in main chunk
    [C]: at 0x00404d50

This filter is equivalent to the following:

$ sudo tcpdump -d 'ip src net 192.168.1.1 and ip dst net 192.168.1.1'
(000) ldh      [12]
(001) jeq      #0x800           jt 2    jf 7
(002) ld       [26]
(003) jeq      #0xc0a80101      jt 4    jf 7
(004) ld       [30]
(005) jeq      #0xc0a80101      jt 6    jf 7
(006) ret      #262144
(007) ret      #0