Applying Design Patterns in the implementation of a simple packet filter

65  Download (0)

Full text



Applying Design Patterns in the implementation of a simple packet filter




Applying Design Patterns in the

implementation of a simple packet filter


Supervisor: Michael Schliephake Examiner: Örjan Ekeberg

CSC May 8, 2015




By reading this thesis the reader will get insight into if and how Design Pattern can help in the grand scheme of software development.

Practice is combined with theory in an empirical study to see if Design

Patterns are a feasible method for implementing a simple packet filter-

ing solution. The resulting application uses the Chain of Responsibil-

ity and Simpleton Design Patterns together with the Security Pattern

Packet Filter Firewall. In the results the thesis will present how De-

sign Patterns assisted in the design and successful implementation of

the packet filter together with a discussion of the benefits, limitations

and drawbacks of the solution. Finally the reader will take part in how

further studies can be constructed upon the given result.




Genom att läsa denna avhandling kommer läsaren få inblick i om och hur Design Pattern kan bidra till mjukvaruutveckling. Praktik kombineras med teori i en empirisk studie för att se om designmönster är en användbar metod för att implementera ett enkelt packetfilter.

Den resulterande applikationen använder sig av designmönstret Chain

of Responsbility och Simpleton, samt säkerhetsmönstret Packet Filter

Firewall. I resultatet presenteras det hur designmönster bidragit till

skapandet av ett paketfilter tillsammans med en diskussion om fördelar,

nackdelar samt begränsningar. Läsaren kommer sedan avslutningsvis

ta del av hur ytterligare studier kan byggas på resultat.



Contents iv

1 Introduction 1

1.1 Dictionary . . . . 2

2 Background 3 2.1 Design Patterns . . . . 3

2.2 Design Patterns now and then . . . . 4

2.3 The structure of a Design Pattern . . . . 4

2.3.1 A pattern for design . . . . 4

2.3.2 Purposes for Design Patterns . . . . 5

2.3.3 Security Patterns . . . . 6

2.3.4 Specializing patterns and Packet Filter Firewall . . . . 6

2.4 Object Oriented Programming . . . . 8

2.5 Patterns used in this thesis . . . . 8

2.5.1 Singleton - A Creational Pattern . . . . 8

2.5.2 Chain of Responsibility - a Behavioural Pattern . . . . 9

2.5.3 Packet Filter Firewall Pattern - A Security Pattern . . 10

2.6 Packet filtering . . . . 12

2.7 A simple packet filter . . . . 12

2.8 Problem Definition . . . . 13

2.9 Problem Statement . . . . 13

3 Method 14 3.1 Literature study . . . . 14

3.1.1 Chain of Responsibility . . . . 14

3.1.2 Singleton . . . . 15

3.1.3 Packet Filter Firewall . . . . 15

3.2 Programming and implementation of the pattern . . . . 15

3.2.1 Implementing a pattern . . . . 16




4 Results 17

4.0.2 Packet Filter . . . . 19

4.0.3 Packet . . . . 20

4.0.4 Filter Engine . . . . 21

4.0.5 Filter Rule . . . . 21

5 Discussion 22 5.0.6 The results . . . . 22

5.0.7 On overuse of Design Patterns and Singleton . . . . 22

5.0.8 Thoughts on our constrains and limitations . . . . 23

5.0.9 The significance of our study . . . . 24

6 Conclusion 25 6.1 Further studies . . . . 25

Bibliography 27 A Appendix A - Code 29 A.1 PacketFilter.cpp . . . . 29

A.2 FilterEngine.h . . . . 33

A.3 FilterEngine.cpp . . . . 34

A.4 FilterRule.h . . . . 37

A.5 FilterRule.cpp . . . . 38

A.6 Packet.h . . . . 41

A.7 Packet.cpp . . . . 42

B Appendix B - Rule file 49 B.1 rules.txt . . . . 49

C Appendix C - Wireshark capture file 50

C.1 cap8.txt . . . . 50


Chapter 1 Introduction

"How many times have you had a design dejavu– that feeling that you’ve solved a problem before but not knowing exactly where or how?" [1, p. 2] This question was asked in the early 90’s when a group of software developers wrote a book on a concept they liked to call Design Patterns. The question empha- sized on if a person could remember the details of a previously solved problem, they could use that experience to solve the problem again without having to rediscover the solution. The book Design Patterns - Elements of Reusable Object-Oriented Software [1] became this tome of recorded experiences to well known problems in object-oriented software design. These experiences are recorded in a formula known as a pattern. Each pattern is very specific on what it solves and how. The user of the pattern then use this tried and tested solution to make his life a little bit easier.

Since its birth, the concept "Design Pattern" have evolved into several other forms. While Design Patterns in its raw form solves a general problem, there are more specialized patterns that deals with specific areas such as databases, applications, whole namespaces and so on. In this thesis the authors will evaluate Design and Security Patters. Theory and design will be tested by the implementation of a simple packet filtering application through an empirical study.




1.1 Dictionary

• Coupling: The grade of dependency between software modules.

• Encapsulate: Packaging the data in to an object.

• Pattern: A formula for solving a reoccurring problem.

• Packet Filter: A function that filters packets based on a ruleset.

• Protocol: A system of rules for data exchange.

• PDU: Protocol Data Unit.

• IP: Internet Protocol.

• IP-Address: A way to identify an entity on a network.

• TCP: Transmission Control Protocol.

• UDP: User Datagram Protocol.

• Port: A way to identify a PDU with an application.

• Header: Data placed in the beginning of the package

• Payload: The data to be delivered.

• C++: An object oriented programming language.

• Object: An instance of a class.

• Object-Oriented Programming: A ways of programming that focuses on using objects.

• The Gang of four (GoF): A reference to the authors of "Design Patterns:

Elements of Reusable Object-Oriented Software.

• Refactoring: A process to restructure and improving an existing code base.

• IP Spoofing: Forging the source IP address with the intend to gain

unauthorized access to a computer.


Chapter 2 Background

2.1 Design Patterns

Design Patterns is the method for creating reusable solutions to solve common and well known design problems in software engineering [1,3,4,7,8]. The idea is that software engineers facing well known design problems can turn to already tried and tested solutions to avoid reinventing the wheel. This concept is not something new for experienced software engineers, since they tend to stick to their past experiences and perfect them over time.

