BIND9 Zone Transfers and Views
If a BIND server is using views to serve two different zone files for the same zone, can a slave nameserver receive a full AXFR of both zone files? From what I have observed, no.
We (limed and I) setup one master nameserver (ip address 10.192.126.20) and one slave nameserver
(ip address 10.192.126.21). We found that the slave nameserver would receive the "public-view"
data if it's ip wasn't in the "private-view" acl range and would receive the "private-view" data if
it's ip was in the "private-view" acl range. During our test, the slave nameserver would transfer
the same zone data into the two different files, db.foo.bar.internal and db.foo.bar.external.
The master named.conf.local config:
acl "zone-transfer" {
10.192.126.21/32; // Slave ip (dns-dev2)
};
// Views
acl "public-view" {
any;
};
acl "private-view" {
10.0.0.0/8;
};
view "internal" {
match-clients { "private-view"; };
zone "foo.bar" {
type master;
file "/etc/bind/db.foo.bar.internal"; // Contains extra data
};
...
...
...
};
view "external" {
match-clients { "public-view"; };
zone "foo.bar" {
type master;
file "/etc/bind/db.foo.bar.external";
};
};
The slave named.conf.local config:
acl "pub-view" {
any;
};
acl "private-view" {
10.0.0.0/8;
};
view "internal" {
match-clients { "private-view"; };
zone "foo.bar" {
type slave;
file "/etc/bind/db.foo.bar.internal";
masters {
10.192.126.20;
};
...
...
...
};
view "external" {
match-clients { "pub-view"; };
zone "foo.bar" {
type slave;
file "/etc/bind/db.foo.bar.external";
masters {
10.192.126.20;
};
};
};
It would be convenient to transfer both files via AXFERs would be easier than using rsync or ftp to transfer the internal and external zone files.
Using Playdoh apps outside of Playdoh.
Django is cool and Playdoh is also pretty cool. But, using django models and django's ORM is really cool. Using django's ORM (not in Playdoh) just involves some os.environ magic.
import os
import sys
# Add project to python path
sys.path.append("/path/to/your/project/")
# Set magic variables.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'project.settings')
# It works?
from project.app.models import some_object
# It works!
Things are different when you want to do the same thing with Playdoh.
import os
import sys
# We still do this
sys.path.append("/path/to/your/project/")
# This stays the same
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'project.settings')
# Here is the difference.
from funfactory import manage
manage.setup_environ("/path/to/your/project/manage.py", more_pythonic=True)
# Import some objects.
from project.app.models import some_object
Playdoh uses funfactory for library configuration. From looking at the source code, it looks
like manage.setup_environ infers path information from the manage.py in a project's
root dir when loading libraries (i.e. things in the vendor directory).
You should now be able to import your apps' models and use Django's ORM outside of Playdoh!
Simple Python Inheritance
Lately, I have been working with Django Class-Based Views (CBVs) which use inheritance heavily. However, they call inheritance "mixing". They build up classes by mixing in other classes and inheriting their properties. I had defined some of my own mixins, and I wondered, which mixin takes precedence? I wrote some simple classes and then performed science.
class A(object):
x = "I'm from A."
class B(object):
x = "I'm from B."
Class W has two mixins, A and B. I mix A first.
class W(A, B):
""" """
Class Y has two mixins, A and B. This time I mix B first.
class Y(B, A):
""" """
Classes A and B both inherit from object. What happens if I don't inherit from object?
class A_():
x = "I'm from A_."
The class U mixes A_ and B. A does not inherit from object.
class U(A_, B):
x = "I'm from B."
Below are the tests I ran using Python 3. The results were the same when Python 2.7 was used.
>>> w = W()
>>> print("Printing class that mixed A first.")
"Printing class that mixed A first."
>>> print(w.x)
"I'm from A."
>>> y = Y()
>>> print("Printing class that mixed B first.")
"Printing class that mixed B first."
>>> print(y.x)
"I'm from B."
>>> u = U()
>>> print("Printing class that mixed A_ first.")
"Printing class that mixed A_ first."
>>> print(u.x)
"I'm from B."
Conclusions
Which order you mix classes is important. Precedence is from left to right. If you don't inherit from object, you lose precedence to classes that do.
Further Questions
Why does it work like this?
Notes on how to get an atmega128 tool chain working on Linux
Here is a quick write up on what I did to get a tool chain working for the atmega128 microprocessor in Linux.
Install Notes
The library file, m128ref.inf, can be found here http://www.attiny.com/definitions.htm
wget http://www.attiny.com/software/AVR000.zip
unzip AVR000.zip
ls AVR000/m128ref.inf
OSU's avrdude is found here http://beaversource.oregonstate.edu/projects/osuisp2/wiki/AvrdudeLinux
svn co --username <onid_username> https://code.oregonstate.edu/svn/osuisp2
Install the dependencies and follow the instructions on Beaversource to install avrdude. From what I understand OSU has patched the drivers to specifically work with the board we use in Lab.
Note: DO NOT get the avr assembler from ubuntu's repo's or EPEL. The version of the code is ancient (November 2007).
The avra (AVR assembler) is found here http://sourceforge.net/projects/avra/files/latest/download
wget http://sourceforge.net/projects/avra/files/latest/download -O avara-1.3.0.tar.bz2
I had some trouble installing this, here are the hacks I did to get it installed.
cd avra-1.3.0/src/
touch NEWS ChangeLog
automake --add-missing
./configure
make
sudo make install
Make sure you have the package automake and build-essentials installed (this is what they are called on ubuntu).
Now that you have everything installed you can compile .asm files into .hex files.
avra ece375-L1_v2.asm
You should now see a .hex file. Use avrdude to upload it to the board.
avrdude -c osuisp2 -P /dev/usb/hiddev0 -p m128 -e -U flash:w:ece375-L1_v2.hex -v
Compiling C program
Getting C code to run is just as easy as getting assembly running. First you need some packages (these are their names according to aptitude).
avr-libc
gcc-avr
Install them:
sudo aptitude install avr-libc gcc-avr
You might not need avr-libc. If I undertand correctly, it installs the m128ref.inf library, which we have already done. But it doesn't hurt.
To compile C code run the following command where $(FILE) is the name of your program. (i.e. if you had a C file foo.c, FILE would be FILE="foo".
avr-gcc -Wall -mmcu=atmega128 -o $(FILE).o $(FILE).c
This compiles the .o file. To get the .hex file, run:
avr-objcopy -j .text -O ihex $(FILE).o $(FILE).hex
Now use avrdude, as described earlier, to flash your board with the .hex file.
avrdude -c osuisp2 -P /dev/usb/hiddev0 -p m128 -e -U flash:w:$(FILE).hex -v
Makefiles
Here are the Makefiles I used for lab.
Assembly Makefile
FILE="ece375-L1_v2"
build:
../../avra-1.3.0/src/avra $(FILE).asm
rm $(FILE).obj
rm $(FILE).cof
rm $(FILE).eep.hex
install:
avrdude -c osuisp2 -P /dev/usb/hiddev0 -p m128 -e -U flash:w:$(FILE).hex -v
clean:
rm $(FILE).hex
C Code Makefile
FILE="ece375-L2_skeleton"
build:
avr-gcc -Wall -mmcu=atmega128 -o $(FILE).o $(FILE).c
avr-objcopy -j .text -O ihex $(FILE).o $(FILE).hex
rm $(FILE).o
install:
avrdude -c osuisp2 -P /dev/usb/hiddev0 -p m128 -e -U flash:w:$(FILE).hex -v
clean:
rm $(FILE).o
rm $(FILE).hex
Do you have questions?
If you have questions, hop on IRC and ask me!! I'm on irc.freenode.net in the channel #osu-lug. My handle is uberj.
Reverse IPv6 Zones
Alas IPv6.
I have been workgin on building bind files while using Google's IP address library ipaddr (awesome library), which is written in Python.
I'm working on something that requires me to determine which reverse zone an IP belongs in. In IPv4 this is super easy. Mainly it's easy because an ipv4 address has one correct representation:
w.x.y.z # Where w,x,y,z are in [0 through 255]
The reverse domain boundaries of an IPv4 domain are along octet boundaries. Since IPv4 adresses
always have four octets, mapping an IPv4 address to a reverse domain is a one to one
'longest-prefix-match' function. For example say we had the reverse domain's 4.193.128.in-addr.arp
and 193.128.in-addr.arpa. Which reverse domain would 128.193.4.1 fall into? It's pretty easy to
tell that it belongs to 4.193.128.in-addr.arpa. It's full reverse name would plainly be
1.4.193.128.in-addr.arpa.
In IPv6 things are different. IPv6 allows IP addresses to be represented differently. For example
1234:0::, 1234:0:0:: and 1234:: are all the same address. But those three addresses all have
the same reverse notation! There goes that nice one to one function we had with IPv4 addresses. To
map an IPv6 address to it's correct reverse domain using a 'longest-prefix-match' function, we need
to get the address into a very specific format.
First let's look at what a reverse IPv6 domain name looks like.
The reverse address of 2620:105:F000::1 looks like this:
1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.F.5.0.1.0.0.2.6.2.ip6.arpa # 32*4 bits = 128 bits
Comparing IPv4 notation with IPv6 we see that '.' is still used as a separator, there is no
truncation (there are always 32 four bit 'nibbles'), and in-addr.arpa is replaced with
ip6.arpa. This is the correct and only way the reverse representation should look (afaik).
So back to the problem. Given an address like 2620:105:F000::1, find the proper reverse domain.
Sounds like a job for the function IPv6Address('2620:105:F000::1').nibble followed by a
'longest-prefix-match' like we did with IPv4 addresses. As far as I know nibble doesn't exist, so
I wrote my own function to calculate it.
"""
@param: addr - A valid IPv6 string
@return: correct reverse zone representation
>>> nibblize('2620:0105:F000::1')
'2.6.2.0.0.1.0.5.F.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1'
>>> nibblize('2620:0105:F000:9::1')
'2.6.2.0.0.1.0.5.f.0.0.0.0.0.0.9.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1'
>>> nibblize('2620:0105:F000:9:0:1::1')
'2.6.2.0.0.1.0.5.f.0.0.0.0.0.0.9.0.0.0.0.0.0.0.1.0.0.0.0.0.0.0.1'
"""
import ipaddr
def nibblize( addr ): # Hey nibalizer!
ip_str = ipaddr.IPv6Address(addr).exploded
return '.'.join(list(ip_str.replace(':','')))
It would be cool if I could do this:
IPv6Address('2620:0105:F000::1').nibbles
>>> ip = IPv6Address('2620:0105:F000::1')
>>> ip.nibbles
'2.6.2.0.0.1.0.5.f.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1'
Feature request?
References: http://www.zytrax.com/books/dns/ch3/#ipv6
Dynamic test cases
A few weeks ago I spent hours trying to figure out how to create dynamic tests at run time with python's unittest library. Specifically I wanted to do it in twisted's unittest library, but the one in standard lib is very similar to the one in twisted.
What I was trying to do was run tests that were not written yet. I was going to read in a file that had data that described the input and expected result, then run a test to make sure that input data did indeed generate that result. Here was the solution I came up with (some credit is owed to MostAwesomeDude who's two words "class scope" made me rethink how to do this).
Here is the basic Idea.
import unittest
def build_test( self, *params ):
def general_test( self ):
...
... Do test that relies on params.
... Just make sure you 'assert' something.
...
return general_test
class Tester(object):
class TestSomeThing(unittest.TestCase):
pass
if __name__ == "__main__":
test_cases = [('input_a','expected_a'),('input_b','expected_b'),....]
for input, expected in test_cases:
test = build_tests( input, expected )
setattr( TestBindBuilds, "test_%s" % (input) , test )
unittest.main()
This is a toy solution to a problem that doesn't exist. The real code that I wrote using this method can be found here on my github.
One way around a Wifi portal.
This summer I went to Linux-con. My group of friends stayed at a youth hostel that offered internet that you had to sign up for. To use the internet you had to log-in with user credentials using a web portal. We found a way around it.
The setup
The network, from our point of view, seemed fairly simple. Everyone who associated with an access-point (AP) was dropped onto a VLAN and given an IP via DHCP. Using this IP you could get to the registration page, but besides that, most useful protocols were being filtered. I say "most" because not everything was blocked. Port 53 was unfiltered and we were able to resolve host names using external DNS servers. One of my friends settled for just tunneling through DNS as a solution. In hind site, tunneling with ssh should have worked too (I doubt they were checking for valid DNS traffic) and I'm not sure why we didn't just do that, oh well.
The solution
Being on that severely firewalled VLAN was not very useful. We needed a way to get onto the VLAN that had access to the larger internet. The good news for us was that these "web portal login pay-walled" internet set ups all work very similarly. You get an account, you login, the system records your MAC address as "valid" and not so magically you end up on a different VLAN and are able to check Facebook. Hurray! Hurray? Yes, all you have to do is get a mac that is already "valid" and you are set.
But what about collisions? Yes, if you are on a layer 2 network with someone with the same MAC address as you things really don't work to well. After TCP sessions kept on collapsing we needed a fix. Since the problem is isolated to level 2, going up 3 floors, sniffing an authenticated mac using Kismet and using that mac solved our problems. Internet for all.
The solution
WPA2 encryption for communicating to the access points and a RADIUS server serving client credentials for use on the second VLAN would %100 make this attack not work. Using WPA-PSK would be sort of silly seeing how it's "Pre-Shared KEY" and not "KEYS". With any sort of encryption between the edge hosts and the AP's stealing a mac would be in vain. You wouldn't know the cipher that the AP is using and so any data sent or received would be seen as garbage on both sides of any connection (it probably would fail the CRC check and fail to even make it onto the wire).
Page 1 of 1