...

Wednesday, May 22, 2013

Computer Science 02

We will now look at Python, as we know previously as an Interpreted Programming Language.

A popular IDE (Integrated Development Environment) for Python is actually IDLE. IDLE consists of:
1) Text Editor - A place where the program can be typed and then sent to the Shell.
2) Shell - The actual environment that the Python code is interpreted.
3) Debugger - Useful for debugging, but most people use print statements.

Everything in Python is considered an Object. The Python code itself can be an Object. Each object has a Type. The Type determines what kind of object it is and what can we do with it.

Types can be two kinds:
1) Scalar - These are the primitive types of the programming language. They are indivisible types.
2) Non-scalar - Things that are divisible, for example, String, which can be divided into smaller 'str' of many chars.

The most common Scalar Types we work with are:
1) int - A real number.
2) float - An approximation of a real number.
3) bool - A true or false value.
4) NoneType - Representing a null.

An example of a Non-Scalar type is:

str - A string of characters.

In Python, we can type the literals (e.g. 3, 'a', '5.6) into the Shell and it would return that value. To check the type of a literal, we can use the type() function as such:
type(3)

This would tell us that 3 is an 'int' type.

Literals by themselves are useless. We cannot do much with it. What we can do, however, is to chain them together using Operands (values) and Operators to form Expressions.

In Python, when we deal with division, it is important to use floating point numbers. If we use "+" between two integers, 5+5, the "+" sign will act as an addition. If we use "+" between 'a' and 'b', we would get 'ab', because the "+" would act as concatenation when dealing with 'str'. This is because "+", like many other Operators, is Overloaded (dependent upon the types and parameters given to it).

We can do manual conversion as such, which is called Type Casting:
1) 'a'+str(3) gives you 'a3'
2) int(2.1) would truncate the float into an integer value of 2.

A Program in the Python sense is a synonym to a Script.

When typing a literal into the Shell, it prints the value directly to the screen. When things are executed in a Program, however, it will not be printed unless we use the print() command.
print 5

In order for things to work, it is important for us to have Variables. A Variable in Python is simply a name for an Object. To bind a Variable to an Object, we use the Assignment:
x=5

This assigns ("=") the int Object of value 5 to the Variable x.

The Function print() allows us to output things. We'll need to get inputs, and there are two types of input:
1) Raw Input (this is the only type that exists in Python 3.0)
2) Input

Raw Input always interprets what the user types as a 'str' type. We would need to do Type Casting:

x=int(input("Please enter an integer: "))
print("You entered "+str(x)+".")


The simplest programs are Straight Line Programs. Straight Line Programs are Programs where every line is computed exactly once, with no conditions or loops (which are referred to as "tests").

Conditional Statements are the simplest "tests". A conditional statement comprises of:
1) if
2) else
3) elif

A program where Conditional Statements are implemented is called a Branching Program. In a Branching Program, each statement is executed the most once.

In conditional statements, the indentation is extremely important. This is how a simple conditional statement is implemented:

x=int(input("Enter an integer: "))
if x%2==0:
    print("Even")
else:
    print("Odd")


Programs are intended to be readable, and by enforcing this, Python actually ensures some sort of code home-keeping.

Finally, we look at a Looping Construct which allows us to do Iterations. When we do this, we'll be able to create a Turing Complete Program.

Whenever we write a loop, we should have either an Incrementing or a Decrementing Function. This allows the loop a guarantee to exit.

The properties of a Decrementing Function is as such:
1) It will map a set of program variables to an 'int'.
2) It starts with a non-negative number.
3) The loop terminates when the value of the variable is <= 0.
4) It is decreased each time through the loop.

In a loop as seen here, there is in fact a Decrementing Function:

while a<25:
    a+=1


Even though all we can see is an Increment here, we can derive the Decrementing Function of:
25-a

Loops allow us to do something known as Exhaustive Enumeration, which we usually refer to as Bruteforce.

The for loop in Python is as such:

for x in range(0,25):
    instructions


In this case, range(0,25) actually creates a tuple with a sequence starting from 0 to 24.

Approximation in computing is finding a number that is accurate enough. It does not need to be perfect, but it must be close enough for our use. For example:

y^2=x+-epsilon

Where epsilon is the degree of error acceptable.

We would then be able to come up with a slow converging approximation algorithm as such:

x = 123
epsilon = 0.01
ans = 0
while abs(ans**2-x)>=epsilon and ans<=x:
    ans+=0.00001
print(ans," is close to sqrt of ",x)


The program is extremely dependent on size of the number given to test, and the maximum number of times it can loop can be calculated by x/0.00001.

A more effective algorithm exists to solve this problem. It is called the Bisection Search. It can be implemented by cutting the search space in half after each iteration. The worst case would be log(x) where x is the number of possible value of answers.

In this method, we first define the possible range of answers. We then try to guess the answer from the middle of the range. We then check if the answer when put through the formula gives us an answer near enough to what we want. If it's higher, then we search for a lower number. If it's lower, we search for a higher number. It is implemented as such:

x=5;
epsilon=0.00000001;
upperBound=x;
lowerBound=0.0;
ans=(lowerBound+upperBound)/2.0;
while abs(ans**2-x)>epsilon:
    if ans**2 > x:
        upperBound=ans;
    else:
        lowerBound=ans;
    if ans==(lowerBound+upperBound)/2.0:
        break
    else:
        ans=(lowerBound+upperBound)/2.0
    print(ans)
if abs(ans**2-x)>epsilon:
    print("Converged at",ans,"without meeting epsilon specifications of",epsilon)
    print("Resultant error is",ans**3-x)
else:
    print("Converged at",ans)


This Program does smart guesses at a range of values you give it. It terminates when it has converged to an answer or it's failed. However, this assumes that the answer lies between 0 to x, which means that for problems where the answer is outside this range, this could not solve it. That is a flaw of this method.

An example to observe this problem is when we try to search for numbers less than 1.0. For example, 0.5's square root is 0.707107, and if we look at the search space of 0 to 0.5, we'll never find it! We then observe this pattern that for every number that is less than 1, the highest answer is 1.0. Therefore, we can see that for the upper bound, we cannot have it less than 1. We can change our upperBound statement as such:

upperBound=max(x,1.0)

This could take the value of x, or 1.0, whichever is higher.

We typically want programs to do things with minimal coding. A smaller program is more efficient than a larger program who can do the same thing.

We can use Functions to help shorten code. A Function is something that provides:
1) Decomposition - It allows us to break our program up into modules. An example of a module is a Function and a Class. Modules should be self-contained and reusable.
2) Abstraction - Suppresses details that the programmer does not need to see. This allows the programmer to focus on what it does.

A simple function could be as such:

def accurateEnough(x, y, epsilon):
    return abs(x-y)<=epsilon


In order to use this Function, we invoke it as such:

print(accurateEnough(1,2,1))

Note that you must invoke this function below where it's been defined or it would not work.

A Function can contain:
1) Formal Parameters - are the names x, y and epsilon. You can use x in the main code and it would have nothing to do with the parameters used in the function, because it is self-contained. This is because upon entry of a function, a new Scope is created. A Scope is a mapping of names to objects. The parameter passed into the function during its call is called the Actual Parameter.
2) Return - It is a statement that causes the Function to return a value to wherever it is called. If no Return is specified, then the NoneType is returned.
3) Assert - The assert statement takes a bool value (resulting from a bool, expression or function) and stops the function if it evaluates to False, otherwise it continues.

We can create a more robust function with assert as such:

def accurateEnough(x, y, epsilon):
    assert epsilon>=0
    return abs(x-y)<=epsilon


This ensures that epsilon is a non-negative value before it continues.

What happens when we run a program:
1) The Interpreter will build a Scope, and it would find Object it sees in sequence and assigns the value of it to the Name (the Object can be a Function or a Variable, etc.).
2) If a Function is invoked, then the Interpreter would create a new Scope for it and begin executing it as in Step 1.
3) This will continue till the program reaches the end.

Each Scope is also called a Stack Frame. When we start the Program, we begin with the Main Scope. Then as we progress into Functions, we'll have Scopes adding to the top of the Stack. When we're done with the Function, its Scope gets popped from the top, and we return to the Scope of the previous Function or the Main Scope. We would eventually end up again with the Main Scope. This is because a Stack is FILO (Frst-In-Last-Out). We can use Variables defined in a Scope below its own Scope (e.g. a Function uses a Variable in the Main Scope). When a Function exits, its Variables and everything else in its scope are lost.

We now look at the 'str' type, which is the most common Non-Scalar type. A 'str' can be used as such:

sum=0
for x in str(1234):
    sum+=int(c)
print(sum)


What we get here is that the numbers 1234 is first converted into a 'str' of '1234'. For each item in the String, starting from 1, they are added to the total sum. In the end, we'll have the answer of 10.

We can deal with 'str' as if it's an array. Suppose that we have the following 'str':

helloStr = 'hello'

We can access the first character of the 'str' using:

print(helloStr[0])

The above code would give us a 'h'. We can also access a range of characters, as such:

print(helloStr[0:2])

This would print out the first (0) and second (1) char in the 'str'. This is a method known as a Slicing. It makes a new copy of the original 'str' (known as a Substring). There are also different operations that you can do with 'str' types, for example, to find patterns (and get the location of the provided pattern), we can use:

helloStr.find('lo')

We would get the output 3.

We'll now look at the following piece of code, which enables us to find patterns in a provided text:

#Finds patterns in Strings
providedString = input('Enter the text: ')
findString = input('Enter the pattern: ')
low = providedString.find(findString)
while providedString.find(findString,low)!=-1:
    print(providedString.find(findString,low),"to",low+len(findString))
    print(providedString[0:low]+'['+providedString[low:low+len(findString)]+']'+providedString[low+len(findString):])
    low=providedString.find(findString,low+1)


In this Program, we first get a String, and a Substring to search for. We have a 'low' value to indicate the last position from the last search. We find the first occurrence of the searched text, and print its start and end slice index of the providedString. Next, we print out the text, adding brackets between the found text. This repeats till no more occurrence is found.