Design Patterns are these experiences recorded for those who lack past experiences or want to improve on their design and architecture skills. They can also be used to help increase the modularity and reusability of code, and this is something that can be referred to as designing for change [1, p. 23].

Designing for change deals with avoiding design related errors that might lead to major redesign or refactoring in the software life cycle. Common de- sign pitfalls include, but are not limited to, examples such as; hard coding, conflicting platform dependences, tight coupling and incorrect usage of in- heritance. Redesigning because of the reason above will often be more time consuming and costly than just planning ahead [8, p. 8]. However designing for change is not only about using Design Patterns, it is also about knowing when and how to use them. At points it might be more favourable to write some simple and short code which provides the same flexibility as a pattern solution would [8, p. 8] [13, p. 8]. It is part of each Design Pattern to also help their user to make this choice [1, p. 31].

Design Patterns are important in the sense that they leave system structure more robust, they are after all tried and tested solutions, but they also provide excellent assistance when object-oriented programming is practised [1, p. 24].

While each pattern is a solution to a smaller problem, they can because of



CHAPTER 2. BACKGROUND 4 their genericness together form whole applications. Applications were objects and classes by practice are only as depended of each other as they need to be [1, p. 26] [2, p. 4].

2.2 Design Patterns now and then

Design Patterns started out in the early 90s with the book Design Patterns:

Elements of Reusable Object-Oriented Software [1]. By then, the focus was on general applicability. These patterns were described as "descriptions of communicating objects and classes that are customized to solve a general design problem in a particular context" [1, p. 3] [3, p. 37]. The focus was to solve general design problems and relationships, not specific application problems or fully working architectures. Other books and research further expand on general architecture, design and programming until they in the early 21st century became more specific to certain areas [4, p. 5] [3, p. 39-40].

This could be patterns for networking, programming or computer security.

2.3 The structure of a Design Pattern

Each pattern follows a format that helps the user apply it as a solution to a problem. The format for Design Patterns were given back in 1994 [1, p. 6] by the GoF and has served as guidelines for Design Patterns since then. This is also the format this thesis will use to explain Design Patterns.

2.3.1 A pattern for design

• Pattern Name and Classification: The name of the pattern.

• Intent: The purpose behind the pattern.

• Motivation: Shows an example where the pattern fit in

• Applicability: Options and ideas about when you can apply the pattern.

• Structure: Shows a graphical representation of the pattern.

• Participants: Classes and/or objects belonging to the pattern.

• Collaborations: How these participants collaborate.

• Consequences: Shows the benefits and liabilities with using the pattern.

• Implementation: How to implement the pattern.



• Related Patterns: Other patterns close in functionality.

The format defined in Design Patters - Elements of Reusable Object-Oriented Software [1, p. 6] also includes the following information that were left out from this thesis.

• Implementation: How to implement the pattern.

• Sample Code: This shows example code for the pattern.

• Also Known As: If there exists any other names for this pattern.

• Related Patterns: Other patterns close in functionality.

• Known uses: Known uses in other systems.

2.3.2 Purposes for Design Patterns

All patterns are catalogued after three distinct types that can also be seen as three different "purposes" [1, p. 10]. Patterns can then also be either a class pattern or an object pattern.

• Creational Patterns - Deals with how classes and objects are created. A class Creational Pattern will use inheritance to control the instantiated class while an object Creational Pattern will delegate the instantiation to another object. They also encapsulate classes that the system uses, and hides how instances are created and collaborate with each other [1, p. 81] [7].

• Structural Patterns - Creates larger structures from classes and objects.

A structural class pattern use inheritance to compose interfaces and implementations while a structural object pattern composes objects to form new functionalities [1, p. 137] [7].

• Behavioural Patterns - Does not only describe objects and classes but

also interactions, algorithms and responsibilities between these. The

purpose of a behavioural pattern is to focus on how objects connect [1,

p. 221] [7].



2.3.3 Security Patterns

As already mentioned, Security Patterns are a specific type of Design Pat- terns. They specialize on security threats and proven solutions for control- ling these [9, p. 30]. Each Security Pattern aims to integrate basic security and knowledge into a system or enterprise on a high level of implementa- tion [4, p. 34]. The goal for Security Patterns is to also give clearly defined consequences for each solution as well as to help put the right solution to the right problem. This is similar to how Design Patterns help designers and soft- ware engineers making correct design choices. For Security Patterns this helps avoid false security by putting a specific pattern into a solution that does not solve the right problem. Security Patterns also pay attention to how different systems of patterns can relate to each other.

For this the format to present Design Patterns will be the same used to present Security Patterns. In context, they are still very close to each other and bring the same key elements to the table [4, p. 31].

2.3.4 Specializing patterns and Packet Filter Firewall

In Security Patterns: Integrating Security and Systems Engineering [4] and Firewall Patterns [6] the authors explains specializing patterns in the area of firewall patterns. This concept deals with how relationships between patterns can add to a multi pattern hierarchical solution. For example the Firewall [6, p. 6] pattern is described as controlling traffic between two or more networks.

It is supposed to be the fundamental base to build a firewall upon. Further

more, the Packet Filter Firewall [4, p. 504] could then be seen as a more

focused and specialized pattern of the Firewall. It adds functionality to the

solution, in this case filtering on IP level. In the same way there can exists

several specialized patterns to a parent pattern. For example, the Proxy Based

Firewall pattern [4, p. 411] deals with packets on application level and is also

a specialization of the Firewall pattern. This does not make Packet Filter

Firewall redundant as both are specializations that can deal with different

problems assigned by the firewall. Finally there exists a Stateful Firewall [4,

p. 417] pattern which specialize on the Packet Filter Firewall (or the Proxy

Firewall pattern) and adds dynamically created rules to the mix. Together this

hierarchy of security patterns create a functionality that makes it simple to

build a complex solution by using the security patterns as modules that build

upon each other. An advanced firewall could be all these patterns connected

together to form a larger and more complex solution [4, p. 404].



Filters on IP-level Filters on application-level

Basic firewall

Creates rules dynamically

Other functionalities like for example network abilities

like DNS

Figure 2.1. Security pattern hierarchy



2.4 Object Oriented Programming

Object Oriented Programming, or OOP as it is commonly abbreviated, is a way of programming that uses Data Abstraction, Inheritance, and Dynamic Binding [10, p. 557].

