;----------------------------------------------------------------------------
; SLIP COMMUNICATION HANDLER
; Intel 386-based
; Receiver and Transmitter ISR
;
; * Thesis Project *
; M. Lutfi Shahab 13389011
; Department of Engineering Physics
; Institut Teknologi Bandung
; (c) Bandung, 1995
;
; First made: March 1995
; Last upated: 4-Jan 1996
;----------------------------------------------------------------------------
;
;
; 26/7/95 I found a bug on ISR. ISR should push flags to stack, but
; in older version, this didn't!
; I observed this bug affected keyboard flag checking
; 11 Nov 1995 In next version I plan to use extended USART controller,
; like Intel 82510 and 16550
; Detecting these chips done with writting appropriate setting
; code to FCR (FIFO control register) and detects their presences
; in extended fields of IIR (Interrupt Control Register).
; 8 Jan 1995 16 bit Cyclic Redundancy Check added.
;
;-----------------------------------------------------------------------------
;IFDEF TASM
PAGE 60, 120
;ENDIF
MODEL large, C
MASM
DEBUG EQU 0 ; debug
INCLUDE PIC.ASH
INCLUDE SLIP.ASH
.DATA
EXTRN base :WORD
EXTRN queue :tQUEUE
EXTRN baudrate :DWORD
EXTRN int_no :BYTE
EXTRN thr :WORD
EXTRN rdr :WORD ; base
EXTRN ier :WORD ; = base+1
EXTRN iir :WORD ; = base+2
EXTRN lcr :WORD ; = base+3
EXTRN mcr :WORD ; = base+4
EXTRN lsr :WORD ;
EXTRN msr :WORD ; = base+6
EXTRN scp :WORD ; scratch pad = base + 7
EXTRN installed :WORD ; initialization flag
EXTRN imr :WORD
EXTRN rcv :tCOMBUF
packet_sem DW 0
xmit_time DW 200 ;timeout
rcv_time DW 200
timeout DW 200
recv_pkt_ready DW 0
IF DEBUG EQ 1
isr_msg DB 'Ini di dalam recv_isr', 10, 13, '$'
isr_in_sema db 'Semaphore > 0', 10,13,'$'
ENDIF
.CODE
; This variable must be put in CODE SEGMENT
in_recv_isr DW 0
IF DEBUG EQ 1
;-------------------------
; al = charactrer to print
;-------------------------
print PROC NEAR
PUSH ax bx cx dx ds es si di bp ; Turbo Assembler's macro
mov bh, 0
mov bl, 07h
mov ah, 0eh
int 10H
POP bp di si es ds dx cx bx ax
RETN
print ENDP
;---------------------
; dx => offset string
;---------------------
print_msg PROC
PUSH ax bx cx dx ds es si di bp
ASSUME ds:@data
mov ax, @data
mov ds, ax
mov ah, 9h
int 10H
POP bp di si es ds dx cx bx ax
RET
print_msg ENDP
ENDIF
xmit PROC NEAR
retn
xmit ENDP
;--------------------
send_char PROC NEAR
PUSH ds dx cx
xchg ah,al ; put data char into ah
push ax
ASSUME ds:@data
mov ax,@data ; resetting ds to DGROUP
mov ds, ax
pop ax
xor cx,cx ; 64K retry counter
sendch1:
mov dx, [lsr]
in al, dx
jmp $+2 ; use time, prevent overdriving UART
jmp $+2
test al, LSR_THRE ; Transmitter (THRE) ready?
jnz sendch2 ; nz = yes
loop sendch1
stc ; carry set for failure
jmp short sendch3 ; timeout
sendch2:
xchg al, ah ; now send it
mov dx, [thr]
out dx, al ; send the byte
jmp $+2 ; use a little time
clc ; status of success
sendch3:
POP cx dx ds
RETN
send_char ENDP
; ------------------------------------------
; int _Send_SLIP_Packet(tSLIP_Pkt *pkt)
; ------------------------------------------
PUBLIC C _Send_SLIP_Packet
_Send_SLIP_Packet PROC C pkt:DWORD
;--------- Turbo Assembler automatically set stack frame
PUSH ds si
sti ; enable interrupts
lds si, pkt
;-------- MODIFIED because CRC16 addition ($LTF$, 8/JAN/95)
;mov cl, ds:[si].datalen
;xor ch, ch
;cmp cx, DATASIZE
;jle LESS_OR_EQU
;mov cx, DATASIZE ; align to DATASIZE
mov cx, PKTSIZE
LESS_OR_EQU:
;---add cx, 4 ; total packet length =
; sizeof(pktlen)+sizeof(datatype)+sizeof(crc)
; = 1 + 1 + 2 = 4 bytes
cld
mov al, FR_END ; Flush out any line garbage
call send_char
jc send_pkt_end ; c = failure to send
; Copy input to output, escaping special characters
send_pkt_1:
lodsb
cmp al, FR_ESC ;escape FR_ESC with FR_ESC and T_FR_ESC
jne send_pkt_2
mov al, FR_ESC
call send_char
jc send_pkt_end
mov al, T_FR_ESC
jmp short send_pkt_3
send_pkt_2:
cmp al, FR_END ;escape FR_END with FR_ESC and T_FR_END
jne send_pkt_3
mov al, FR_ESC
call send_char
jc send_pkt_end
mov al, T_FR_END
send_pkt_3:
call send_char
jc send_pkt_end
loop send_pkt_1 ; do cx user characters
mov al, FR_END ; terminate it with a FR_END
call send_char
jc send_pkt_end
mov ax, 1 ; success
jmp short keluar
send_pkt_end:
xor ax, ax ; error occured
keluar:
POP si ds
RET
_Send_SLIP_Packet ENDP
;------------------------------------
; static void near asyrxint(void)
; return:
; - packet_sem
; - recv_pkt_ready
;------------------------------------
asyrxint PROC NEAR
push ds ; save ds register
ASSUME ds:@data
mov ax, @data ; ds points to DGROUP !
mov ds, ax
mov ax, WORD PTR [rcv.buf_end+2] ; just check !!
xor bx, bx
cmp WORD PTR [baudrate+2], 0
jb short asyrxint_a
jbe check_again
jmp short asyrxint_a
check_again:
cmp WORD PTR [baudrate], 9600 ;below 9600 we're strictly
jb asyrxint_a ;interrupt driven
mov bx, rcv_time
asyrxint_a:
les di, DWORD PTR [rcv.head]
xor bp, bp ; set flag to indicate 1st char processed
mov si, packet_sem ; optimization
mov ah, LSR_DR
asyrxint_again:
xor cx, cx ; initialize counter
mov dx, [lsr]
asyrxint_in:
in al, dx ; check for data ready
test al, LSR_DR
jnz asyrxint_gotit ; yes - break out of loop
inc cx ; no - increase loop counter
cmp cx, bx ; timeout?
jae asyrxint_exit ; yes - leave
jmp asyrxint_in ; no - keep looping
asyrxint_gotit:
mov dx, [rdr]
in al, dx
; Process incoming data;
; If buffer is full, we have no choice but to drop the character
;
; segment of rcv.head and rcv.tail is same !!
; so just compare their offsets
cmp di, WORD PTR [rcv.tail]; is it buffer collision ?
jne asyrxint_ok ; none - continue
or si, si ; maybe - if there are packets
jnz asyrxint_exit ; yes exit
asyrxint_ok:
stosb
cmp di, WORD PTR [rcv.buf_end] ; did we hit the end of the buffer?
jne asyrxint_3 ; no.
mov di, WORD PTR [rcv.buf] ; yes - wrap around.
asyrxint_3:
cmp al,FR_END ; might this be the end of a frame?
jne asyrxint_reset ; no - reset flag and loop
inc si ; yes - indicate packet ready
cmp si, 1 ; determine if semaphore is <> 1
jne asyrxint_chk_flg ; yes - recv_frame must be active
inc recv_pkt_ready ; no - set flag to start recv_frame
IF DEBUG EQ 1
mov al, 'O'
call print
ENDIF
asyrxint_chk_flg:
cmp bp, 0 ; was this the first char?
jne asyrxint_1 ; no - exit handler
asyrxint_reset:
inc bp ; set 1st character flag
jmp asyrxint_again ; get another character
asyrxint_exit:
asyrxint_1:
mov WORD PTR [rcv.head], di ; set offset pointed by rcv.head
mov [packet_sem], si
exit:
pop ds
RETN
asyrxint ENDP
;--------------------
; registers used:
; ax, ds
;
;--------------------
recv PROC NEAR
recv_2:
push ds
mov ax, @data
mov ds, ax
mov dx, [iir]
pop ds
in al, dx ;any interrupts at all?
test al, IIR_IP
jne recv_1 ;no.
and al,IIR_ID
cmp al,IIR_RDA ;Receiver interrupt
jne recv_3
call asyrxint
jmp recv_2
recv_3:
recv_5:
; process IIR_MSTAT here.
; If CTS and packet ready then
; enable the transmit buffer empty interrupt
; else
; disable the transmit buffer empty interrupt
;
cmp al, IIR_MSTAT
jne recv_1
push ds
mov ax, @data
mov ds, ax
mov dx, [msr]
pop ds
in al, dx
test al, MSR_CTS ; is CTS bit set
jz recv_5_1 ; no - disable xmit buffer empty int
jmp recv_2
recv_5_1:
jmp recv_2
;process IIR_RLS here
recv_1:
RETN
recv ENDP
;-------------------------------------------
; recv_char
; si = receive buffer = FP_OFF(rcv.tail)
; bx = receive count
; ds = data segment
; return:
; al = next char
; bx = pointer rcv.head
; zero flag:
; nz (0) : character received
; zr (1) : no more chars in this frame
;-----------------------------------------
recv_char PROC NEAR
push ds ; we assume that data segment has been set
mov ax, WORD PTR [rcv.tail+2]
mov ds, ax
lodsb
pop ds
cmp si, WORD PTR [rcv.buf_end]
jne recv_char_1
mov si, WORD PTR [rcv.buf]
recv_char_1:
mov bx, WORD PTR [rcv.head]
cmp si, bx ; if ((rcv.tail==rcv.head)|| //buffer collision
je recv_char_2 ; (_AL==FR_END))
cmp al, FR_END ; return (1);
; else return (0);
recv_char_2:
RETN
recv_char ENDP
;------------------------------
; recv_copy
; on entry:
; ds:si = packet_buffer
; cx = packet length
; do copy packet_to queue.write
;------------------------------
recv_copy PROC NEAR
les di, DWORD PTR [queue.write]
mov ax, es
or ax, di
jz fail
ulang:
rep movsb
mov WORD PTR [queue.write], di ; points to next entry list
fail:
RETN
recv_copy ENDP
;---------------------------------------
; INTERRUPT SERVICE ROUTINE
; almost all registers used, so
; we must save all of those.
; use register variables as possible
; because accesses to memory variable
; consuming much more time
;----------------------------------------
.CODE
PUBLIC C dummy_isr
dummy_isr PROC FAR
PUSH ax bx cx dx ds es si di bp
pushf
ASSUME ds:@data
mov ax, @data
mov ds, ax
mov al, [int_no] ;get hardware int #
add al, TMREOI ; make specific EOI dismissal
out BASE8259, al
popf
POP bp di si es ds dx cx bx ax
iret
ENDP
PUBLIC C recv_isr
recv_isr PROC FAR
;jmp short start
;in_recv_isr DW 0
start:
cmp cs:[in_recv_isr], 0
je no_re_enter
iret
no_re_enter:
PUSH ax bx cx dx ds es si di bp
pushf
mov cs:in_recv_isr, 1
ASSUME ds:@data
mov ax, @data
mov ds, ax
mov al, int_no ; Disable further specific device interrupt
call maskint
COMMENT *
I realize this re-entrancy trap is not perfect, you could be re-entered
anytime before the above instruction. However since the stacks have not
been swapped re-entrancy here will only appear to be a spurious interrupt.
*
;----------------------- CALL TRANSMITTER -----------------------
call xmit
;----------------------------------------------------------------
COMMENT *
; The following comment is wrong in that we now do a specific EOI command,
; and because we don't enable interrupts (even though we should).
;
; Chips & Technologies 8259 clone chip seems to be very broken. If you
; send it a Non Specific EOI command, it clears all In Service Register
; bits instead of just the one with the highest priority (as the Intel
; chip does and clones should do). This bug causes our interrupt
; routine to be reentered if:
; 1. we reenable processor interrupts;
; 2. we reenable device interrupts;
; 3. a timer or other higher priority device interrupt now comes in;
; 4. the new interrupting device uses a Non Specific EOI;
; 5. our device interrupts again.
; Because of this bug, we now completely mask our interrupts around
; the call to "recv", the real device interrupt handler. This allows us
; to send an EOI instruction to the 8259 early, before we actually
; reenable device interrupts. Since the interrupt is masked, we
; are still guaranteed not to get another interrupt from our device
; until the interrupt handler returns. This has another benefit:
; we now no longer prevent other devices from interrupting while our
; interrupt handler is running. This is especially useful if we have
; other (multiple) packet drivers trying to do low-latency transmits.
;
; The following is from Bill Rust, <wjr@ftp.com>
; this code dismisses the interrupt at the 8259. if the interrupt number
; is > 8 then it requires fondling two PICs instead of just one.
*
mov al, [int_no] ;get hardware int #
cmp al, BASEVEC ; see if its on secondary PIC
jg recv_isr_4
add al, TMREOI ; make specific EOI dismissal
out BASE8259, al
jmp short recv_isr_3 ; all done
recv_isr_4:
add al, 060H - BASEVEC ; make specific EOI (# between 9 & 15).
out 0a0H, al ; Secondary 8259 (PC/AT only)
mov al, 062H ; Acknowledge on primary 8259.
out BASE8259, al
recv_isr_3:
;-------- save packet data to buffer
call recv
cmp [recv_pkt_ready], 1 ; is a packet ready?
je ready ; yes, start read
jmp recv_exit ; no - skip to end
ready:
mov [recv_pkt_ready], 0 ; reset flag
sti
;===================== BEGIN DEPACKETIZE DATA HERE ======================
recv_frame:
cmp [packet_sem], 0 ; should we do this?
jne sema ; yes - process it
jmp next_sema ; no (packet_sem==0) => exit
sema:
mov bx, WORD PTR [queue.last]
cmp WORD PTR [queue.write], bx
jne not_full
;-------
; if queue.write reach queue.last, we have no choice thus just return
;-------
recv_frame_full:
mov [queue.status], QFULL
next_pkt:
mov [recv_pkt_ready], 1
jmp recv_exit
not_full:
mov si, WORD PTR [rcv.tail] ; get tail pointer
xor cx, cx ; count up the size here.
;---------- debug only, not needed int final linking
IF DEBUG EQ 1
mov bx, ds
mov dx, WORD PTR [rcv.tail+2]
mov ds, dx
mov ax, ds:[si]
mov ds, bx
mov al, 'A'
call print
ENDIF
;--------
;---- find how long message in the packet is
recv_frame_1:
call recv_char ; get a char.
je recv_frame_2 ; go if no more chars (al==FR_END)
cmp al,FR_ESC ; an escape?
je recv_frame_1 ; yes - don't count this char.
inc cx ; no - count this one.
jmp recv_frame_1
;--- now cx contains message length
recv_frame_2:
jcxz recv_frame_3 ;no data in packet? yes - free the frame
les di, DWORD PTR [queue.write]
mov ax, es
or ax, di
jnz trail_recv
xor cx, cx ; if (queue.write==NULL)
jmp recv_frame_3 ; queue.write[0] = 0 //force packet length to zero
; cx reset to avoid putting a non-packet message
; into queue
trail_recv:
mov bp, di ;remember first entry of queue line
cmp di, WORD PTR [queue.lastline]
jg recv_frame_full
; es:di -> packet buffer to be filled in
; cx = packet length
cmp cx, Q_WIDTH ;if (cx > Q_WIDTH)
jle recv_frame_ok ;
mov cx, Q_WIDTH ;align packet to proper width, 1 byte for size
;so will truncate char beyond the bound
recv_frame_ok:
mov si, WORD PTR [rcv.tail] ;resetting pointer to rcv.tail.
;----mov ax, cx
;----stosb ;queue.write[0] = cx
mov dx, 0 ;count
recv_frame_4:
cmp di, WORD PTR [queue.last] ; is it reach the end of queue ?
jne recv_frame_ready
recv_too_big:
mov [queue.status], QTOOBIG
;--- We don't need to store frame width anymore to simplify queue.
;---- The packet now contains data length to inform other task
;---- that frame has.
;----- (LUTFI, 16 Aug-95)
;-----mov BYTE PTR es:[bp], Q_WIDTH ;truncate packet
IF DEBUG EQ 1
mov al, 'M'
call print
ENDIF
;jmp next_sema
jmp next_pkt
recv_frame_ready:
call recv_char ; if ((recv.tail==recv.buf_end)||(al==FR_END))
je recv_frame_6 ; we're all done.
cmp al,FR_ESC ;an escape?
jne recv_frame_5 ;no - just store it.
call recv_char ;get the next character.
je recv_frame_6
cmp al,T_FR_ESC
mov al,FR_ESC ;assume T_FR_ESC
je recv_frame_5 ;yup, that's it - store FR_ESC
mov al,FR_END ;nope, store FR_END
recv_frame_5:
cmp dx, cx
jge recv_frame_6 ; beyond queue width, so break loop
stosb ;store the byte.
inc dx ;bytes stored
jmp recv_frame_4
recv_frame_6:
mov WORD PTR [rcv.tail], si ;we're skipped to the end
mov [queue.status], QOK ;sign queue status to OK state
jmp recv_frame_end
recv_frame_3:
mov WORD PTR [rcv.tail], si ;set to new location
recv_frame_end:
jcxz next_sema ; if no message, just skipped out
kecil:
add bp, Q_WIDTH
mov WORD PTR queue.write, bp ;next line of queue.
next_sema:
dec [packet_sem]
cmp [packet_sem], 0 ; are there more packets ready?
ja any_packet ; if (semaphore > 0)
jmp short recv_exit
any_packet:
jmp recv_frame ; yes - execute again
recv_exit:
; DDP - This is a BIG mistake. This routine SHOULD NOT enable interrupts.
; doing so can cause interrupt recursion and blow your stack.
; Processor interrupts SHOULD NOT be enabled after enabling device
; interrupts until after the "IRET". You will lose atleast 12 bytes
; on the stack for each recursion.
cli
mov al,[int_no] ; Now reenable device interrupts
call unmaskint
popf
POP bp di si es ds dx cx bx ax
sti
mov cs:in_recv_isr, 0 ; clear the re-entrancy flag
iret
recv_isr ENDP
;--------------------
; parameter:
; al : IRQ number
; register used:
; ax, cx, dx
;--------------------
maskint PROC NEAR
or al, al ;are they using a hardware interrupt?
je maskint_1 ;no, don't mask off the timer!
mov dx, MASKPORT ;assume the master 8259.
cmp al, BASEVEC ;using the slave 8259 on an AT?
jb mask_not_irq2
mov dx, MASKSLAVEPORT ;go disable it on slave 8259
sub al, BASEVEC
mask_not_irq2:
mov cl,al
in al,dx ;disable them on the correct 8259.
mov ah,1 ;set the bit.
shl ah,cl
or al,ah
;
;500ns Stall required here, per INTEL documentation for eisa machines
;
push ax
;in al, KBEOI ; 1.5 - 3 uS should be plenty
;in al, KBEOI
in al, KBEOI
out KBEOI,al
pop ax
out dx,al ; mask IRQ
maskint_1:
RETN
maskint ENDP
;--------------------
; parameter:
; al : IRQ number
; register used:
; ax, cx, dx
;--------------------
unmaskint PROC NEAR
mov dx, MASKPORT ;assume the master 8259.
mov cl, al
cmp cl, BASEVEC ;using the slave 8259 on an AT?
jb unmask_not_irq2 ;no
in al, dx ;get master mask
and al, NOT (1 shl 2) ; and clear slave cascade bit in mask
out dx, al ;set new master mask (enable slave int)
;
;500ns Stall required here, per INTEL documentation for eisa machines
;
push ax
in al, KBEOI ; 1.5 - 3 uS should be plenty
;********in al, KBEOI
;********in al, KBEOI
out KBEOI,al ; refresh keyboard stroke (LUTFI, 7/10/95)
pop ax
mov dx, MASKSLAVEPORT ;go enable interrupt on slave 8259
sub cl, BASEVEC
unmask_not_irq2:
in al,dx ;enable interrupts on the correct 8259.
mov ah,1 ;clear the bit.
shl ah,cl
not ah
and al,ah
; 500ns Stall required here, per INTEL documentation for eisa machines
; --- not needed, caused a problem with kbhit(). (lutfi, april 1995)
push ax
in al, KBEOI ; 1.5 - 3 uS should be plenty
mov ah, al ; save keyboard stroke (LUTFI, 11/12/95)
out KBEOI, al ; refresh keyboard stroke (LUTFI, 7/10/95)
pop ax
out dx,al ; un-mask IRQ
RETN
unmaskint ENDP
ENDS
END
;============================ END OF PROGRAM ===============================
Thursday, December 17, 2009
Wednesday, December 16, 2009
iptables rules for Anti Social-Net on Linux
List of IP addresses used by most popular social-networking sites:
69.63.181.11, fb1
69.63.181.12, fb2
69.63.181.15, fb3
69.63.181.16, fb4
69.63.187.17, fb5
69.63.187.19, fb6
69.63.184.142, fb7
69.63.186.30, fb8
69.63.184.31, fb9
69.63.184.28, fb10
69.63.184.30, fb11
69.63.184.31, fb12
216.86.150.58, plurk
168.143.162.36, twitter
69.63.181.11, fb1
69.63.181.12, fb2
69.63.181.15, fb3
69.63.181.16, fb4
69.63.187.17, fb5
69.63.187.19, fb6
69.63.184.142, fb7
69.63.186.30, fb8
69.63.184.31, fb9
69.63.184.28, fb10
69.63.184.30, fb11
69.63.184.31, fb12
216.86.150.58, plurk
168.143.162.36, twitter
Pseudo code:
<foreach ip above> do {
sudo iptables -A OUTBOUND -d <ip>/32 -j DROP
}
For firestarter, DROP is replaced with LSO
The above steps will create outbound firewall.
Tuesday, December 15, 2009
Best PC Hardwares in 2009
Mobo: Gigabyte GA-P55-UD6
Gaming Mouse: Logitech G9x
Liquid cooler: Corsair Cooling Hydro Series H5O
Mid-priced CPU: Intel Core i7-860
Video card: ATI Radeon HD-5870
Gaming Mouse: Logitech G9x
Liquid cooler: Corsair Cooling Hydro Series H5O
Mid-priced CPU: Intel Core i7-860
Video card: ATI Radeon HD-5870
Friday, December 11, 2009
Firewall made easy on Ubuntu
https://help.ubuntu.com/community/IptablesHowTo
Basic iptables howto
Iptables is a firewall, installed by default on all official Ubuntu distributions (Ubuntu, Kubuntu, Xubuntu). When you install Ubuntu, iptables is there, but it allows all traffic by default. Ubuntu 8.04 Comes with ufw - a program for managing the iptables firewall easily.
There is a wealth of information available about iptables, but much of it is fairly complex, and if you want to do a few basic things, this How To is for you.
Basic Commands
Typing
# iptables -L
lists your current rules in iptables. If you have just set up your server, you will have no rules, and you should see
Chain INPUT (policy ACCEPT) target prot opt source destination Chain FORWARD (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination
Basic Iptables Options
Here are explanations for some of the iptables options you will see in this tutorial. Don't worry about understanding everything here now, but remember to come back and look at this list as you encounter new options later on.
- -A - Append this rule to a rule chain. Valid chains for what we're doing are INPUT, FORWARD and OUTPUT, but we mostly deal with INPUT in this tutorial, which affects only incoming traffic.
- -L - List the current filter rules.
- -m conntrack - Allow filter rules to match based on connection state. Permits the use of the --ctstate option.
- --ctstate - Define the list of states for the rule to match on. Valid states are:
- NEW - The connection has not yet been seen.
- RELATED - The connection is new, but is related to another connection already permitted.
- ESTABLISHED - The connection is already established.
- INVALID - The traffic couldn't be identified for some reason.
- -m limit - Require the rule to match only a limited number of times. Allows the use of the --limit option. Useful for limiting logging rules.
- --limit - The maximum matching rate, given as a number followed by "/second", "/minute", "/hour", or "/day" depending on how often you want the rule to match. If this option is not used and -m limit is used, the default is "3/hour".
- -p - The connection protocol used.
- --dport - The destination port(s) required for this rule. A single port may be given, or a range may be given as start:end, which will match all ports from start to end, inclusive.
- -j - Jump to the specified target. By default, iptables allows four targets:
- ACCEPT - Accept the packet and stop processing rules in this chain.
- REJECT - Reject the packet and notify the sender that we did so, and stop processing rules in this chain.
- DROP - Silently ignore the packet, and stop processing rules in this chain.
- LOG - Log the packet, and continue processing more rules in this chain. Allows the use of the --log-prefix and --log-level options.
- --log-prefix - When logging, put this text before the log message. Use double quotes around the text to use.
- --log-level - Log using the specified syslog level. 7 is a good choice unless you specifically need something else.
- -i - Only match if the packet is coming in on the specified interface.
- -I - Inserts a rule. Takes two options, the chain to insert the rule into, and the rule number it should be.
- -I INPUT 5 would insert the rule into the INPUT chain and make it the 5th rule in the list.
- -v - Display more information in the output. Useful for if you have rules that look similar without using -v.
- -s --source - address[/mask] source specification
- -d --destination - address[/mask] destination specification
- -o --out-interface - output name[+] network interface name ([+] for wildcard)
Allowing Established Sessions
We can allow established sessions to receive traffic:
# iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
- The above rule has no spaces either side of the comma in ESTABLISHED,RELATED
If the line above doesn't work, you may be on a VPS that uses OpenVZ or doesn't have some kernel extensions installed. In that case, try this line instead:
# iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
Allowing Incoming Traffic on Specific Ports
You could start by blocking traffic, but you might be working over SSH, where you would need to allow SSH before blocking everything else.
To allow incoming traffic on the default SSH port (22), you could tell iptables to allow all TCP traffic on that port to come in.
# iptables -A INPUT -p tcp --dport ssh -j ACCEPT
Referring back to the list above, you can see that this tells iptables:
- append this rule to the input chain (-A INPUT) so we look at incoming traffic
- check to see if it is TCP (-p tcp).
- if so, check to see if the input goes to the SSH port (--dport ssh).
- if so, accept the input (-j ACCEPT).
Lets check the rules: (only the first few lines shown, you will see more)
# iptables -L Chain INPUT (policy ACCEPT) target prot opt source destination ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED ACCEPT tcp -- anywhere anywhere tcp dpt:ssh
Now, let's allow all incoming web traffic
# iptables -A INPUT -p tcp --dport 80 -j ACCEPT
Checking our rules, we have
# iptables -L Chain INPUT (policy ACCEPT) target prot opt source destination ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED ACCEPT tcp -- anywhere anywhere tcp dpt:ssh ACCEPT tcp -- anywhere anywhere tcp dpt:www
We have specifically allowed tcp traffic to the ssh and web ports, but as we have not blocked anything, all traffic can still come in.
Blocking Traffic
Once a decision is made to accept a packet, no more rules affect it. As our rules allowing ssh and web traffic come first, as long as our rule to block all traffic comes after them, we can still accept the traffic we want. All we need to do is put the rule to block all traffic at the end.
# iptables -A INPUT -j DROP # iptables -L Chain INPUT (policy ACCEPT) target prot opt source destination ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED ACCEPT tcp -- anywhere anywhere tcp dpt:ssh ACCEPT tcp -- anywhere anywhere tcp dpt:www DROP all -- anywhere anywhere
Because we didn't specify an interface or a protocol, any traffic for any port on any interface is blocked, except for web and ssh.
Editing iptables
The only problem with our setup so far is that even the loopback port is blocked. We could have written the drop rule for just eth0 by specifying -i eth0, but we could also add a rule for the loopback. If we append this rule, it will come too late - after all the traffic has been dropped. We need to insert this rule before that. Since this is a lot of traffic, we'll insert it as the first rule so it's processed first.
# iptables -I INPUT 1 -i lo -j ACCEPT # iptables -L Chain INPUT (policy ACCEPT) target prot opt source destination ACCEPT all -- anywhere anywhere ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED ACCEPT tcp -- anywhere anywhere tcp dpt:ssh ACCEPT tcp -- anywhere anywhere tcp dpt:www DROP all -- anywhere anywhere
The first and last lines look nearly the same, so we will list iptables in greater detail.
# iptables -L -v
Chain INPUT (policy ALLOW 0 packets, 0 bytes) pkts bytes target prot opt in out source destination 0 0 ACCEPT all -- lo any anywhere anywhere 0 0 ACCEPT all -- any any anywhere anywhere state RELATED,ESTABLISHED 0 0 ACCEPT tcp -- any any anywhere anywhere tcp dpt:ssh 0 0 ACCEPT tcp -- any any anywhere anywhere tcp dpt:www 0 0 DROP all -- any any anywhere anywhere
You can now see a lot more information. This rule is actually very important, since many programs use the loopback interface to communicate with each other. If you don't allow them to talk, you could break those programs!
Logging
In the above examples none of the traffic will be logged. If you would like to log dropped packets to syslog, this would be the quickest way:
# iptables -I INPUT 5 -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7
See Tips section for more ideas on logging.
Saving iptables
If you were to reboot your machine right now, your iptables configuration would disappear. Rather than type this each time you reboot, however, you can save the configuration, and have it start up automatically. To save the configuration, you can useiptables-save and iptables-restore.
Configuration on startup
WARNING: Iptables and NetworkManager seem to have a conflict. However NetworkManager is still in Beta. If you are concerned enough about security to install a firewall you might not want to trust NetworkManager to manage it yet. Also noteNetworkManager and iptables have opposite aims. Iptables aims to keep any questionable network traffice out.NetworkManager aims to keep you connected at all times. Therefore if you want security all the time, run iptables at boot time. If you want security some of the time then NetworkManager might be the right choice.
WARNING: If you use NetworkManager (installed by default on Feisty and later) these steps will leave you unable to useNetworkManager for the interfaces you modify. Please follow the steps in the next section instead.
NOTE: It appears on Hardy, NetworkManager has an issue with properly on saving and restoring the iptable rules when using the method in the next section. Using this first method appears to work. If you find otherwise, please update this note.
Save your firewall rules to a file
# iptables-save >/etc/iptables.rules
Then modify the /etc/network/interfaces configuration file to apply the rules automatically. You will need to know the interface that you are using in order to apply the rules - if you do not know, you are probably using the interface eth0, although you should check with the following command first to see if there are any wireless cards:
$ iwconfig
If you get output similiar to the following, then you do not have any wireless cards at all and your best bet is probably eth0.
$ iwconfig lo no wireless extensions. eth0 no wireless extensions. $
When you have found out the interface you are using, please open your /etc/network/interfaces file depending on what editor you want and/or what distribution you have:
Command line:
# nano /etc/network/interfaces
For Ubuntu and Xubuntu: type ALT+F2, then in the window that pops up, type:
gksudo gedit /etc/network/interfaces
and press Enter.
For Kubuntu: type ALT+F2, then in the window that pops up, type:
kdesu kate /etc/network/interfaces
and press enter.
When in the file, search for the interface you found, and at the end of the network related lines for that interface, add the line:
pre-up iptables-restore < /etc/iptables.rules
You can also prepare a set of down rules, save them into second file /etc/iptables.downrules and apply it automatically using the above steps:
post-down iptables-restore < /etc/iptables.downrules
A fully working example using both from above:
auto eth0 iface eth0 inet dhcp pre-up iptables-restore < /etc/iptables.rules post-down iptables-restore < /etc/iptables.downrules
You may also want to keep information from byte and packet counters.
iptables-save -c > /etc/iptables.save
The above command will in other words save the whole rule-set to a file called /etc/iptables.save with byte and packet counters still intact.
Alternatively you could add the iptables-restore and iptables-save to the if-pre-up.d and if-post-down.d directories in the /etc/network directory instead of modifying /etc/network/interface directly.
The script /etc/network/if-pre-up.d/iptaload will contain:
#!/bin/sh iptables-restore < /etc/iptables.rules exit 0
and/etc/network/if-post-down.d/iptasave will contain:
#!/bin/sh if [ -f /etc/iptables.downrules ]; then iptables-restore < /etc/iptables.downrules fi iptables-save -c > /etc/iptables.save exit 0
Then be sure to give both scripts execute permissions:
# chmod +x /etc/network/if-post-down.d/iptasave # chmod +x /etc/network/if-pre-up.d/iptaload
Configuration on Startup for NetworkManager
NetworkManager includes the ability to run scripts when it activates or deactivates an interface. To save iptables rules on shutdown, and to restore them on startup, we are going to create such a script. To begin, press Alt+F2 and enter this command:
For Ubuntu:
$ gksudo gedit /etc/NetworkManager/dispatcher.d/01firewall
For Kubuntu:
kdesu kate /etc/NetworkManager/dispatcher.d/01firewall
Then, paste this script into your editor, save, and exit the editor.
if [ -x /usr/bin/logger ]; then LOGGER="/usr/bin/logger -s -p daemon.info -t FirewallHandler" else LOGGER=echo fi case "$2" in pre-up) if [ ! -r /etc/iptables.rules ]; then ${LOGGER} "No iptables rules exist to restore." return fi if [ ! -x /sbin/iptables-restore ]; then ${LOGGER} "No program exists to restore iptables rules." return fi ${LOGGER} "Restoring iptables rules" /sbin/iptables-restore -c < /etc/iptables.rules ;; post-down) if [ ! -x /sbin/iptables-save ]; then ${LOGGER} "No program exists to save iptables rules." return fi ${LOGGER} "Saving iptables rules." /sbin/iptables-save -c > /etc/iptables.rules ;; *) ;; esac
Finally, we need to make sure NetworkManager can execute this script. In a terminal window, enter this command:
# chmod +x /etc/NetworkManager/dispatcher.d/01firewall
Tips
If you manually edit iptables on a regular basis
The above steps go over how to setup your firewall rules and presume they will be relatively static (and for most people they should be). But if you do a lot of development work, you may want to have your iptables saved everytime you reboot. You could add a line like this one in /etc/network/interfaces:
pre-up iptables-restore < /etc/iptables.rules post-down iptables-save > /etc/iptables.rules
The line "post-down iptables-save > /etc/iptables.rules" will save the rules to be used on the next boot.
Using iptables-save/restore to test rules
If you edit your iptables beyond this tutorial, you may want to use the iptables-save and iptables-restore feature to edit and test your rules. To do this open the rules file in your favorite text editor (in this example gedit).
$ sudo iptables-save > /etc/iptables.rules $ gksudo gedit /etc/iptables.rules
You will have a file that appears similiar to (following the example above):
# Generated by iptables-save v1.3.1 on Sun Apr 23 06:19:53 2006 *filter :INPUT ACCEPT [368:102354] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [92952:20764374] -A INPUT -i lo -j ACCEPT -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A INPUT -i eth0 -p tcp -m tcp --dport 22 -j ACCEPT -A INPUT -i eth0 -p tcp -m tcp --dport 80 -j ACCEPT -A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7 -A INPUT -j DROP COMMIT # Completed on Sun Apr 23 06:19:53 2006
Notice that these are iptables commands minus the iptable command. Feel free to edit this to file and save when complete. Then to test simply:
# iptables-restore < /etc/iptables.rules
After testing, if you have not added the iptables-save command above to your /etc/network/interfaces remember not to lose your changes:
# iptables-save > /etc/iptables.rules
More detailed Logging
For further detail in your syslog you may want create an additional Chain. This will be a very brief example of my /etc/iptables.rules showing how I setup my iptables to log to syslog:
# Generated by iptables-save v1.3.1 on Sun Apr 23 05:32:09 2006 *filter :INPUT ACCEPT [273:55355] :FORWARD ACCEPT [0:0] :LOGNDROP - [0:0] :OUTPUT ACCEPT [92376:20668252] -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A INPUT -i eth0 -p tcp -m tcp --dport 22 -j ACCEPT -A INPUT -i eth0 -p tcp -m tcp --dport 80 -j ACCEPT -A INPUT -i lo -j ACCEPT -A INPUT -j LOGNDROP -A LOGNDROP -p tcp -m limit --limit 5/min -j LOG --log-prefix "Denied TCP: " --log-level 7 -A LOGNDROP -p udp -m limit --limit 5/min -j LOG --log-prefix "Denied UDP: " --log-level 7 -A LOGNDROP -p icmp -m limit --limit 5/min -j LOG --log-prefix "Denied ICMP: " --log-level 7 -A LOGNDROP -j DROP COMMIT # Completed on Sun Apr 23 05:32:09 2006
Note a new CHAIN called LOGNDROP at the top of the file. Also, the standard DROP at the bottom of the INPUT chain is replaceed with LOGNDROP and add protocol descriptions so it makes sense looking at the log. Lastly we drop the traffic at the end of theLOGNDROP chain. The following gives some idea of what is happening:
- --limit sets the number of times to log the same rule to syslog
- --log-prefix "Denied..." adds a prefix to make finding in the syslog easier
- --log-level 7 sets the syslog level to informational (see man syslog for more detail, but you can probably leave this)
Disabling the firewall
If you need to disable the firewall temporarily, you can flush all the rules using
# iptables -F
or create a script using text editor such as nano
# nano -w /root/fw.stop
echo "Stopping firewall and allowing everyone..." iptables -F iptables -X iptables -t nat -F iptables -t nat -X iptables -t mangle -F iptables -t mangle -X iptables -P INPUT ACCEPT iptables -P FORWARD ACCEPT iptables -P OUTPUT ACCEPT
Make sure you can execute the script
$ chmod +x /root/fw.stop
You can run the script
$ /root/fw.stop
Easy configuration via GUI
GUFW - Gufw is a graphical frontend to UFW (Uncomplicated Firewall).
A new user can use Firestarter (a gui), available in repositories (Synaptic or apt-get) to configure her/his iptable rules, without needing the command line knowledge. Please see the tutorial though... Configuration is easy, but may not be enough for the advanced user. However, it should be enough for the most home users... The (read:my) suggested outbound configuration is "restrictive", with whitelisting each connection type whenever you need it (port 80 for http, 443 for secure http -https-, 1863 for msn chat etc) from the "policy" tab within firestarter. You can also use it to see active connections from and to your computer... The firewall stays up once it is configured using the wizard. Dial-up users will have to specify it to start automatically on dial up in the wizard.
Homepage for firestarter: http://www.fs-security.com/ (again, available in repositories, no compiling required) Tutorial:http://www.fs-security.com/docs/tutorial.php
Subscribe to:
Posts (Atom)