{
AFX Lite TCP Firewall by Aphex
Usage: afxfw.exe <port> <port> <port>...
Example: afxfw.exe 25 80 1433 6667
This firewall is the simplest of it's kind. It is a packet
filtering firewall that monitors SYN packets. When a SYN
packet is sent to an unauthorized TCP port a RST packet
is sent to same port, immediately tearing down the
connection.
The rules apply to both local and remote connections.
}
program Project1;
{$APPTYPE CONSOLE}
uses
Windows,
Winsock2;
type
TIPHEADER = record
ip_verlen: byte;
ip_tos: byte;
ip_len: word;
ip_id: word;
ip_offset: word;
ip_ttl: byte;
ip_protocol: byte;
ip_checksum: word;
ip_saddr: longword;
ip_daddr: longword;
end;
TTCPHEADER = record
th_sport: word;
th_dport: word;
th_seq: longword;
th_ack: longword;
th_len: byte;
th_flags: byte;
th_win: word;
th_checksum: word;
th_upr: word;
end;
TPACKET = record
d_ip: TIPHEADER;
d_tcp: TTCPHEADER;
end;
TPACKETARRAY = array [0..sizeof(TPACKET)-1] of char;
var
WSAData: TWSAData;
ArgLoop: integer;
Ports: array [0..31] of word;
const
IOC_RCVALL: cardinal = IOC_IN or $18000000 or 1;
function IntToStr(I: integer):string;
var
v1: string;
begin
Str(I, v1);
Result := v1;
end;
function StrToInt(const S: string): integer;
var
v1: Integer;
begin
Val(S, Result, v1);
end;
function CheckSum(var Buffer; Size: integer): word;
type
TWordArray = array[0..1] of word;
var
lSumm: LongWord;
iLoop: integer;
begin
lSumm := 0;
iLoop := 0;
while Size > 1 do
begin
lSumm := lSumm + TWordArray(Buffer)[iLoop];
inc(iLoop);
Size := Size - SizeOf(word);
end;
if Size = 1 then lSumm := lSumm + Byte(TWordArray(Buffer)[iLoop]);
lSumm := (lSumm shr 16) + (lSumm and $FFFF);
lSumm := lSumm + (lSumm shr 16);
Result := word(not lSumm);
end;
procedure RSTHeader(FromIP: dword; FromPort: word; ToIP: dword; ToPort: word; var Buffer: TPACKETARRAY; var Socket: TSockAddr; var Size: dword; Seq: dword);
var
ipHdr: TIPHEADER;
tcpHdr: TTCPHEADER;
TcpHeaderLen: word;
ChecksumSize: word;
DataPointer: ^byte;
procedure IncPtr(Value: integer);
begin
DataPointer := pointer(integer(DataPointer) + Value);
end;
begin
Size := sizeof(ipHdr) + sizeof(tcpHdr);
ipHdr.ip_verlen := ((4 shl 4) or sizeof(ipHdr) div sizeof(longword));
ipHdr.ip_tos := 0;
ipHdr.ip_len := htons(Size);
ipHdr.ip_id := 0;
ipHdr.ip_offset := 0;
ipHdr.ip_ttl := 128;
ipHdr.ip_protocol := 6;
ipHdr.ip_checksum := 0;
ipHdr.ip_saddr := FromIP;
ipHdr.ip_daddr := ToIP;
ChecksumSize := 0;
tcpHdr.th_sport := FromPort;
tcpHdr.th_dport := ToPort;
tcpHdr.th_seq := htonl(Seq);
tcpHdr.th_ack := 0;
tcpHdr.th_len := 80;
tcpHdr.th_flags := 20;
tcpHdr.th_win := htons(65535);
tcpHdr.th_checksum := 0;
tcpHdr.th_upr := 0;
DataPointer := @Buffer[0];
FillChar(Buffer, SizeOf(Buffer), 0);
Move(ipHdr.ip_saddr, DataPointer^, SizeOf(ipHdr.ip_saddr));
IncPtr(SizeOf(ipHdr.ip_saddr));
ChecksumSize := ChecksumSize + sizeof(ipHdr.ip_saddr);
Move(ipHdr.ip_daddr, DataPointer^, sizeof(ipHdr.ip_daddr));
IncPtr(SizeOf(ipHdr.ip_daddr));
ChecksumSize := ChecksumSize + sizeof(ipHdr.ip_daddr);
IncPtr(1);
Inc(ChecksumSize);
Move(ipHdr.ip_protocol, DataPointer^, sizeof(ipHdr.ip_protocol));
IncPtr(sizeof(ipHdr.ip_protocol));
ChecksumSize := ChecksumSize + sizeof(ipHdr.ip_protocol);
TcpHeaderLen := htons(sizeof(tcpHdr));
Move(TcpHeaderLen, DataPointer^, sizeof(TcpHeaderLen));
IncPtr(sizeof(TcpHeaderLen));
ChecksumSize := ChecksumSize + sizeof(TcpHeaderLen);
Move(tcpHdr, DataPointer^, sizeof(tcpHdr));
IncPtr(sizeof(tcpHdr));
ChecksumSize := ChecksumSize + sizeof(tcpHdr);
tcpHdr.th_checksum := CheckSum(Buffer, ChecksumSize);
FillChar(Buffer, sizeof(Buffer), 0);
DataPointer := @Buffer[0];
Move(ipHdr, DataPointer^, sizeof(ipHdr));
IncPtr(sizeof(ipHdr));
Move(tcpHdr, DataPointer^, sizeof(tcpHdr));
Socket.sin_family := AF_INET;
Socket.sin_port := 0;
Socket.sin_addr.S_addr := ToIP;
end;
procedure Main;
var
rSocket, sSocket: TSocket;
Data, RST: TPACKET;
BytesReceived, BytesSent: dword;
Control: dword;
SockAddrIn: TSockAddrIn;
ArgLoop, Option: integer;
function GetInAddr: TInAddr;
var
Host: array[0..128] of char;
HostEnt: PHostEnt;
begin
GetHostName(@Host, 128);
HostEnt := GetHostByName(@Host);
Result := PInAddr(HostEnt^.h_addr_list^)^
end;
begin
if WSAStartup(WINSOCK_VERSION, WSAData) = 0 then
begin
rSocket := Socket(PF_INET, SOCK_RAW, 0);
sSocket := Socket(PF_INET, SOCK_RAW, 0);
if ((rSocket <> INVALID_SOCKET) and (sSocket <> INVALID_SOCKET)) then
begin
SetSockOpt(sSocket, 0, 2, @Option, SizeOf(Option));
SockAddrIn.sin_family := AF_INET;
SockAddrIn.sin_addr := GetInAddr;
SockAddrIn.sin_port := htons(0);
bind(rSocket, @SockAddrIn, SizeOf(SockAddrIn));
WSAIoctl(rSocket, IOC_RCVALL, @Control, SizeOf(Control), nil, 0, @BytesReceived, nil, nil);
while rSocket <> INVALID_SOCKET do
begin
BytesReceived := recv(rSocket, Data, SizeOf(Data), 0);
if BytesReceived > 0 then
begin
if Data.d_ip.ip_protocol = 6 then
begin
if (Data.d_tcp.th_flags and 2) <> 0 then
begin
for ArgLoop := 0 to 31 do
begin
if Ports[ArgLoop] = htons(Data.d_tcp.th_dport) then
begin
RSTHeader(Data.d_ip.ip_saddr, Data.d_tcp.th_sport, Data.d_ip.ip_daddr, Data.d_tcp.th_dport, TPACKETARRAY(RST), SockAddrIn, BytesSent, ntohl(Data.d_tcp.th_seq) + 1);
SendTo(sSocket, RST, BytesSent, 0, SockAddrIn, sizeof(SockAddrIn));
Break;
end;
end;
end;
end;
end
else
begin
Break;
end;
end;
end;
end;
WSACleanup;
end;
begin
WriteLn('AFX Lite TCP Firewall by Aphex');
WriteLn('http://www.iamaphex.cjb.net');
WriteLn('unremote@knology.net');
if ParamStr(1) = '' then
begin
WriteLn('');
WriteLn('Usage: afxfw.exe <port> <port> <port>...');
Halt(0);
end;
for ArgLoop := 1 to 32 do
begin
if ParamStr(ArgLoop) <> '' then
begin
Ports[ArgLoop - 1] := StrToInt(ParamStr(ArgLoop));
end;
end;
Main;
end.