An object oriented program could be seen as an abstract model of the reality. In this model each object represent a part or a thing that helps in forming the reality that the application represents [11, p. 51]. This way of structuring data is what can be referred to as Data Abstraction.

In this thesis the candidates to make up the objects are; Packet, Packet- Filter, FilterEngine and FilterRule. In C++ the Data Abstraction is done by using classes to represent the different objects of a program. [10, p. 557].

The object oriented approach to programming is in direct contrast to the more traditional way of seeing programming as a box that receives input, transforms it and writes output. This is also commonly known as Function Oriented Programming [11, p. 51].

Inheritance, which is another big part of C++ Object Oriented Program- ming, is handled by class Derivation [10, p. 557]. This means that a class that is derived from its base class can use any one of the base classes member functions [10, p. 558]. In some cases the derived class will use the functions as they are, but in other cases the derived class will redefine these functions to better suit its need.

Dynamic binding, which is the last big part of C++ Object Oriented Pro- gramming, allows the compiler to make runtime decisions to either call the base class function or the derived class function. [10, p. 621].

2.5 Patterns used in this thesis

2.5.1 Singleton - A Creational Pattern

• Source: [1, p. 127]

• Pattern Name and Classification: Singleton.

• Intent: Ensure a class only has one instance with a single point of access.

• Motivation: Some classes need to have exactly one instance to which it itself provides access.

• Applicability: Use when there must be exactly one instance and it must

be accessible from one point. Or when the sole instance should be ex-

tendible by sub classing and clients can use an extended instance without



modifying their code.

• Structure -


static instance() SingletonOperation() GetSingletonData()

static uniqueinstance singletonData


Figure 2.2. Singleton

• Participants: Singleton - creates a unique instance for clients.

• Collaborations: Clients access the Singleton instance directly.

• Consequences: The Singleton class encapsulate its own instance and gain total control over when and how clients access it. It is also an improve- ment over using global variables and gives flexibility when configuring subclasses or extended instances of the Singleton class.

2.5.2 Chain of Responsibility - a Behavioural Pattern

• Source: [1, p. 223]

• Pattern Name and Classification: Chain of Responsibility

• Intent: Avoid coupling between sender and receiver. Send a receiving object through a chain until one object handles it.

• Motivation: There might exist a need to decouple senders and receivers.

• Applicability: Use when more then one object might handle a request

and you do not want to specify the receiver. The set of objects that


CHAPTER 2. BACKGROUND 10 handles the request should be specified dynamically.

• Structure -

Client Handler


ConcreteHandler1 HandleRequest()

ConcreteHandler2 HandleRequest() Successor

Figure 2.3. Chain Of Responsibility

• Participants: A Handler that defines an interface for requests. The Handler is then connected to a Concrete Handler that handles requests.

The client initiates the request to the Concrete Handler(s).

• Collaborations: The request is initiated by the client and then travels along the chain until a Concrete Handler takes responsibility for the request.

• Consequences: The pattern reduces coupling between the sender and the receiver. The whole structure of the chain is unknown to any but the Handler itself. It is easy to add or remove Concrete Handlers. However, there is no guarantee that a request is handled. It could fall of the chain if no Concrete Handler takes responsibility for it.

2.5.3 Packet Filter Firewall Pattern - A Security Pattern

• Source: [2]

• Pattern Name and Classification: Packet Filter Firewall

• Intent: Filter incoming and outgoing network traffic based on the packets




• Motivation - When there is need for a low performance filter on IP level.

• Applicability - Some malign entities may try to attack a network through IP level payloads. The network needs to be protected so that it can still stay connected to other networks. At the same time the protection needs to be transparent for users on the network as well as precise to reflect existing security policies. The protection needs to be easily customiz- able, clear on what is being protected, have low cost and the possibility to log activity.

• Structure -

Packet Filter Sender


Reciever address

RuleBase addRule() deleteRule() modifyRules() reorderRules()

Rule in/out

explicitRule defaultRule

Figure 2.4. Packet Filter pattern

• Participants: The Packet Filter Firewall object receives requests from clients and either forward or drop them. The RuleBase class hosts and creates the rules for the organization. These rules can be either explicit or default.

• Collaborations: Packet Filter Firewall receives requests from clients. It

request a service from the RuleBase which checks the request against all

the rule objects. It then either accepts or denies the request. If denied,

Packet Filter Firewall drops the package.



• Consequences: The Packet Filter Firewall have the following conse- quences:

Packages are filtered when moving through the firewall.

It is easy to reflect an organizations security policies through the rules.

The rules are easy to update.

The Packet Filter firewall could log messages and incidents.

It has a low cost because of its simplicity.

Can be combined with other security systems.

Rules can interfere with each other if not carefully applied.

Can not stop attacks that travels to higher levels then the IP level.

Every package needs to be analysed. May affect performance.

Does not handle IP spoofing.

2.6 Packet filtering

Packet filtering is the method of passing or dropping individual packets at a network interface [2, p. 329]. This is typically done by defining static rules specified on source address, protocol, port number and so on. A packet filter can also handle packets dynamically (Stateful Packet Filtering) where the packet filter understands requests and replies [2, p. 330]. New rules are created during the procedure of handling a whole sequence of packets, instead of only single ones. There is a benefit in that this allows a packet filter to handle much more advanced protocols. For a simple packet filter however static rules are enough.

2.7 A simple packet filter

For a simple packet-filter we want to have the following functionality:

• Able to receive packets and extract their TCP/IP header information

• Retrieve source and destination address.

• Run the extracted information against pre-determined static rules.

• Pass or drop each packet.



2.8 Problem Definition

The main purpose of this thesis is to investigate the feasibility of using Design Patterns when developing new software solutions. This study will evaluate the usage of Design Pattern in software development by implementing a simple packet filtering solution using the object oriented language C++.

A pack filtering solution was chosen because an application with security related features has great benefits from being developed in a structured and se- cure way. The added structure that Design Patterns provide will help prevent the packet filters security functionality from being jeopardized.

2.9 Problem Statement

Are Designs Patterns a possible way to design and develop a simple packet

filter such that the solution can handle the security requirements in a generic



Chapter 3 Method

3.1 Literature study

