1. 程式人生 > >埠詳解+埠掃描原理+簡單埠掃描實現

埠詳解+埠掃描原理+簡單埠掃描實現

一 摘要

        埠是個網路應用中很重要的東西,相當於“門”。
二 什麼是埠
        埠在計算機網路中是個非常重要的概念,他不是硬體,不同於計算機中的插槽,可以說是個軟插槽。如果有需要,一臺計算機中可以由上萬個埠。 

       埠是由計算通訊協議TCP/IP協議定義的。其中規定,用IP地址和埠作為套接字,它代表TCP連結的一個連線端,一般稱為socket,具體來說,就是用[ip:埠]來定位一臺主機中的程序。可以做這樣的比喻,埠相當於兩臺計算機程序間的大門,可隨便定義,其目的只是為了讓兩臺計算機能找到對方的程序。計算機就想一座大樓,這個大樓有好多入口(埠),進到不同的入口中就可以找到不同的公司(程序)。如果要和遠端主機A的程式通訊,那麼只要把資料發向[A;埠]就可以實現通訊了。


三 埠的分類
  在Internet上,按照協議型別分類,埠被分為TCP埠和UDP埠兩類,雖然他們都用正整數標識,但這並不會引起歧義,比如TCP的80埠和UDP的80埠,因為資料報在標明埠的同時,還將標明埠的型別。 
  從埠的分配來看,埠被分為固定埠和動態埠兩大類(一些教程還將極少被用到的高階口劃分為第三類:私有埠):
  固定埠(0-1023):
   使用集中式管理機制,即服從一個管理機構對埠的指派,這個機構負責釋出這些指派。由於這些埠緊綁於一些服務,所以我們會經常掃描這些埠來判斷對方 是否開啟了這些服務,如TCP的21(ftp),80(http),139(netbios),UDP的7(echo),69(tftp)等等一些大家熟 知的埠;

  動態埠(1024-49151):
  這些埠並不被固定的捆綁於某一服務,作業系統將這些埠動態的分配給各個程序, 同一程序兩次分配有可能分配到不同的埠。不過一些應用程式並不願意使用作業系統分配的動態埠,他們有其自己的‘商標性’埠,如oicq客戶端的 4000埠,木馬冰河的7626埠等都是固定而出名的。

四 埠在入侵中的作用
  有人曾經把伺服器比作房子,而把埠比作通向不同房間(服務)的門,如果不考慮細節的話,這是一個不錯的比喻。入侵者要佔領這間房子,勢必要破門而入(物理入侵另說),那麼對於入侵者來說,瞭解房子開了幾扇門,都是什麼樣的門,門後面有什麼東西就顯得至關重要。
   入侵者通常會用掃描器對目標主機的埠進行掃描,以確定哪些埠是開放的,從開放的埠,入侵者可以知道目標主機大致提供了哪些服務,進而猜測可能存在 的漏洞,因此對埠的掃描可以幫助我們更好的瞭解目標主機,而對於管理員,掃描本機的開放埠也是做好安全防範的第一步。

五、埠掃描原理:嘗試與目標主機建立連線,如果目標主機有回覆則說明埠開放。
掃描分類:
      1. 全TCP連線,這種方法使用三次握手與目標主機建立標準的tcp連線。但是這種方法跟容易被發現,被目標主機記錄。
      2. SYN掃描,掃描主機自動向目標主機的指定埠傳送SYN資料段,表示傳送建立連線請求。
!!如果目標主機的迴應報文SYN=1,ACK=1.則說明該埠是活動的,接著掃描主機發送回一個RST給目標主機拒絕連線。導致三次握手失敗。
!!如果目標主機迴應是RST則埠是“死的”。
      3 FIN掃描,傳送一個FIN=1的報文到一個關閉的視窗該報文將丟失並返回一個RST,如果該FIN報文傳送到活動視窗則報文丟失,不會有任何反應。
      4.代理掃描。就是抓雞啦。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <pthread.h>

#define MAX_THREAD_NUM 100
#define SEG_LEN 655
#define MAX_PORT 65535

typedef struct PortNode
{
    char ip[30];
    int minPort;
    int maxPort;
}PortNode;
pthread_t tid;
void* doit(void* arg)
{
    int i, sockfd, connfd;
    struct sockaddr_in servaddr;
    PortNode* port = (PortNode*)arg;
    pthread_detach(pthread_self());//為避免儲存器洩漏,每個可結合線程都應該被其他執行緒顯式地收回,要麼通過呼叫pthread_detach函式被分離
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    //inet_pton(AF_INET, port->ip, &servaddr.sin_addr);
    servaddr.sin_addr.s_addr = inet_addr(port->ip);
    for(i = port->minPort; i <= port->maxPort; i++){
        servaddr.sin_port = htons(i);
        if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
            perror("socket error");
            pthread_exit(NULL);
        }
        if(connect(sockfd, (struct sockaddr *)&servaddr, sizeof(struct sockaddr)) == 0){
            printf("%s:%d\n", port->ip, i);
        }
        close(sockfd);//注意關閉!!
    }
    pthread_exit(NULL);
}


int main(int argc, char** argv)
{
    int i,j;
    for(i = 1; i < argc; i++){
        PortNode* port = (PortNode*)malloc(sizeof(PortNode));
        for(j = 0; j < MAX_THREAD_NUM; j++){
            strcpy(port->ip, argv[i]);
            port->minPort = j*SEG_LEN + 1;
            if(j == (MAX_THREAD_NUM - 1))port->maxPort = MAX_PORT;
            else port->maxPort = port->minPort + SEG_LEN - 1;
            if(pthread_create(&tid, NULL, doit, (void*) port)  != 0 ){
                perror("pthread create error.\n");
                free(port);
                port=NULL;
                exit(1);
            }
        }
    }
    sleep(3);
}