openwrt – Grey Panthers Savannah https://grey-panther.net Just another WordPress site Wed, 08 Apr 2009 12:21:00 +0000 en-US hourly 1 https://wordpress.org/?v=6.7.1 206299117 Compiling software for OpenWrt (and creating packages) https://grey-panther.net/2009/04/compiling-software-for-openwrt-and-creating-packages.html https://grey-panther.net/2009/04/compiling-software-for-openwrt-and-creating-packages.html#comments Wed, 08 Apr 2009 12:21:00 +0000 https://grey-panther.net/?p=320 2726596365_66a64212fb_b From my experience, compiling software is not especially hard, but most of the tutorials out there are somewhat dated (as this one will be in 6-7 months). But at least until then it can be useful, and hopefully I will find the time to update it later on. I’m using the trunk version of OpenWrt, which a little more up-to-date than 8.09, but most probably everything described here works with 8.09 (the latest release).

I’ve taken inspiration from the following sources:

The main ideas would be:

  • The easiest way to start is by copying an existing makefile and editing it to fit your needs
  • OpenWrt has an advanced build system which does all the following things:
    • Download the application from its original source (and verify the integrity of the archive using md5sum)
    • Apply some local patches to it
    • Configure / build it

    However, for local development you most likely won’t need this. An alternative solution (which will be used in the tutorial later on) would be to copy the source to the build directory in the preparation faze.

  • Makefiles are very sensitive to tabs (so you have to have tabs and not 4 or 8 spaces in certain locations) and also, errors in them are very cryptic (for example "missing separator"). If your build fails, the first thing you should check is that you have your tabs in order. Also verify that your editor doesn’t have some kind of “transform tabs to spaces” option active. For example, if you are using mcedit with the default color-scheme, it will highlight correct tabs in red, as can be seen in the screenshot below.
    mcedit_openwrt_package Also, you might have observed that not all the sections use tabs, some are ok with spaces. However rules for which section should use what are not clear to me, so my recommendation is to stick with tabs everywhere. For a quick make tutorial, you can check out this site. A last word of warning on this matter: copy-pasting from this blogpost will almost certainly mess things up (convert tabs to spaces, etc), so please double check the source after copying it.

Our goal (taken from the first linke tutorial) is to get the following little C program to compile and run:


/****************
* Helloworld.c
* The most simplistic C program ever written.
* An epileptic monkey on crack could write this code.
*****************/
#include <stdio.h>

int main(void)
{
 printf("Hell! O' world, why won't my code compile?nn");
 return 0;
}

The first step is to create a Makefile for it:


# build helloworld executable when user executes "make"
helloworld: helloworld.o
 $(CC) $(LDFLAGS) helloworld.o -o helloworld
helloworld.o: helloworld.c
 $(CC) $(CFLAGS) -c helloworld.c

# remove object files and executable when user executes "make clean"
clean:
 rm *.o helloworld

Place the files in the packages/helloworld/src directory of either the checked-out OpenWrt source or the Openwrt SDK. Now change into this directory and make sure that everything builds on our local system (without the crosscompiling magic):


make
./helloworld <-- this should output the message
make clean   <-- clean up after ourselves

Now to create the openwrt makefile. This will be located one level up (ie. packages/helloworld/Makefile):


#
# Copyright (C) 2008 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
# $Id$

include $(TOPDIR)/rules.mk

PKG_NAME:=helloworld
PKG_RELEASE:=1

include $(INCLUDE_DIR)/package.mk

define Package/helloworld
 SECTION:=utils
 CATEGORY:=Utilities
 TITLE:=Helloworld -- prints a snarky message  
endef