A literature study around Design Patterns and Security Patterns was neces- sary to understand the concept and background of the subject. This included the work of "The Gang of Four" and various other books explaining the theory and basics. Further information was drawn from conference papers and stud- ies found on the internet. These were not found through any specific site or forum, but included after review from search engine results and cited reference searching. Student literature already in possession of the authors were used for reference to Network Security, TCP/IP as well as Computer Networking.

3.1.1 Chain of Responsibility

During the beginning of the literature study, the pattern Chain of Responsi- bility [1,7] seemed like a match for this thesis problem statement. The pattern structure corresponded well with our idea of how a packet object will traverse a chain of rules.

This chain would consist of rule objects. Each rule object would then evaluate the packet object by comparing its own rules against the packets payload. The rules object will then either drop the packet, if the content matched its rule, or pass it to the next rule object in the chain.

The Chain of Responsibility also fit the scope since it provided a way for decoupling sender and receiver [1, p. 226]. This in turn means that sender and receiver also has no reference to the rules that the packet object pass through.

This knowledge is reserved for the FilterEngine.

The way Chain of Responsibility works also means that it is very simple to add and remove rules during runtime [1, p. 226].



CHAPTER 3. METHOD 15 One of the risks with the design of the pattern is that a request does not have an explicit receiver. This could in theory mean that a request falls of the chain without ever being handled [1, p. 226]. This problem can be solved by defining a default rule object at the end of the chain to guarantee that a request is handled.

3.1.2 Singleton

Another pattern that stood out during the literature study is the "Singleton"

Design Pattern [1, p. 127]. The Singleton Pattern is a way to ensure that a class can only ever be instantiated once.

The use of the Singleton Pattern in this thesis would be to assert strict boundaries on the FilterEngine class.

3.1.3 Packet Filter Firewall

The Packet Filter Firewall pattern describes implementing a packet filter that sorts packets on the IP-level [4, p. 405] [6]. It is similar to the Chain of Responsibility Pattern in that it has a handler that delegates incoming packet objects to a set of rules.

The Packet Filter Firewall pattern intercepts indata from a source and passes this to a RuleBase object. The RuleBase object is then responsible for matching the indata against the ruleset and then either drop or forward it to the destination. [4, p. 409] [6]

The ruleset consists of a set of explicit rules and a default rule. If no match can be made between the indata and one of the explicit rules, the default rule will always be used. This means that a package will always be handled in contrast to the Chain of Responsibility pattern which do not give the same guarantee.

3.2 Programming and implementation of the pattern

During the literature study investigation were made into what was required to access the network interface on a Windows 7/8 based system. It was quickly realised that a custom driver was needed to be able to create a working packet filter solution able to intercept traffic.

To get around the extra time the implementation of a driver would take it

was decided that the thesis scope would be narrowed. This was accomplished


CHAPTER 3. METHOD 16 by implementing a packet filter that would use a network dump from Wire- shark as indata instead of a real network stream. This was deemed feasible as no focus had to go to design and implement a network driver. An area that was not within the problem definition.

It is also worth noting that the packet filter that we are implementing will only filter on IPv4 addresses and not any other address space. The reason that this choice was made was that IPv6 was not considered necessary to answer the thesis problem statement.

All coding has been done in Visual Studio 2013 and using C++ as the programming language of choice. The choice of C++ was based on it being one of the object oriented languages with a close link to hardware. It is also a language that stems from C, a language that is highly suited for use in network related programming. This is specially apparent when dealing with raw data such as, bits and bytes.

3.2.1 Implementing a pattern

For the main pattern the choice fell on Chain of Responsibility [1, 7]. This pattern uses a handler that passes requests along a chain of objects. One of these objects then takes responsibility for the request and handles it. The idea was that this design could be implemented in a packet filter by having each part of the chain representing a rule. A packet object would then be passed through the chain to receive an approval. With this design in mind the basis of the RuleEngine and RuleObject was constructed.

Later on in the development process a decision was made to adapt our

solution to meet the requirements of the security pattern "Packet Filter Fire-

wall" [4,6]. This design is also what the final code is based on.


Chapter 4 Results

The implemented packet filtering solution in this thesis is based on the prin- ciples of Design Patterns. To make the implementation achievable within the set time frame of this thesis, the solution had to read the packets from an input file consisting of a Wireshark Packet dump. This was a concious decision that was based on the complexity to access the network interface on windows 7/8 based systems. It should also be noted that filtering is only done on packets containing IPv4 data.




recieve packet



validatePacket() accept

send packet Packet

Sender PacketFilter RuleBase Rule Reciever

Figure 4.1. Sequence diagram for Packet Filter

The solution works by reading the indata and encapsulating it into a Packet object. This Packet object is then forwarded into the FilterEngine using the Validate(Packet packet) function. It is in turn further forwarded into a chain of rules using the ValidatePacket(Packet packet) function to start the verifica- tion process. If a packet is approved by a rule in the chain, a boolean with the value "true" will be returned. If it is rejected, a boolean with the value "false"

is returned instead. The packet filter will then either forward the packet to the receiver or drop it using the returned boolean value as a decision point. In the application the sender and receiver are represented by input and output files.

The final solution is based on the following three Design patterns.

Packet Filter Firewall This pattern is the main pattern for the appli-

cation. It give the general structure and basic functionality that is needed to

answer the defined problem statement. It also dictates the overall application



CHAPTER 4. RESULTS 19 Chain of Responsibility This pattern was originally thought to be the main pattern for the solution. But as we progressed further into the design iterations, it soon became apparent that this pattern was less suited then originally thought. Instead Chain of Responsibility was used to implement the rule structure and how they interacted with each other and the PDU.

Singleton This pattern is intended to keep the FilterEngine object to only ever be instantiated once. The thought behind this was to keep the Fil- terEngine unique so that there was no way to instantiate a second false filter engine. The instantiation of a second filter engine could in theory mean that the security that the application provides could intentionally or unintention- ally be circumvented.

Below the application components and objects will be described in more detail.

4.0.2 Packet Filter

The PacketFilter is written as the "main" class of the application. This class triggers the initialization of the FilterEngine Object. It also reads the input data and packets the data into Packet objects, PDU’s. These PDU’s are then forwarded into the FilterEngine to either be approved or rejected.

The Input data is a network packet dump file created by recording our own network traffic using Wireshark. In this file each packet is represented as a line of hexadecimal pairs. The file is read line by line were irrelevant information is discarded. The remaining data is then converted into a Packet object containing the binary representation of the packet. This information is stored as bytes in an unsigned char vector where each hexadecimal pair makes up one byte.