Monday, May 20, 2013

Computer Science 01

Engineers are people who can map problems into computational frameworks.

A good computer scientist is someone who has the skills to make a computer do whatever they want it to do.

Let's start with the question... What is computation? To answer this, we first look at two kinds of knowledge:

1) Declarative - It is composed of statements of facts. It does not tell us how to arrive at a conclusion, but if a piece of declarative knowledge is correct, we can use it to test computations. An example of declarative knowledge is: "A chocolate cake is delicious".

2) Imperative - Imperative knowledge tells how to solve something. For example, a recipe for a chocolate cake is imperative knowledge.

We use the recipe to create a dish (Imperative Knowledge), and if the dish is indeed delicious, looks everything like the description of a chocolate cake (Declarative Knowledge) then we know we've made a chocolate cake.

Let's look at an approximation algorithm that lets us solve a square root. Say for example, we are looking for the value of sqrt(25).

We first get facts about the declarative knowledge we know of squares and their roots. It is as such:

g^2=x

We have x, we need to find g.

The approximation algorithm, a form of imperative knowledge, for obtaining the sqrt(x) is as such:
1) Guess a value g.
2) Compute the value of g^2.
3) If g^2 is x, or close enough to x, then g is the root of x.
4) Else, the next value of g will be (g+x/g)/2 (The average of g and x/g). Compute again from Step 2.

Programmatically, we write it like this:

while(math.pow(g,2)!=x)
{
    g=g+x/g;
}


When you get the value of g which when squared gives you x, it is said that the algorithm has converged.

An algorithm is made up of the following components:
Instructions - Operations that are carried out, e.g. "g=g+x/g"
Flow Control - The way and sequence the instructions are carried out.
Termination Condition - When are we satisfied with the answer, e.g. "g^2 equals x or is close enough to x"

There are two types of programs:

1) Fixed Program Computer - These computers are designed to do specific and fixed things. Instructions are hard-coded into circuitry (think logic gates in ASICs) and only input and output is considered data.

2) Stored Program Computer -The input, instructions and output are all considered data and are all stored alongside in memory. This allows infinite amount of flexiblity and programs can now produce programs. This is the current state of computers.

In the Stored Program Computer, people think of a computer as a Hardware Program, known as an Interpreter.

A basic Stored Program Computer has the following things:
1) Memory - Memory used for storing of data and program.
2) Control Unit - Interprets instructions from memory and turns it into a form that the ALU can understand.
3) Arithmetic Logic Unit - Accepts instructions from Control Unit, pulls and pushes data from Memory, computes and stores results in its Accumulator (the ALU's own Memory).
4) Input/Output - Allows interaction with external systems.

A British mathematician proved that there are 6 primitive instructions that can be used to do anything that can be done with the computer.

In Programming, we make use of a set of Primitive Instructions and a set of Flow Control. Using and combining these two elements, we can come up with different programs.

A Programming Language comprises of:
1) Syntax - Which sequence of characters and symbols constitute a well-formed string, e.g. g=5+6.
2) Static Semantics - Which well-formed strings have a meaning, e.g. 6+4 by itself is well-formed but does not have a proper meaning/purpose.
3) Semantics - What that meaning is. A program can have a proper syntax and proper static semantics, but it may mean differently from what the programmer wants it to do.

A program with improper semantics can:
1) Crash - The program stops running and shows an obvious sign that it's happened. A properly designed program environment will keep damages minimal and local (i.e. does not damage the program or system).
2) Never Stop - The program never finishes the job, which is also known as "Hang". These programs typically have entered an infinite loop due to a deadlock or semantics error.
3) Wrong Output - The program runs to completion, but produces the wrong answer. This is the worst kind of problem because people may think it's running fine and it isn't.

There are two types of Programming Languages:
1) Interpreted - Python, where the source code is executed directly and does not need to be compiled.
2) Compiled - Java, where a compiler changes source code into an object code, which is executed by the Hardware Interpreter.

Sunday, May 5, 2013

CCNA Review 04

You can see a plethora of different hardware in a typical network, but the most important two devices are the Switches and the Routers.

Switches were not like that from the start. In the past, everything was connected by network hubs. A hub is basically a repeater with multiple ports. Being a repeater, every device on the network actually shares the bandwidth available through it. Therefore, only one device can transmit at the same time. If more than one device transmits, then it is said that there is a collision.

To combat collisions, the CSMA/CD (Carrier Sense Multiple Access / Collision Detection) protocol is created which detects collisions whenever one happens. When two devices transmits at the same time, a collision is resulted and both devices would transmit a jam signal. The devices would back off for a random amount of time before transmitting again.

There are three types of RX/TX modes:
-Simplex is where the transmitter only transmits, and the receiver only receives. It is a one-way traffic. An example of simplex communication is radio broadcasting.
-Half-Duplex is when only one device can transmit across the wire at the same time. When one talks, all others sharing the medium must listen. An example of half-duplex communication is WiFi.
-Full-Duplex allows all devices to transmit at the same time. Modern switched networks and router interfaces are full-duplex.

