Webアプリケーションファイアウォールを開発する任務があります。私はそれについていくつかのソースコードを研究してきました。私の主なソースはModSecurityでした。
主な質問は次のとおりです。
-Webアプリケーションファイアウォールを開発するために使用できるフレームワークまたはプログラミング言語はどれですか?どれが最も便利でしょうか?
-DjangoとPythonを使用できますか?
それがプロジェクト研究の出発点となるでしょう。
Webアプリケーションファイアウォールを開発する任務があります。私はそれについていくつかのソースコードを研究してきました。私の主なソースはModSecurityでした。
主な質問は次のとおりです。
-Webアプリケーションファイアウォールを開発するために使用できるフレームワークまたはプログラミング言語はどれですか?どれが最も便利でしょうか?
-DjangoとPythonを使用できますか?
それがプロジェクト研究の出発点となるでしょう。
わかりました。セキュリティがまったくないか悪いアプリを保護していると思っていたのですが、基本的には正しいと思いますが、それは攻撃からの保護に関するものです。その場合、Djangoは間違いなく間違っています。Pythonで明らかに実行可能ですが、1秒あたり100.000のリクエストを処理できるとは期待しないでください。:)しかし、研究開発の場合、Pythonは開発が速く、Cythonのようなツールを使用すると実行も非常に速くなるため、優れた選択肢になると思います。その後、極端なパフォーマンスを必要とする完成品を作成することになった場合は、アルゴリズムを使用してC /C++に変換できます。
あなたの場合はツイストを調べます。それが正しい解決策かもしれません。
「これは、HTTPを介してユーザートランザクションを制御するためにサーバー側で使用されます。」
ほとんどのWebアプリケーションフレームワークにはセキュリティ設定があります。これらは通常「ファイアウォール」とは呼ばれず、あなたは私の質問に答えなかったので、ここで推測します。
アクセス制御がまったくないアプリケーションがあるため、正しい権限を持たない要求を除外するように機能するWebプロキシを作成しています。これは正しいです?
はい、Pythonでそれを行うことができます。Djangoはおそらく正しい解決策ではありません。ログインページとユーザー管理を使用してアクセス制御を実装する必要がある場合は、SQLとテンプレートが必要になる可能性があり、軽量のPythonフレームワークが役立つ可能性があります。それ以外の場合は、ツイストするか、標準ライブラリの機能を使用してそれを実行することが正しい解決策になる可能性があります。
これはあなたがしなければならないことです。Linuxを使い始めるには、Windowsよりもはるかに扱いやすく、2つのオプションがあります。1つはシステム呼び出しにフックしてNetFilterドライバーを実装することです(もっと複雑です!)、2つ目はlibnetfilter_queueを使用することですパケットをユーザースペースアプリケーションに転送するためのライブラリとiptablesの主なアイデアは、IPとTCPヘッダー、非常によく似たIDS、IPSシステムをチェックする以外に、ペイロードを詳細に分析することですが、Webアプリケーションのセキュリティホールに焦点を当てています。
私はあなたがより深い干渉なしにPythonでこれを行うことができるとは思いません、あなたがここで尋ねることはかなりトリッキーです、それはシステムのより低いレベルに関係しています...
次の例を使用して、データの分析を開始できます。
iptablesを構成します
#: iptables -A INPUT -j NFQUEUE --queue-balance 0:3
#: iptables -A OUTPUT -j NFQUEUE --queue-balance 4:8
キュー0から3はすべての入力用であり(別のキューに分割する方が良いです。キューが保持できるパケットには制限があります)、もう1つはすべての出力用です。
Cでアプリケーションを作成する(iptablesはパケットをカーネルからユーザースペースに転送します)
filterQueue.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <linux/types.h>
#include <string.h>
/* for ethernet header */
#include<net/ethernet.h>
/* for UDP header */
#include<linux/udp.h>
/* for TCP header */
#include<linux/tcp.h>
/* for IP header */
#include<linux/ip.h>
/* -20 (maximum priority) */
#include <sys/time.h>
#include <sys/resource.h>
/* for NF_ACCEPT */
#include <linux/netfilter.h>
/* for Threads */
#include <pthread.h>
/* for Queue */
#include <libnetfilter_queue/libnetfilter_queue.h>
#define NUM_THREADS 15
pthread_t threads[NUM_THREADS];
void printTCP(unsigned char *buffer) {
unsigned short iphdrlen;
struct iphdr *iph = (struct iphdr *) (buffer + sizeof(struct ethhdr));
iphdrlen = iph->ihl * 4;
struct tcphdr *tcph = (struct tcphdr *) (buffer + iphdrlen
+ sizeof(struct ethhdr));
int header_size = sizeof(struct ethhdr) + iphdrlen + tcph->doff * 4;
printf("| Packet Type: TCP \n");
printf("|-Source Port : %u\n", ntohs(tcph->source));
printf("|-Destination Port : %u\n", ntohs(tcph->dest));
printf("|-Sequence Number : %u\n", ntohl(tcph->seq));
printf("|-Acknowledge Number : %u\n", ntohl(tcph->ack_seq));
printf("|-Header Length : %d DWORDS or %d BYTES\n",
(unsigned int) tcph->doff, (unsigned int) tcph->doff * 4);
printf("|-CWR Flag : %d\n", (unsigned int) tcph->cwr);
printf("|-ECN Flag : %d\n", (unsigned int) tcph->ece);
printf("|-Urgent Flag : %d\n", (unsigned int) tcph->urg);
printf("|-Acknowledgement Flag : %d\n", (unsigned int) tcph->ack);
printf("|-Push Flag : %d\n", (unsigned int) tcph->psh);
printf("|-Reset Flag : %d\n", (unsigned int) tcph->rst);
printf("|-Synchronise Flag : %d\n", (unsigned int) tcph->syn);
printf("|-Finish Flag : %d\n", (unsigned int) tcph->fin);
printf("|-Window : %d\n", ntohs(tcph->window));
printf("|-Checksum : %d\n", ntohs(tcph->check));
printf("|-Urgent Pointer : %d\n", tcph->urg_ptr);
}
void printUDP(unsigned char *buffer) {
unsigned short iphdrlen;
struct iphdr *iph = (struct iphdr *) (buffer + sizeof(struct ethhdr));
iphdrlen = iph->ihl * 4;
struct udphdr *udph = (struct udphdr*) (buffer + iphdrlen
+ sizeof(struct ethhdr));
int header_size = sizeof(struct ethhdr) + iphdrlen + sizeof udph;
printf("| Packet Type: UDP \n");
printf("|-Source Port : %u\n", ntohs(udph->source));
printf("|-Destination Port : %u\n", ntohs(udph->dest));
printf("|-UDP Length : %u\n", ntohs(udph->len));
printf("|-UDP Checksum : %u\n", ntohs(udph->check));
}
char * getText(unsigned char * data, char Size) {
char * text = malloc(Size);
int i = 0;
for (i = 0; i < Size; i++) {
if (data[i] >= 32 && data[i] <= 128)
text[i] = (unsigned char) data[i];
else
text[i] = '.';
}
return text;
}
u_int32_t analyzePacket(struct nfq_data *tb, int *blockFlag) {
//packet id in the queue
int id = 0;
//the queue header
struct nfqnl_msg_packet_hdr *ph;
//the packet
char *data;
//packet size
int ret;
//extracting the queue header
ph = nfq_get_msg_packet_hdr(tb);
//getting the id of the packet in the queue
if (ph)
id = ntohl(ph->packet_id);
//getting the length and the payload of the packet
ret = nfq_get_payload(tb, &data);
if (ret >= 0) {
printf("Packet Received: %d \n", ret);
/* extracting the ipheader from packet */
struct sockaddr_in source, dest;
unsigned short iphdrlen;
struct iphdr *iph = ((struct iphdr *) data);
iphdrlen = iph->ihl * 4;
memset(&source, 0, sizeof(source));
source.sin_addr.s_addr = iph->saddr;
memset(&dest, 0, sizeof(dest));
dest.sin_addr.s_addr = iph->daddr;
printf("|-Source IP: %s\n", inet_ntoa(source.sin_addr));
printf("|-Destination IP: %s\n", inet_ntoa(dest.sin_addr));
printf("|-Checking for Protocol: \n");
if (iph->protocol == 6) {
printTCP(data);
} else if (iph->protocol == 17) {
printUDP(data);
}
printf("|-Extracting Payload: \n");
char * text = getText(data, ret);
//filtering requests for facebook
if (text && text[0] != '\0') {
printf("\n %s \n", text);
ret = strstr(text, "facebook");
if (ret == 0)
//not found in string
*blockFlag = 0;
else
//found in string
*blockFlag = 1;
}
//release the packet
free(text);
}
//return the queue id
return id;
}
int packetHandler(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa,
void *data) {
printf("entering callback \n");
//when to drop
int blockFlag = 0;
//analyze the packet and return the packet id in the queue
u_int32_t id = analyzePacket(nfa, &blockFlag);
//this is the point where we decide the destiny of the packet
if (blockFlag == 0)
return nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL);
else
return nfq_set_verdict(qh, id, NF_DROP, 0, NULL);
}
void *QueueThread(void *threadid) {
//thread id
long tid;
tid = (long) threadid;
struct nfq_handle *h;
struct nfq_q_handle *qh;
char buf[128000] __attribute__ ((aligned));
//pointers and descriptors
int fd;
int rv;
int ql;
printf("open handle to the netfilter_queue - > Thread: %d \n", tid);
h = nfq_open();
if (!h) {
fprintf(stderr, "cannot open nfq_open()\n");
return NULL;
}
//unbinding previous procfs
if (nfq_unbind_pf(h, AF_INET) < 0) {
fprintf(stderr, "error during nfq_unbind_pf()\n");
return NULL;
}
//binding the netlink procfs
if (nfq_bind_pf(h, AF_INET) < 0) {
fprintf(stderr, "error during nfq_bind_pf()\n");
return NULL;
}
//connet the thread for specific socket
printf("binding this socket to queue '%d'\n", tid);
qh = nfq_create_queue(h, tid, &packetHandler, NULL);
if (!qh) {
fprintf(stderr, "error during nfq_create_queue()\n");
return NULL;
}
//set queue length before start dropping packages
ql = nfq_set_queue_maxlen(qh, 100000);
//set the queue for copy mode
if (nfq_set_mode(qh, NFQNL_COPY_PACKET, 0xffff) < 0) {
fprintf(stderr, "can't set packet_copy mode\n");
return NULL;
}
//getting the file descriptor
fd = nfq_fd(h);
while ((rv = recv(fd, buf, sizeof(buf), 0)) && rv >= 0) {
printf("pkt received in Thread: %d \n", tid);
nfq_handle_packet(h, buf, rv);
}
printf("unbinding from queue Thread: %d \n", tid);
nfq_destroy_queue(qh);
printf("closing library handle\n");
nfq_close(h);
return NULL;
}
int main(int argc, char *argv[]) {
//set process priority
setpriority(PRIO_PROCESS, 0, -20);
int rc;
long balancerSocket;
for (balancerSocket = 0; balancerSocket < NUM_THREADS; balancerSocket++) {
printf("In main: creating thread %ld\n", balancerSocket);
//send the balancer socket for the queue
rc = pthread_create(&threads[balancerSocket], NULL, QueueThread,
(void *) balancerSocket);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
while (1) {
sleep(10);
}
//destroy all threads
pthread_exit(NULL);
}
これが単なる学術的な演習であり、Pythonがそれを迅速に実行するのに役立つ場合を除いて、Pythonのような高級言語がファイアウォールに最適であるとは思いません(正直に可能かどうかさえわかりません)。ある種のプロキシ/フィルターアプリケーションを計画している場合、それは問題ないかもしれませんが、Djangoはどちらの方法でも必要ありません。
DjangoはWebアプリケーションフレームワークです。それを使用してファイアウォールの実装を書いている人は誰もいません。
C、C ++、Golang、Luaはすべて、Webアプリケーションファイアウォールまたはゲートウェイを開発するためのオプションの言語ですが、djangoはそれに適していません。C、C ++は、nginxプラグインまたはバックエンドWAFを開発できます。Golangは、JanusecApplicationGatewayなどのWAFを使用したゲートウェイを開発できます。Luaはnginxアクセス制御を拡張し、WAFとして機能できます。