This class will, based on the FilterEngines approval, also perform the drop and forwarding task. In the effort to make the flow easier to follow and verify, the outdata was forwarded into either a "dropped packets" file or a "passed packets" file.

This class together with the in/out data stream, the FilterEngine and the

FilterRules make up the Packet Filter Firewall Security Pattern design that

can be seen below.



PacketFilter Sender


Reciever Packet

FilterEngine InitializeRules()


explicitRule defaultRule

validatePacket() setRules()

Figure 4.2. Packet Filter

4.0.3 Packet

The Packet object is the representation of indata. Its data is converted from hexadecimal pairs and then stored as byte units in a character vector. The Packet object provides a set of getter functions to fetch the data which in most cases is provided as raw data in the form of unsigned integers.

The reason the data is stored as bytes but provided as unsigned integers has to do with the structure of a network packet. It was more feasible to pinpoint the data needed using an offset of bytes. The unsigned integer provides data such as IP addresses and Port numbers, and is easy to manipulate using bitwise operations. These bitwise operations, such as Bitwise Shift and Bitwise And/Or, are especially well suited for handling and manipulating network data.

In the few cases that data was not provided as unsigned integers it was instead represented as text strings. This decision was made to make it easier to show data like IPv4 and IPv6 addresses as well as protocols for the user.

It is worth mentioning that the packet object in itself is not based on any

particular Design Pattern even though there are a few that might be fitting.



4.0.4 Filter Engine

The FilterEngine object is based on the Singleton Design Pattern. This is the part of the application that is responsible for initializing all the user defined filter rules as well as the default rule.

Each rule in the rules file is converted into a FilterRule object. Together all explicit rules and the default rule forms a chain structure based on the Chain of Responsibility Design Pattern.

The FilterEngine object functions by forwarding packet verification re- quests into the chain which is made up by all the filter rules. Each rule will in turn request the data from the Packet object and match it against its rule criteria.

A data packet will be forwarded as outdata if it manages to pass all the user defined rules in the chain and arrive at the default rule object.

4.0.5 Filter Rule

Each Rule object is created by the FilterEngine using the predefined rule file.

These rules, including the default rule, are stored in the FilterEngine in the form of a linked list. This structure is as explained earlier based on the Chain of Responsibility Design Pattern. Each of the Rule objects contain the data required to decide if a Packet object would either be approved or rejected. All rules except the default rule also contain a pointer to its successor rule.

The FilterEngine will start the packet verification process by passing a Packet object into the first Rule object in the chain. This object will then request the IP information by calling the Packet objects getter methods.

If the IP-version is 4 then the rule will apply the netmask to both its own IP address and that of the packet using bitwise operations. The results are then compared with each other to see if there is a match or not. But if the IP version is not 4 then the packet will be automatically passed, since the application is not built to handle IPv6 as explained in section.

If the rule finds that the packet contains data that does not match its own, it will forward the packet object deeper into the chain using its own knowledge of the successor rule.

This process will be repeated by each rule until the packet is either rejected

by a rule and returned with a boolean "false", or approved by the default rule

and returned with a boolean "true".


Chapter 5 Discussion

5.0.6 The results

During the course of this thesis we were able to successfully implement a simple packet filter that used Design Patterns in the design process. This packet filtering solution also fulfills the requirements predefined in background section 4.7 A simple packet filter. This is in our opinion further verified by using the Security Pattern Packet Filter Firewall. Security Patterns have in their nature the prerequisites to put the right solution to the right problem.

We are confident that this is what have been accomplished as well.

We also believe in that our assumption that the object oriented language C++ was well suited for the task of implementing our application.

We have as well been able to conclude that Design Patterns are well suited and provide well worth assistance during the software design process. They give developers the tools necessary to make correct and well informed design decisions. It is also our opinion that the use of patterns theoretically would lessen the maintenance work needed during the software life cycle. A notion that is supported in research when carefully documenting pattern usage is practised [13, p. 7]. Unfortunately the scope of this thesis does not delve deeper into how the use of patterns affects a software life cycle, but this might be a subject for further studies.

5.0.7 On overuse of Design Patterns and Singleton

This thesis also found that the usage of Design Patterns are not as easy and straight forward as we first believed. We found that one of the most difficult aspects with using Design Patterns was to identify which patterns to use and why to use them. To us it became apparent that the overuse of Design Patterns is a pitfall that programmers trying out Design Patterns for the first



CHAPTER 5. DISCUSSION 23 time might fall into. That is, forcing a Design Pattern into the solution just for the sake of using it. This can have an affect that is opposite to what is desired. The software might for example become less flexible and modular.

There are research that support this and points out how inexperience affects working with Design Patterns [13, p. 1]. Experience and knowledge are both very important in using Design Patterns optimally for software development.

In the solution designed in this thesis we feel that the use of the Singleton might be unnecessary. We think that this Design Pattern can even introduce obstacles that might force a redesign when the packet filtering solution is ex- panded with more complex functionality. An example from the book [8, p. 41]

is when you have a package or library that relies on a Singleton coupled within an application. You then either have to redesign your Singleton implemen- tation or replace it completely if the rules for accessing the package/library is changed. Another example is a study which deals with the problems that multiple instances of a Singleton object can cause during runtime [12]. We found that these both are issues that were not mentioned as drawbacks in the pattern’s definition [1, p. 127]. In our case, as well as in our opinion, it was rather inexperience than a flaw in the Singleton pattern, that lead us to include the pattern when it might not have been needed. Only further experi- ence with the pattern would give us more insight into the Singleton patterns uses and disadvantages.

5.0.8 Thoughts on our constrains and limitations

It should also be noted that because of the constraints of this thesis there was not time to implement the entire flow. We were not able to build the function that intercepts packets. Part of the reason for this was that it is complex to build this functionality in a windows 7/8 based system without prior knowledge.

For this thesis we opted to limit the solution to just filter packets using a packet dump from Wireshark as indata. The data is processed and the output is written to two different files. Which file is chosen is based on if a packet was dropped or not. This particular limitation also means that we have not been able to test our application in a live environment using live network data. However in our opinion this does not affect the outcome of this empirical study.

The limited scope of this thesis also means that we have not tested if