The biggest problem with the hub is that it is a shared medium, and therefore it is half-duplex. If 5 devices are transmitting at the same time across a 50Mbps hub, then each of them have less than 10Mbps for transmission. In this case, an entire hub is a collision domain. The repeater and hub is a layer 1 device.

A new device came and allowed collision domains to be segmented. This is called the bridge. The bridge is an intelligent layer 2 device which allows learning of MAC addresses on each interface, much like a switch. Hubs can be connected to the bridges, allowing larger networks to be created. Each interface on the bridge is a collision domain if a hub is connected to it. If a computer is connected directly to a bridge, it has full duplex connectivity. However, the biggest problem with bridges is that they're software based, so they introduce really high latencies and limited bandwidth.

Switches were then created, which is much like a bridge, but moves frames around via ASICs. Every port on the switch is a full-duplex wire. If all ports are full-duplex, there can be no collision occuring on the switch. However, each switchport is still considered a collision domain by definition. Modern switches can support multiple speeds per interface and it is managed and intelligent. It is managed because you can modify settings, and it has a large feature-set and intelligence due to its IOS firmware.

Switches typically have one or two high-speed links for daisy chaining switches together. Switches need to be connected with crossover cables but modern switches have auto-sensing ports that allow connection through straight-through as well. Modern switches also have SFP (Small-Form Factor Pluggable Transceiver) modules which allow chaining together via Fibre Optics.

When switches are first booted up, its CAM (Content Addressable Memory) table is empty. CAM tables are used to store MAC address associations with interfaces. Once STP (Spanning Tree Protocol, covered in a later article) is completed and stable, the switches will start learning MAC addresses from its interfaces.

Suppose that two devices, A and B, connected to the switch wants to communicate. A would first create an ARP request to look for B. At this time, A's MAC will be recorded, while the ARP request is forwarded out of all ports. B would receive the ARP request and generate an ARP reply, which allows the switch to record the location of B's MAC. Now that the switch has both device's MACs, further communication from now would be switched at wire-speed.

By default, CAM entries has a timeout of 5 minutes. If a device stops communicating for 5 minutes, the entry is dropped. If A stops communicating for 5 minutes and his MAC gets dropped, further communication to A will be forwarded out of all open ports like a broadcast until his MAC is learned again.

CCNA Review 03

In this article we are going to talk about two of the most common transport layer protocols: UDP and TCP.

If the two protocols could talk, UDP would say, "I hope it gets there", while TCP would say, "I'll make sure it gets there".



UDP (User Datagram Protocol) is a connectionless protocol. It does not establish connections and packets sent by it has no guarantee of reaching the intended target. Therefore, UDP is unreliable. However, it has many practical uses due to its low overhead and is typically used in time-sensitive, real-time applications like VoIP where a dropped packet is not important but latency and jitter could render the whole protocol useless.



An example of a UDP protocol is DNS Client. The DNS Client is UDP not because of the time-sensitive nature but because everything fits into one packet and it makes no sense to have to establish a full connection with the 3-Way Handshake and the subsequent ACKs and termination just to send that one packet. If the request is dropped the client simply has to send another one after a timeout. Much more efficient than using TCP.

TCP (Transmission Control Protocol) is a connection-oriented protocol. Before the start of every transmission, there is a Three-Way Handshake that starts a session between the clients. The handshake consists of a SYN, SYN-ACK and ACK, which will be covered more in detail later. TCP requires ACK for messages, which allows dropped packets to be detected and resent. TCP is therefore reliable. However, due to the connection-oriented nature, it has costly overhead and is more suitable for applications that deal with large transfers that has a requirement for data integrity. TCP has a mechanism known as the TCP Sliding Window Protocol, which allows more efficient use of the acknowledgment system. This will be covered in greater detail later.



An example of TCP is the HTTP, where a 3-Way Handshake is first established before the client sends a GET message. Since web-browsing is data-integrity sensitive and bandwidth-heavy, TCP is the perfect protocol. Protocols like FTP use TCP for the same reason.

As previously mentioned, the Three-Way Handshake consists of a SYN, SYN-ACK, and an ACK. It is used to initialize a connection between two communicating hosts. The initiating host (in the case of a client accessing a web server) would first send a SYN 0 to the target. This is a good time to introduce the concept of sequence numbers, which TCP uses to track what's been received and what's not been received. The server would then reply with a ACK 1, stating that it has received 0 and is ready for 1. It would also send a SYN 0 along with it. Finally, the client sends a ACK 1.



At this point there would be a connection ready for data to be transmitted. The first HTTP packet would then be sent out.

The sequence number represents the amount of bytes sent out by the sender. The ACK number represents the sequence that it is ready to receive. This is particularly useful in implementing the TCP Sliding Window Protocol. To implement the Sliding Window, TCP first sends out one segment. Once it is successful, it would send more segment at one go (e.g. 2). If it is successful, it would send some more (e.g. 4), and so on. It would do so until it reaches the tolerance of the end-to-end devices and packets get dropped. It knows that packets get dropped when the ACK it receives is not what is expects. The next transmission would then start from that number of packets, and then from there it slowly increases.



The common TCP and UDP ports are:

TCP
21 - FTP (File Transfer Protocol)
22 - SSH (Secure SHell)
23 - Telnet
25 - SMTP (Simple Mail Transfer Protocol)
53 - DNS Server (DNS server-server communication)
80 - HTTP (Hyper-text Transfer Protocol)
110 - POP3 (Post Office Protocol 3)
443 - HTTPS (Hyper-text Transfer Protocol Secure)

UDP
53 - DNS Client (DNS client-server communication)
69 - TFTP (Trivial File Transfer Protocol)

Both protocols have 65535 distinct ports.
Well known ports are from 0 to 1023.
1024 to 49151 are registered ports.
Finally, 49152 to 65535 (215+214 to 216-1) are the dynamic/private ports.

Let us look at the previous examples we used again.



If A wants to visit a website on B, then this is going to happen.

Again, A would check if B is in the same network. It would realize that B is in a different network, so it needs to send it through its default gateway. It ARPs for the router's MAC and once it gets it, the following frame is created:

(v,w)
FCS (Created at the end)
SYN
S TCP - 58372 (Randomly generated)
D TCP - 80
S IP - A's IP
D IP - B's IP
S MAC - A's MAC
D MAC - R1's MAC

As the switch receives the frame, it would associate A's MAC to the interface, then forward it out of all ports because it does not know where the router is. When the router receives the frame, it would look deeper at the IP header and realize that it's intended for another network that it can reach by sending it to R2. It would replace the S and D MAC, recalculate the FCS, then send it out as:

(x)
FCS (Created at the end)
SYN
S TCP - 58372
D TCP - 80
S IP - A's IP
D IP - B's IP
S MAC - R1's MAC
D MAC - R2's MAC

Once F2 gets it, it would realize that it is intended for something connected to S2, so it sends it out of that interface like this:

(y,z)
FCS (Created at the end)
SYN
S TCP - 5837
D TCP - 80
S IP - A's IP
D IP - B's IP
S MAC - R2's MAC
D MAC - B's MAC

The switch learns that R2 is at that interface, then sends it out through all the other ports. B receives it, processes the IP header and realizes that it's for itself. Once it reaches the TCP header, it would realize that something is trying to initiate a connection to its port 80 (HTTP) from port 58372. It then replies with the following:

(y,z)
FCS (Created at the end)
SYN, ACK
S TCP - 80
D TCP - 58372
S IP - B's IP
D IP - A's IP
S MAC - B's MAC
D MAC - R2's MAC

The same process happens but the other way round, till A receives the SYN,ACK. It would then proceed to send an ACK. Thereafter, the HTTP connection would take place.

Saturday, May 4, 2013

CCNA Review 02

In this review article we are going to go back to revisit some of the network fundamentals that sums up the operation of the network from a bird's eye view.



An IP address is a Layer 3, Logical address that is 32-bits in length. As such, it can be represented in four dot-separated decimal octets with each octet having a value between 0 and 255. As IP addresses are used for end-to-end path determination, it must be universally unique (and as for private addresses, locally unique). An example of an IP address is:

192.168.1.1

IP addresses are typically coupled with a subnet mask. A subnet mask is a 32-bit mask, represented the same way as the IP address (in four dot-separated decimal octets). The most striking thing about the subnet mask is that it is made up of contiguous 1s, as such:

255.255.0.0 (Binary 11111111.11111111.00000000.00000000)
255.255.192.0 (Binary 11111111.11111111.11000000.00000000)
255.224.0.0 (Binary 11111111.11100000.00000000.00000000)

Subnet masks can be represented by its octet form, or more conveniently (and professionally), the CIDR format (Classless Inter-Domain Routing, but pronounced "sider"). The CIDR format is a representation of the number of 1s in the subnet mask. Using the same example:

255.255.0.0 (CIDR /16)
255.255.192.0 (CIDR /18)
255.224.0.0 (CIDR /11)

So far we've talked about how a subnet mask is represented but not what it does. A subnet mask is actually used to allow a host to know what network it is in, and whether another host it is communicating to is locally accessible (in the same network as itself) or foreign (requiring a router to reach).



The subnet mask in a router allows it to accurately build its routing table to reflect the actual networks that are available. For example, the 172.16.1.0/17 network and 172.16.1.128/17 networks may be at different places. Without the subnet mask (as per RIPv1), routers would assume its an address to its classful boundaries and wrongly reflect it as a 172.16.1.0/16 route.

For example, we have a host 192.168.1.10 with a subnet mask of 255.255.255.0. From this, we can tell that the host is in the 192.168.1.0 network by performing a logical AND between the host address and its subnet mask. It is the 10th host in the network.

Suppose that our host wants to reach 192.168.1.15. It would first perform the logical AND between the subnet mask and the target address. The result is 192.168.1.0, which it concludes to be in the same network.

If the host wants to communicate with 172.16.1.0, it would attempt to apply its own subnet mask to the address. In this case, he'll see it as 172.16.1.0 (which may not be the actual network that the host is in), and conclude that the target is outside its local network.