define Build/Prepare
 mkdir -p $(PKG_BUILD_DIR)
 $(CP) ./src/* $(PKG_BUILD_DIR)/
endef

define Build/Configure
endef

define Build/Compile
 $(MAKE) -C $(PKG_BUILD_DIR) $(TARGET_CONFIGURE_OPTS)
endef

define Package/helloworld/install
 $(INSTALL_DIR) $(1)/bin
 $(INSTALL_BIN) $(PKG_BUILD_DIR)/helloworld $(1)/bin/
endef

$(eval $(call BuildPackage,helloworld))

The makefile should be pretty self-explanatory. A couple things I would like to highlight:

  • Build/Prepare is the step where we copy our source-code to the build directory. This is a hack to circumvent the need of downloading the tgz file, but it is a hack which works well (you might want to add the –r switch to cp if you have nested directories in src – this isn’t the case for this simple example)
  • In the Build/Compile step it is very important to include the $(TARGET_CONFIGURE_OPTS) part. Without it, the thing will build, but it will link with the standard libc, rather than the ulibc available on the Openwrt router. Tracking down this error is made harder by the unintuitive error messages. Specifically, you will see something like this on your router: “/bin/ash: The command /bin/helloworld can not be found”, even though you see that the file exists and it has execute permissions! To verify that your issues are caused by this problem, simply too a “less /bin/helloworld” on your router and check to see if you have strings indicating glibc (instead of ulibc).

Now you are ready to compile:

  • If you are using the SDK, simply go to its root directory and issue the make V=99 command
  • If you are building the complete tree, you have to first do “make menuconfig”, make sure that your package is checked for build (you should see the letter M near it) and then issue make V=99. Be aware that compiling the full tree can take a considerable time (more than a hour in some cases).

Your package should now be ready. Copy the package (you will find it in the bin/packages/target-... subfolder) to your router (or better yet, a Qemu VM running OpenWrt – for safety) and test that everything works:


scp helloworld.ipkg root@router:/root
[root@router]# opkg install helloworld.ipkg
[root@router]# helloworld <-- the message should be printed

This would be all :-). Because of simplicity, this tutorial doesn’t cover the the calling of configuration scripts. Also, as far as I’ve seen, there is no easy way to include parts of other projects. For example, if I wish to create a package for LuaFileSystem, I would need lua.h (and some other, related files). However, I haven’t found an easy way reference it from the lua package, and have opted for putting a local copy in the src/lua subdirectory.

Picture taken from cantrell.david’s buddy icon with permission.

]]>
https://grey-panther.net/2009/04/compiling-software-for-openwrt-and-creating-packages.html/feed 3 320
Installing the webhoneypot on OpenWrt https://grey-panther.net/2009/03/installing-the-webhoneypot-on-openwrt.html https://grey-panther.net/2009/03/installing-the-webhoneypot-on-openwrt.html#comments Fri, 20 Mar 2009 14:04:00 +0000 https://grey-panther.net/?p=349 3238690716_5f9771a8c0_o This is a raw tutorial for installing webhoneypot on a router running OpenWrt. The used version is Kamikaze 8.09 (this can be important because commands change between version). The tutorial is not 100% complete and I will update it in the future when I learn new information.

An other assumption I make is that you have a separate Linux machine. The techniques can be also adapted to Windows, but it is easier on Linux.

The first step is to make more space. Typical routers come equipped with small amount of flash (between 8 and 20MB), which isn’t even enough to install all the packages. This means that some kind of external storage needs to employed. In this example I’m assuming that an USB flash drive is used (a hidden assumption also is that the router in question has USB ports – for example some of the older WRT54Gs don’t, but ASUS 500 series do).

  • After logging in with SSH, update the list of packages: opkg update (in version 8.09 the list of packages is kept in RAM, so it needs to refreshed after each reboot)
  • Following (adapting) the UsbStorageHowto from the OpenWrt wiki, I installed the USB 1.1 and 2.0 modules (surprisingly both types of modules are needed to support USB 1.1 and 2.0 devices – 2.0 doesn’t offer compatibility with 1.1) and the ext3 filesystem modules:
    opkg install kmod-usb-uhci kmod-usb2 kmod-usb-storage kmod-fs-ext3
    # The insmod commands might not be necessary, because I got the message
    # "insmod: a module named X already exists" for all of them, but better
    # safe than sorry
    insmod usbcore
    insmod uhci
    insmod ehci-hcd
    insmod scsi_mod
    insmod sd_mod
    insmod usb-storage
    insmod ext3

  • Now we format our stick with the ext3 filesystem on the Linux box we have access to. You can do it with a visual tool like gparted, or from the command line:
    sudo cfdisk /dev/sdx   #delete other partitions and create a Linux partition
    mkfs.ext2 -j /dev/sdx1 #make sure to use the correct device :-)

    You might also want to consider dedicating part of the stick to swap (since the RAM of the router is also quite limited)

  • Plug in the stick into the router and mount it:
    mkdir /mnt/usbstick
    mount /dev/scsi/host0/bus0/target0/lun0/part1 /mnt/usbstick

  • Now, the following steps can lead to bricking your router, so proceed with care. The basic plan is the following:
    • Copy over the /usr directory to the stick
    • Delete the /usr directory from the internal flash
    • Mount the stick on the /usr directory
    • Install the packages we need
    • Copy back the old /usr directory to the internal flash (for safety, if for some reason the flas drive can not be mounted)

    This elaborate dance in needed because opkg (the package manager) insists on having X amount of free space on / before starting the install, even if /usr (where the packages will ultimately end up) is mounted from a separate device. opkg does have options which theoretically can work around this problem, however I couldn’t use them successfully.

  • To execute our plan:
    mkdir /mnt/usbstick/usr_backup
    # these commands will take some time
    cp -R /usr/* /mnt/usbstick
    cp -R /usr/* /mnt/usbstick/usr_backup
    rm -rf /usr/*
    umount /mnt/usbstick
    mount /dev/scsi/host0/bus0/target0/lun0/part1 /usr
    # now install the new packages. a few comments:
    # - nano is so that we can do some basic text editing (yeah, vi is too hard for me :-))
    # - php5-cli is needed because in the future an update capability will be added to
    #   the webhoneypot, which will be run from the command line
    # - php5-mod-curl - it is possible that this will be a dependency in the future
    # - php5-mod-openssl - the updates will be (possibly) done trough SSL in the future
    opkg install lighttpd lighttpd-mod-cgi lighttpd-mod-rewrite nano php5 php5-cli 
    	php5-mod-curl php5-mod-openssl php5-mod-pcre php5-mod-sockets
    # now copy back everything to /usr
    umount /usr
    mount /dev/scsi/host0/bus0/target0/lun0/part1 /mnt/usbstick
    cp -R /mnt/usbstick/usr_backup/* /usr/
    # and remount the stick again
    umount /mnt/usbstick
    mount /dev/scsi/host0/bus0/target0/lun0/part1 /usr

Now we have the packages installed. What follows is the fetching of the honeypot code from the repository and its installation to the router.

  • First we need to fetch the honeypot from the SVN. We could do this on the router (becuase it has a subversion-client package), but unfortunately that package doesn’t support the HTTP (WebDAV) protocol (as per the SVN FAQ, SVN implements a plugin system for the different protocols and ra_dav is missing from the package provided by OpenWrt). So we do on the Linux box: svn export http://webhoneypot.googlecode.com/svn/trunk/
  • We should also prepare two other files on the Linux box, which will be copied over to the router (you could create them on the router, but it is more convenient to do it on the Linux side):

    lighttpd.conf

    server.modules              = ("mod_rewrite", "mod_cgi")
    server.document-root       = "/usr/wh/html/"
    server.upload-dirs = ( "/tmp/" )
    server.errorlog            = "/usr/wh/logs/lighttpd_error.log"
    index-file.names           = ( "index.php", "index.html",
    static-file.exclude-extensions = ( ".php", ".pl", ".fcgi" )
    server.port               = 80
    server.bind                = "0.0.0.0"
    server.pid-file            = "/var/run/lighttpd.pid"
    dir-listing.encoding        = "utf-8"
    server.dir-listing          = "disable"
    url.rewrite-once = ( "^/(.*)$" => "/index.php/$1" )
    cgi.assign = ( ".php" => "/usr/bin/php-cgi" )
    # debug.log-request-handling = "enable"

    php.ini

    [PHP]
    
    engine = On
    short_open_tag = Off
    asp_tags = Off
    output_buffering = Off
    max_execution_time = 5
    max_input_time = 60
    memory_limit = 8M
    error_reporting  =  E_ALL & ~E_NOTICE
    
    register_globals = Off
    post_max_size = 8M
    magic_quotes_gpc = Off
    magic_quotes_runtime = Off
    extension_dir = "./"
    enable_dl = Off
    cgi.force_redirect = 1
    file_uploads = Off
    allow_url_fopen = On
    allow_url_include = Off
    
    apc.enabled = Off
    
    extension_dir = "/usr/lib/php/"
    extension=pcre.so

    We set up lighttpd to run PHP scripts using the CGI protocol (FastCGI would be more efficient, but also more complicated). The steps were adapted from this tutorial. The php.ini file is needed for two reasons: first, Perl regex support is not compiled into the PHP binary, so we must load it. Second APC support is compiled into the PHP library, so we must disable it, since it tries to allocate 32M of memory by default, which makes PHP fail, since we have around 20M of memory in total :-). To test that your PHP installation is workin, issue the following command on the router: /usr/bin/php-cgi -v It should output some basic information about PHP (lik version, copyright, etc). If it fails because of the APC cache, it outputs error message like the one described here: [apc-error] apc_shm_create: shmget(0, 8388608, 658) failed: No error. It is possible that the chosen SHM segment size is higher than the operation system allows. Linux has usually a default limit of 32MB per segment.

  • We copy all the files from the Linux box to the router (in the /usr directory, since it now represents the USB stick):
    # on the router:
    mkdir /usr/wh
    # on the Linux box - replace 192.168.1.1 with your router's IP
    scp -r * [email protected]:/usr/wh
    # on the router:
    mkdir /etc/lighttpd
    mv /usr/wh/lighttp.conf /etc/lighttpd
    mv /usr/wh/php.ini /usr/bin
    # start the webserver

  • Start the webserver: lighttpd /etc/lighttpd/lighttp.conf Check that everything is working by accessing the address http://192.168.1.1/phpbb/ from you box (where 192.168.1.1 should be replaced with your router’s address)
  • Now configure the honeypot however you wish. The installation document should given you a good start. To edit the configuration file, do nano /usr/wh/etc/config.local. One thing I would suggest is to add loglevel=4 to it, so that the request details are also stored locally.
  • The next step would be do get a DNS name (from DynDNS for example). This is especially important if you have an IP address which changes from time to time. Also, you should submit the honeypot URL to the search engines. Have fun and please report any bugs or problems on the issue tracker.

Picture taken from mightyohm’s photostream with permission.

]]>
https://grey-panther.net/2009/03/installing-the-webhoneypot-on-openwrt.html/feed 1 349