Design Patters assists the software developers to design for change. A more

complex study would have to be done comparing the amount of time spent

on refactoring and redesigning a software that were designed using Design

Patters, and one that was not.



5.0.9 The significance of our study

Even with the limitations to our study, the results bear high significance in our opinion in that Design Patterns fulfill a role in software development. It is a tool like any other that can be used right or wrong, but can truly help in the first case. This is of importance specially for people inexperienced with object-orientated programming. More experienced programmers can use Design Patterns to ease their work or as an additional tool to reach their goals.

Additionally we believe that there is need for more evaluation of Design

Patterns in empirical studies like ours. It provides further enlightenment and

understanding around Design Patterns to the software development commu-

nity. Something highly needed for the concept to be correctly used and the

optimal effect to achieved.


Chapter 6 Conclusion

In this thesis we successfully implemented a packet filter by using Design Patterns. With the help of Security Patterns we were able to verify that our solution fulfilled all the requirements of a simple packet filter.

With the tools given to us we believe that Design Patterns do help in the design phase and assists in making the correct design choices. Design Patterns give better structure to a program, potentially decreasing the main- tenance work during the software life-cycle and increase possibilities for further development.

We were also able to conclude that Design Patterns help in choosing the right solution to the right problem, even if our inexperience made us make mistakes. As such we do believe that even Design Patterns have an learning curve and further learning would have helped us using Design Patterns to their full potential.

The thesis was faced with several limitations. Because of time constrains we were not able to implement full network functionality. This means that our application was never tested in a live environment. We have also not been able to verify that Design Patterns actually do lessen the amount of maintenance work that is needed.

6.1 Further studies

The most interesting conclusion for us in this thesis is the wealth of further opportunities that patterns provide. In the section "Security Patterns" we implied how the Packet Filter Firewall pattern can be combined with further patterns to create an even more advanced firewall. Security Patterns would work together as modules to the application, each pattern increasing the over- all functionality in the direction of our choice. The Security Pattern could




then include Design Patterns on a lower level in the same way we used Chain

of Responsibility and Simpleton in our implementation. Such a work could

further affirm, or deny, our conclusion that Design Patterns is a feasible way

to implement a practical solution.



[1] Erich Gamma,Richard Helm, Ralp Johnson, John Vlissides, Design Pat- terns: Elements of Reusable Object-Oriented Software. Addison Wesley Pearson Education, 42nd printing, 2014.

[2] Dieter Gollmann, Computer Security. Wiley, 3nd edition, 2011.

[3] Clive Blackwell, Hong Zhu Cyberpatterns: Unifying Design Patterns with Security and Attack Patterns Springer, 2014

[4] Markus Schumacher, Eduardo Fernandez-Buglioni, Duane Hybertson, Frank Buschmann,Peter Sommerlad Security Patterns: Integrating Secu- rity and Systems Engineering John Wiley & Sons, Ltd, 2006

[5] Behrouz A. Forouzan TCP/IP Protocol Suite McGraw Hill, Third Edition 2007

[6] Markus Schumancher Firewall Patterns 2003


FirewallPatterns.pdf Last accessed: 2015-05-09

[7] Jason McC. Smith Elemental Design Patterns Addison-Wesley, 2012 [8] Joshua Kerievsky, J. B. Rainsberger Refactoring To Patterns Industrial

Logic, 2003

[9] Eduardo B. Fernandez, Markus Schumacher Security Patterns in Practice Designing Secure Architectures Wiley

[10] Stanley B. Lippman, Josée Lajoie, Barbara E. Moo C++ Primer Addison Wesley, Fourth Edition, 2009

[11] Jan Skansholm Java Direkt med Swing Studentliteratur, Femte Utgåvan, 2005



BIBLIOGRAPHY 28 [12] Mel O Cinnelde Design Patterns: The Devils in the Detail School of Computer Sceince and Informats, University of College Dublin,

20Paper%20Design%20Patterns.pdf Last accessed: 2015-05-09

[13] L. Prechelt and B. Unger A series of Controlled Experiments on De- sign Patterns: Methodology and Results

edu/viewdoc/download?doi= Last

accessed: 2015-05-09


Appendix A

Appendix A - Code

A.1 PacketFilter.cpp

1 #i n c l u d e <iostream>

2 #i n c l u d e " Packet . h "

3 #i n c l u d e " F i l t e r E n g i n e . h "

4 #i n c l u d e " F i l t e r R u l e . h "

5 #i n c l u d e <s t r i n g >

6 #i n c l u d e <fstream>

7 #i n c l u d e <iomanip>

8 #i n c l u d e <vector >


10 using namespace std;


12 /∗ This method w r i t e s the data i n t o the output f i l e s . ∗/

13 void Write( string s , string filename2 ) {


15 ofstream myfile;

16 myfile. open ( filename2 , ios : : app ) ;


18 myfile << s << endl ;

19 myfile. close ( ) ;

20 21 }


23 /∗ This method reads data from an iput f i l e . ∗/

24 void Read( string filename1 , bool cpy) {

25 string line;

26 string filename2;

27 ifstream myfile( filename1 ) ;


29 i f ( ! cpy ) {




30 i f ( myfile . is_open ( ) ) {

31 while ( getline ( myfile , line ) ) {

32 cout << line << endl ;

33 }

34 myfile. close ( ) ;

35 }

36 e l s e {

37 cout << " unable to open f i l e " << endl ;

38 }

39 }

40 e l s e {

41 cout << " Please ent er the t a r g e t filename : "

42 << endl ;

43 cin >> filename2 ;


45 i f ( myfile . is_open ( ) ) {

46 while ( getline ( myfile , line ) ) {

47 Write( line , filename2 ) ;

48 }

49 myfile. close ( ) ;

50 }

51 e l s e {

52 cout << " unable to open f i l e " << endl ;

53 }

54 }

55 }

56 57

58 /∗ Help method to p r i n t a char as 8 b i t binary number . ∗/

59 void PrintBinary(char c) {

60 unsigned char tmp = c ;

61 unsigned char mask = 0x80 ;


63 f o r (i n t i = 0 ; i < 8 ; i++) {


65 i f ( ( tmp & mask ) == 0x80 ) { cout << 1 ; }

66 e l s e { cout << 0 ; }


68 tmp = tmp << 1 ;

69 }

70 71 }