For communications in the local network, upon confirmation that the target is local, a host would send out an ARP request to resolve the target's MAC address. A MAC address is another type of addressing, 48-bits long, represented as a set of 12 hexadecimal characters. MAC formatting varies from pair-grouped (11-22-33-44-55-66) to quartet-grouped (1122-3344-5566). The delimiters vary typically between the period (.), colon (:) and the hyphen (-).

MAC is a Layer 2 (Ethernet) physical addressing that switches use to switch frames between its ports. Switches does not see the IP address. The MAC header contains the source and destination port, which allows switching of packets from point-to-point.

As previously mentioned, an ARP request is used to resolve a MAC address. Once the source host has the destination host's MAC address, communication through an Ethernet network can begin.



If on the other hand, the host discovers that the target is actually outside of its network, it would need to find a way to it. It would first check its internal routing table, and if there are no entries available, the request would be send through its default gateway. In this case, instead of ARP-ing for the target host, it would ARP for the MAC of the default gateway. The MAC is used as a means to get from point-to-point, and it changes as it passes through routers, but the IP address will remain the same end-to-end.

Notice that we've been talking about ARP. What exactly is ARP? ARP stands for Address Resolution Protocol, which is used to resolve a target's MAC from its IP. ARP contains four important fields, the SHA (Sender Hardware Address), SPA (Sender Protocol Address), THA (Target Hardware Address), TPA (Target Protocol Address). Suppose that A wants to communicate with B in a local network, A would need to find B's MAC using the following ARP Request.

Frame Header - MAC Source: A, MAC Destination: BROADCAST
SHA - A's MAC
SPA - A's IP
THA - IGNORED
TPA - B's IP

There are three common types of messages:
Unicast - One-to-One communication
Broadcast - One-to-All communication
Unicast - One-to-Group communication

All hosts would receive this request because it is a broadcast message and they would check if the TPA is referring to them. It would be dropped if it is not intended for them. Otherwise, it would send the following reply:

Frame Header - MAC Source: B, MAC Destination: A
SHA - A's MAC
SPA - A's IP
THA - B's MAC
TPA - B's IP
(Notice that SHA/THA are not the fields used for switching in the frame header).

Take a typical scenario:



Suppose that A wants to communicate with B. It would first check if B is in the same subnet as itself. If it is not, it would attempt to send the request through the router R1. Before it could do that, it would need to perform an ARP to find out the MAC of the router. Once that is done, the packet with the following header would be sent out. At point v, it would be as such:

Upper Layers and Data
Source IP - A's IP
Destination IP - B's IP
Source MAC - A's MAC
Destination MAC - R1's MAC
 The switch receives it and if it is the first time it is receiving the destination MAC (i.e. it doesn't know where the router is), it would send it out on all ports as if it were a broadcast. (The returning packet from the router would allow the switch to know its location later on) The packet exiting at wire w will be exactly the same as the one on v.

Each network is typically a broadcast domain. Networks are connected by switches, and daisy-chained switches. Routers are used to separate networks, so each interface of the router represents a broadcast domain. Routers are seen as separators that stop broadcast traffic from traversing between networks, which is really useful when dealing with large networks with large volumes of broadcast traffic.

Once the router receives it, it first checks that the MAC is intended for it. It begins processing the IP header and finds out that it is actually not the final recipient. It begins to check its routing table for the correct destination and either send it to a default route or the correct next-hop router. In this case, R1 will determine that R2 is the next hop. It rebuilds the frame's MAC header portion as such, leaving the other things intact:

Upper Layers and Data
Source IP - A's IP
Destination IP - B's IP
Source MAC - R1's MAC
Destination MAC - R2's MAC

R2 does the same and finds out that B's network is actually connected to it from the y wire. Therefore it forwards it out of that port after rebuilding the  MAC header as shown:

Upper Layers and Data
Source IP - A's IP
Destination IP - B's IP
Source MAC - R2's MAC
Destination MAC - B's MAC

If B hasn't communicated with the network before, the switch would again send it out as if it were a broadcast. B receives it and finds out that the MAC destination and IP destination is itself (the frame is intended for it), so it processes it further.



Since we're on the topic of IP addresses, let's talk about how IP is assigned to a host. There are two ways that a host can get an IP. The simplest but most non-scalable way is through static addressing. Static addressing is when a network administrator manually enters a static (unchanging) IP for each computer. Another way is to set up a DHCP server to perform dynamic IP address. The DHCP server automatically assigns IP addresses based on a range/pool that is allocated to it. Addresses are leased for a time period and if it is not used it will be taken back and reassigned to another client. The client requests it when it boots up / is connected to the network. It sends out a broadcast message requesting for DHCP and if a server is in the local network it would reply with an address.

However, because broadcast traffic is local to the network, would it therefore mean that there must be a DHCP server in every network? That could work, but there is something known as the "DHCP Relay" which allows certain broadcast messages in a subnet to be forwarded as a unicast to a DHCP server centrally managed elsewhere. In this case, the router can be set up as a DHCP Relay (via the "ip helper-address x.x.x.x" command, which will be reviewed in a later article). The DHCP server would then be set up with multiple pools, and it will assign an address (send it back to the router) based on the source interface the DHCP Relay is sending from.



A single host can have one or multiple NICs with one or multiple IP addresses per NIC connected to one or multiple networks. This is known as multihoming and allows separation of services on a single server or load balancing in the case of multiple NICs.

IP addresses come in three common classes, and two more uncommon classes. Class of the address is determined by the first octet. The classes are:
A - 1-127.x.x.x
B - 128-191.x.x.x
C - 192-223.x.x.x
D (Multicast) - 224-239.x.x.x
E (Experimental) - 239-255.x.x.x

Addresses can be public or private. Public addresses are Internet routable and it is registered/assigned by the IANA. Private addresses are freely usable but must be translated through NAT/PAT before it can be routed into the Internet (reviewed in a later article).

Private addresses blocks are allocated as shown:
A - 10.0.0.0/8 (10.0.0.0 to 10.255.255.255)
B - 172.16.0.0/12 (172.16.0.0 to 172.31.255.255)
C - 192.168.0.0/16 (192.168.0.0 to 192.168.255.255)

There are also special address ranges to note:
127.0.0.0/8 is reserved for Loopback addresses, but typically only 127.0.0.1 is used widely.
169.254.0.0/16 is reserved for autoconfiguration addresses when a host is unable to obtain an IP address from a DHCP server.

Cisco's guidelines for a network is 500 maximum hosts or the broadcast messages will be too much to handle. Subnetting is used to split large networks into smaller, manageable ones. For example, if we are given a 192.168.1.0/24 network, we can make four /26 networks as shown:

192.168.1.0/26
192.168.1.64/26
192.168.1.128/26
192.168.1.192/26

This process is known as subnetting, which would be covered in a future article.

Friday, May 3, 2013

CCNA Review 01

It's been quite some time since I last wrote an article and since it's time for recertification, I think it's a good chance to start reviewing on the basics again.

What is a network, again? Network engineers are just like road builders. We've been building these roads since the start of time, and through new technologies we build bigger and faster roads. As a network engineer, our goal is to make these roads as fast and efficient as possible.



Hardware can be made by anyone. Companies can make really fast routers and other hardware, but what makes Cisco stand out is their operating system; the IOS (Internetwork Operating System). Companies are now making their software appear and behave more like IOS, which makes Cisco certification more and more valuable.

Let's now talk about what makes a basic everyday network. The common hardware components involved in modern networks are:

1. Switch - The switch provides local area connectivity. All devices plugged into a switch reside in the same LAN. The LAN provides the most basic form of network communication, allowing sharing of resources (think of resources as data, servers, printers, and so on).



2. Router - Routers are used to interconnect LANs. A router marks the dividing line between networks. The main purpose of routers is to allow communication between networks, but they also provide services like NAT and basic security.



3. WAP - Wireless Access Points allows wireless connectivity (through the 802.11 series of standards). The biggest challenge of WAP in the past was security, but modern security protocols are now secure enough to be implemented in enterprise settings. However, wired access is still the preferred mode of communication for its speed, reliability and relative security.



4. Clients and Servers - These are the actual users of the network.



Network equipment are usually of standard sizes called Rack Units. Racks and equipment have RU ratings. A 24 RU rack can hold 8 switches of 3 RU. Racks typically have attached patch panels, which aid in cable management and organization.



The most common type of LAN is the Ethernet LAN. The most common Ethernet LAN cable is Cat 5e. These cables terminate with an RJ-45 connector. Cat 5e cables consists of 4 twisted pairs, and if crimped properly in the correct order, create an RF insulation field which allows maximum speed connectivity up to 100m. The common cable wirings are: Straight, Crossover and Rollover. The two standards for wiring are T568A and T568B.



Fiber is now more prominent in our everyday networks with the introduction of OpenNET. Fibers make use of light to communicate, which are much less prone to interference. These cables come in Single- and Multi-Mode types. The Single-Mode fibers are glass fibers which allows transmission of light across miles before requiring regeneration/repetition. The bandwidth allowed on each fiber cable is extremely high due to the number of ways we can exploit light, and newer light modulation techniques are being constantly designed.



In some older commercial networks we could encounter serial connections. Routers are connected to a CSU/DSU connected to wall ports, which is akin to a modem for serial connections. These are slowly being replaced by Ethernet fiber.



When we talk about data speeds in network, we need to know the units of data size. The smallest unit of representation is a bit, which has two states (0 or 1). When you put 8 bits together, you get a byte, which is equivalent to an ASCII character. A kilobyte is a 1024 bytes. A megabyte is 1024 kilobytes. Following the megabyte is the gigabyte, terabyte, petabyte, exabyte, zettabyte, yottabyte, brontobyte and gyopbyte. The world had 160 exabyte of data in 2006, 500 exabyte in 2009, and in 2012 the world was estimated to have 2.7 zettabytes of data.



When we look at data size, we usually talk in bytes. However, when referring to data rates, we usually talk in bits. A 100Mbps connection is actually a 12.5MBps connection. In simple mathematics, assuming 10% overhead (files are typically chopped into packets of 1500 Bytes, which is encapsulated with header overheads), to send a 100MB file over the network, we'll take...

100MB/(100*0.9/8) = Approximately 8.9 seconds.

When we go into networking, we need to be able to abstract the functions of devices into different groups. The standard architecture to describe network communications is the OSI Model. It is a standard to create standards. This abstraction allows interoperability, and implementation of compatible protocols.

OSI used to be a protocol, instead of just a model. It was developed in 1977 to compete with the TCP/IP stack. OSI was much better, but TCP/IP was chosen as the industry standard because of the difficult address scheme. The OSI's addressing scheme is actually similar to IPv6, which was created because IPv4 address space is running out.



The OSI model has 7 layers:
7. Application
The application layer is where the simplest form of data is created. API's reside on the application layer to handle the top 3 layers, which allows the programmers to focus on his program and less on the way the actual mechanics involved in sending data.

6. Presentation
Formatting and cryptography is part of the presentation layer. It defines how to format data (such as a picture, video, sound, or other data) into standard and generic format recognizable by the receiving end.

5. Session
This handles the entire session of access, which may comprise multiple connections.

4. Transport
The two most prominent transport protocols are the TCP (connection-oriented and reliable) and UDP (connectionless and unreliable). TCP is used when the integrity of data is important, while UDP is used for realtime applications where time is sensitive. This allows application/service separation through ports.

3. Network
It provides logical addressing and routing. Path determination is performed in the network layer which allows traversing of packets across networks.

2. Data Link
It is required for local communication in LANs and devices in the same subnet.

1. Physical
This describes the actual signals and hardware required to transmit these data. These include the hardware boxes itself, the cables or wireless signals, etc.



For data to be sent, it is encapsulated, which means it moves down the OSI Layer starting from Application. The application first creates the request, which is passed to be formatted by the presentation layer. The session is then established in the local computer. The transport layer then creates a logical connection through a transport protocol (e.g. TCP) which opens a source port (Registered/Dynamic 1024 to 65535) on the local system destined for a known open destination port of the target system (e.g. Port 80 if you're accessing a web server, and port 443 for secure connections). The data is then chopped into small TCP segments with TCP headers, then encapsulated with an IP header (with source and destination IP and other information) in the network layer to become a packet. Finally, the data encapsulated with an Ethernet header (source and destination MAC  addresses and other information) to become a frame.  At Layer 1 it is transmitted into the network.

Monday, November 7, 2011

Misc 52

It's been such a long time since I've come up with an article that I find it hard to name this one. It seems miscellaneous anyway, so I'll name it that way.
This article is about using port-mirroring with Linux iptables for purposes such as Sniffing, IDS Monitoring and so on.

For this article, I'm going to show you how to capture DNS requests made by an application on an Android phone. Sounds difficult, but with sniffing, you can finish this task in less than 5 minutes!

First, you need to get on the Linux box (via Telnet or whatever) doing the routing. (Well, I'm technically on a WRT160NL running DD-WRT, so it is a Linux box)

We'll need to enter the following commands:
iptables -t mangle -A PREROUTING -s 172.16.1.139 -j ROUTE --tee --gw 172.16.1.150



In this case, 172.16.1.139 is the phone's IP address, while 172.16.1.150 is the IP of the system doing the sniffing. The above command redirects traffic coming FROM the phone.

In iptables, a packet goes through the following tables:
1) Filter
2) NAT
3) Mangle