73 /∗ Helper method that converts a car to a hexadecimal ←- r e p r e s e n t a t i o n and s t o r e s in an 8 b i t char . ∗/

74 char ReadHex(char c) {

75 unsigned char tmp = tolower ( c ) ;


77 switch ( tmp ) {



78 case ' 0 ':

79 return 0x00 ;

80 case ' 1 ':

81 return 0x01 ;

82 case ' 2 ':

83 return 0x02 ;

84 case ' 3 ':

85 return 0x03 ;

86 case ' 4 ':

87 return 0x04 ;

88 case ' 5 ':

89 return 0x05 ;

90 case ' 6 ':

91 return 0x06 ;

92 case ' 7 ':

93 return 0x07 ;

94 case ' 8 ':

95 return 0x08 ;

96 case ' 9 ':

97 return 0x09 ;

98 case ' a ':

99 return 0x0a ;

100 case 'b ':

101 return 0x0b ;

102 case ' c ':

103 return 0x0c ;

104 case 'd ':

105 return 0x0d ;

106 case ' e ':

107 return 0x0e ;

108 case ' f ':

109 return 0x0f ;

110 d e f a u l t:

111 return 0xFF ;

112 }

113 }


115 /∗Method that loads the packed data i n t o a packet o b j e c t ∗/

116 Packet LoadPacket( string data_ ) {

117 Packet tmpPacket;


119 unsigned char c;

120 unsigned char c2;


122 i n t i = 0 ;


124 i n t lastPos = data_ . find_first_not_of (' | ', 0) ;

125 i n t pos = data_ . find_first_of (' | ', lastPos ) ;

126 while ( string : : npos != pos | | string : : npos != lastPos ) {



127 i f ( data_ . substr ( lastPos , pos − lastPos ) != " 0 ") {

128 c = ReadHex (char( data_ . at ( lastPos ) ) ) ;

129 c2 = ReadHex (char( data_ . at ( lastPos + 1) ) ) ;


131 c = c << 4 ;

132 c = c ^ c2 ;


134 tmpPacket. setPacketData ( c ) ;

135 }

136 lastPos = data_ . find_first_not_of (' | ', pos ) ;

137 pos = data_ . find_first_of (' | ', lastPos ) ;

138 }

139 return tmpPacket;

140 }

141 142

143 /∗Main∗/

144 i n t main( ) {


146 string dropped_data = " dropped_cap8 . txt ";

147 string passed_data = " passed_cap8 . txt ";

148 i n t input = 0 ;


150 FilterEngine∗ FilterEngine = FilterEngine−>Instance ( ) ;

151 FilterEngine−>InitializeRules ( ) ;

152 ifstream dataStream(" cap8 . txt ") ;


154 i f ( dataStream . is_open ( ) ) {

155 string data;

156 Packet PDU;

157 while ( getline ( dataStream , data ) ) {

158 i f ( ! data . empty ( ) ) {

159 i f ( data . front ( ) == ' | ') {

160 PDU = LoadPacket ( data ) ;

161 i f ( ! FilterEngine−>validate ( PDU ) ) {

162 Write(" Dropped Packet with SrcIP : " + PDU . ←-

getTextSrc( ) + " and DstIP : " + PDU . ←- getTextDst( ) , dropped_data ) ;

163 Write( data , dropped_data ) ;

164 Write("+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+", ←-

dropped_data) ;

165 }

166 e l s e {

167 Write(" Passed Packet with SrcIP : " + PDU . ←-

getTextSrc( ) + " and DstIP : " + PDU . ←- getTextDst( ) , passed_data ) ;

168 Write( data , passed_data ) ;

169 Write("+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+", ←-

passed_data) ;



170 }

171 }

172 }

173 }

174 }

175 }

A.2 FilterEngine.h

1 #pragma once

2 #i n c l u d e <vector >

3 #i n c l u d e " F i l t e r R u l e . h "


5 using namespace std;


7 c l a s s FilterEngine

8 {

9 p u b l i c:


11 s t a t i c FilterEngine∗ Instance ( ) ;

12 void InitializeRules( ) ;

13 unsigned i n t ProtocolStrToInt( string protocol_ ) ;

14 unsigned i n t IpToInt( string Ip_ ) ;

15 bool validate( Packet packet_ ) ;


17 protected:

18 FilterEngine( ) ;

19 ~FilterEngine ( ) ;


21 p r i v a t e:


23 s t a t i c FilterEngine∗ _instance ;


25 FilterRule ∗start ;

26 FilterRule ∗temp ;

27 FilterRule ∗rule_pointer ;


29 vector<FilterRule> Rules ;

30 31 } ;



A.3 FilterEngine.cpp


2 #i n c l u d e " F i l t e r E n g i n e . h "

3 #i n c l u d e " F i l t e r R u l e . h "

4 #i n c l u d e <sstream>

5 #i n c l u d e <iostream>

6 #i n c l u d e <fstream>

7 #i n c l u d e <iomanip>

8 #i n c l u d e <s t r i n g >

9 10

11 using namespace std;

12 13

14 FilterEngine: : FilterEngine ( )

15 {

16 FilterRule ∗start = NULL ;

17 FilterRule ∗temp = NULL ;

18 FilterRule ∗rule_pointer ;

19 }


21 FilterEngine∗ FilterEngine : : _instance = 0 ;


23 /∗ Creates a f i l t e r engine i n s t a n c e ∗/

24 FilterEngine∗ FilterEngine : : Instance ( ) {

25 i f ( _instance == 00) {

26 _instance = new FilterEngine;

27 }

28 return _instance;

29 }


31 /∗ Function that t r a n s l a t e s p r o c o c o l from s t r i n g to i n t ∗/

32 unsigned i n t FilterEngine: : ProtocolStrToInt ( string protocol_ ) {

33 34

35 i f ( protocol_ . compare ("ICMP") == 0) {

36 return 1 ;

37 }

38 e l s e i f ( protocol_ . compare ("IGMP") == 0) {

39 return 2 ;

40 }

41 e l s e i f ( protocol_ . compare ("TCP") == 0) {

42 return 6 ;

43 }

44 e l s e i f ( protocol_ . compare ("UDP") == 0) {

45 return 1 7 ;



46 }

47 e l s e i f ( protocol_ . compare ("OSPF") == 0) {

48 return 8 9 ;

49 }

50 e l s e i f ( protocol_ . compare ("ICMPv6") == 0) {

51 return 5 8 ;

52 }

53 e l s e {

54 return 0 ;

55 }

56 57 }