Filter is for filtering of unwanted packets, NAT is for address translations, and Mangle is for final modification of packets (for things like QoS or mirroring).

Visit here to have a clearer idea of how the packet is routed.

The ROUTE target is an experimental target that performs routing in the mangle table. The -tee parameter specifies to MIRROR a packet, and the -gw parameter specifies the gateway to send it through.

Here is the documentation for the ROUTE target

Next, if we're interested in the return traffic, we can also enter the following commands:
iptables -t mangle -A POSTROUTING -d 172.16.1.139 -j ROUTE --tee --gw 172.16.1.150

If we are interested in ALL traffic, we can omit the -d and -s parameters.

Now we can fire up Wireshark and do some sniffing. First, we'll need to select the right interface for sniffing. Mine is quite obvious:



Now, as we are interested in DNS traffic in this scenario, we'll use the filter:
ip.addr == 172.16.1.139 && udp.port == 53

Go generate the request in your phone. Lo and behold, as if black magic, you now know the DNS names your phone applications are connecting to.



From here you can do what you want. Let's say you want to find out what port the phone is accessing and what type of traffic goes through. No problem, just scroll down and look for the line where the answer comes back in (usually one line after the request).



We'll then use the following filters:
ip.addr == 1.2.3.4 && tcp.flags.syn == 1

Of course, replace 1.2.3.4 with the response address. You'll get something like this:



In our case, it's port 8300 we're looking for!

Of course, this is not where we stop. Remember, the extra rule takes up extra CPU cycles. When you're done, remember to remove everything using:
iptables -t mangle -D PREROUTING -s 172.16.1.139 -j ROUTE --tee --gw 172.16.1.150
iptables -t mangle -D POSTROUTING -d 172.16.1.139 -j ROUTE --tee --gw 172.16.1.150
<