58 59

60 /∗ Function that t r a n s l a t e s an ip a d r e s s from s t r i n g to unsigned ←- i n t ∗/

61 unsigned i n t FilterEngine: : IpToInt ( string ip_ ) {


63 unsigned i n t ip;

64 unsigned i n t tmp;

65 66

67 string: : size_type lastPos = ip_ . find_first_not_of (" . ", 0) ;

68 string: : size_type pos = ip_ . find_first_of (" . ", lastPos ) ;

69 istringstream( ip_ . substr ( lastPos , pos − lastPos ) ) >> ip ;

70 while ( string : : npos != pos | | string : : npos != lastPos ) {

71 istringstream( ip_ . substr ( lastPos , pos − lastPos ) ) >> tmp ;

72 lastPos = ip_ . find_first_not_of (" . ", pos ) ;

73 pos = ip_ . find_first_of (" . ", lastPos ) ;

74 ip = ip << 8 ;

75 ip = ip ^ tmp ;

76 }


78 return ip;

79 80 }


82 /∗ Function to i n i t i a l i z e the r u l e s ∗/

83 void FilterEngine: : InitializeRules ( ) {


85 string filename_ = " r u l e s . txt ";

86 ifstream myfile;

87 string delimiter = " , ";

88 string line;


90 myfile. open ( filename_ ) ;

91 bool firstline = true;


93 while ( ! myfile . eof ( ) ) {



94 getline( myfile , line ) ;


96 i f ( ! firstline ) {


98 vector<string> tokenz ;

99 string: : size_type lastPos = line . find_first_not_of (←-

delimiter, 0) ;

100 string: : size_type pos = line . find_first_of ( delimiter , ←-

lastPos) ;


102 while ( string : : npos != pos | | string : : npos != lastPos ) ←- {

103 tokenz. push_back ( line . substr ( lastPos , pos − lastPos )←-

) ;

104 lastPos = line . find_first_not_of ( delimiter , pos ) ;

105 pos = line . find_first_of ( delimiter , lastPos ) ;

106 }


108 //add e x p l i c i t r u l e

109 unsigned i n t tmp[ 7 ] = {0 , 0 , 0 , 0 , 0 , 0 , 0 } ;


111 tmp[ 0 ] = ProtocolStrToInt ( tokenz . at ( 0 ) ) ;

112 tmp[ 1 ] = IpToInt ( tokenz . at ( 1) ) ;

113 tmp[ 2 ] = IpToInt ( tokenz . at ( 2) ) ;

114 tmp[ 3 ] = IpToInt ( tokenz . at ( 3) ) ;

115 tmp[ 4 ] = IpToInt ( tokenz . at ( 4) ) ;

116 istringstream( tokenz . at ( 5) ) >> tmp [ 5 ] ;

117 istringstream( tokenz . at ( 6) ) >> tmp [ 6 ] ;


119 rule_pointer = new FilterRule;

120 rule_pointer−>setRules ( tmp [ 0 ] , tmp [ 1 ] , tmp [ 2 ] , tmp [ 3 ] , ←- tmp[ 4 ] , tmp [ 5 ] , tmp [ 6 ] , f a l s e) ;


122 i f ( start == NULL )

123 {

124 start = rule_pointer ;

125 }

126 e l s e

127 {

128 temp−>nextRule ( rule_pointer ) ;

129 }

130 temp = rule_pointer ;


132 }

133 e l s e {

134 firstline = f a l s e;

135 }


137 }




139 unsigned i n t defaultRule[ 7 ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 } ;

140 rule_pointer = new FilterRule;

141 rule_pointer−>setRules ( defaultRule [ 0 ] , defaultRule [ 1 ] , ←- defaultRule[ 2 ] , defaultRule [ 3 ] , defaultRule [ 4 ] , ←- defaultRule[ 5 ] , defaultRule [ 6 ] , true) ;

142 temp−>nextRule ( rule_pointer ) ;


144 //temp = NULL;

145 myfile. close ( ) ;

146 }


148 /∗ This method sends the packet i n t o the f i r s t rule , and s t a r t s ←- the v a l i d a t i o n p r o c e s s ∗/

149 bool FilterEngine: : validate ( Packet packet_ ) {

150 return start−>validatePacket ( packet_ ) ;

151 }


153 FilterEngine: : ~ FilterEngine ( )

154 {

155 }

A.4 FilterRule.h

1 #pragma once

2 #i n c l u d e <s t r i n g >

3 #i n c l u d e " Packet . h "


5 using namespace std;


7 c l a s s FilterRule

8 {

9 p u b l i c:


11 FilterRule( ) ;


13 void setRules(unsigned i n t srcIP_, unsigned i n t srcNetmask_, ←- unsigned i n t dstIP_, unsigned i n t dstNetmask_, unsigned ←- i n t srcPort_, unsigned i n t dstPort_, unsigned i n t ←-

protocol_, bool pass_) ;

14 void nextRule( FilterRule ∗anotherRule ) ;


16 unsigned i n t getDstIP( ) ;


18 unsigned i n t getSrcIP( ) ;



19 bool validatePacket( Packet packet_ ) ;


21 ~FilterRule ( ) ;


23 p r i v a t e:

24 unsigned i n t srcIP;

25 unsigned i n t srcNetmask;


27 unsigned i n t dstIP;

28 unsigned i n t dstNetmask;


30 unsigned i n t srcPort;


32 unsigned i n t dstPort;


34 unsigned i n t protocol;


36 bool pass;


38 FilterRule ∗nextFilterRule ;


40 bool sendToNext( Packet packet_ ) ;

41 42 } ;

A.5 FilterRule.cpp

1 #i n c l u d e " F i l t e r R u l e . h "

2 #i n c l u d e " Packet . h "

3 #i n c l u d e <s t r i n g >

4 #i n c l u d e <iostream>


6 using namespace std;


8 FilterRule: : FilterRule ( )

9 {

10 11

12 FilterRule ∗nextFilterRule = NULL ;


14 unsigned i n t srcIP;

15 unsigned i n t srcNetmask;


17 unsigned i n t dstIP;

18 unsigned i n t dstNetmask;




Related subjects :