Последнее обновление:
Разработка простого ТСР-сервера под Linux
В этой статье мы приведем небольшой сервер на языке С. При его помощи можно продемонстрировать взаимодействие между хостовой и гостевой ОС. Можно, конечно, взять что-то готовое, но его придется устанавливать и описывать дополнительно. Да и работу готового сервера, что называется, не пощупаешь руками. Поэтому проще набросать простенький сервер самостоятельно, на основе технологии сокетов, к примеру. Вот его исходный код на языке С:
- #include <stdlib.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <string.h>
- #include <sys/stat.h>
- char message[] = "Hello from Linux! ";
- char tmp[8];
- unsigned int sizeAddr;
- int main()
- {
- int sock, listSOCKET;
- struct sockaddr_in addr;
- char buffer[1024];
- int amount;
- listSOCKET = socket(AF_INET, SOCK_STREAM, 0);
- if(listSOCKET < 0)
- {
- perror("socket cannot use. Exit.");
- exit(1);
- }
- addr.sin_family = AF_INET;
- addr.sin_port = htons(3001);
- addr.sin_addr.s_addr = htonl(INADDR_ANY);
- if(bind(listSOCKET, (struct sockaddr *)&addr, sizeof(addr)) < 0)
- {
- perror("bind is wrong. Exit.");
- exit(2);
- }
- listen(listSOCKET, 1);
- int i =0;
- while(1)
- {i++;
- sizeAddr=sizeof(addr);
- sock = accept(listSOCKET, (struct sockaddr *)&addr, &sizeAddr );
- printf ("\n");
- if(sock < 0) {
- perror("accept is wrong. Exit.");
- exit(3);
- }
- amount = recv(sock, buffer, 1024, 0);
- strncat(buffer, message, sizeof(message));
- sprintf (tmp, "%d", i);
- strncat(buffer, tmp, strlen(tmp) * sizeof(char));
- printf("buffer= %s \n", buffer);
- send(sock, buffer, amount+sizeof(message) + strlen(tmp) * sizeof(char)-1, 0);
- if(amount <= 0) break;
- memset (buffer, 0, sizeof(buffer));
- close(sock);
- }
- return 0;
- }
Эта программа принимает сетевой запрос, выводит его содержимое в консоль (в на основнм хосте или в виртуальной машине - в зависимости от того, где он запущен), затем добавляет к нему фразу «Hello from Linux!» и счетчик обновлений страницы и затем, окончательно, отсылает все это обратно источнику запроса, т.е. клиенту. При каждом очередном обновлении страницы счетчик увеличивается на 1. Обсуждать программу не будем, ибо, видится, что все и так понятно. Отметим, что ее можно использовать для демонстрации взаимодействия между основным хостом и виртуальной машиной после проброса портов.
Как сделать запрос от клиента, запущенного на хосте?
В качестве клиента подойдет любая программа, способная отправлять запросы и получать на них ответы. Например, любой браузер. В его адресной строке необходимо ввести URL запроса.
Допустим, IP-адрес виртуальной машины есть 192.168.56.1. Также предположим, что в гостевой операционной системе (которая запущена виртуальная машина) есть свободный порт под номером 3000. Так вот, именно на этот адрес (и на порт 3000) и следует направить запрос. Т.е. в адресной строке браузера должно быть:
http://192.168.56.1:3000
Т.е. все как обычно:
- протокол,
- двоеточие,
- два слеша,
- доменное имя или IP-адрес,
- двоеточие,
- порт (номер порта).
Выполнив запрос браузера, обнаружим в окне страницы заголовки протокола HTTP, отправленные браузером, фразу «Hello from Linux!» и номер счетчика, который будет увеличиваться на 1 при каждом последующем обращении к странице (в результате ее обновления). Запрос направляется на порт под номером 3000 в ОС хоста, но затем на него действует правило проброса, перенаправляя его в ОС виртуальной машины (гостевую) на порт номер 3001.
Как видно, проброс портов в условиях действия политики NAT решил проблему взаимодействия между хостом и виртуальной машиной.
Для чего это может быть использовано?
Приведем парочку наиболее популярных примеров.
1. Например, в гостевой ОС можно запустить прокси-сервер, который, в свою очередь, будет соединяться с интернетом. И из хоста можно будет перенаправлять запросы, идущие на некоторые (или даже на все) IP-адреса. При этом запросы браузера в хостовой системе на открытие страницы того или иного (или всех) сайта будут перенаправлены в виртуальную машину и попадут на прокси-сервер. Ну, а он уже будет связываться с интернетом, получать контент страниц, как-то изменять его, при необходимости и возвращать его браузеру в хост. Причем, браузер даже и знать не будет, что его запросы перенаправляются на прокси-сервер.
При этом, если вдруг на вебсервере, т.е. на сайте, расположенном в интернете, попадется нечто нехорошее (так называемый вирус), практически все проблемы примет на себя ОС в виртуальной машине, в частности, запущенный в ней прокси-сервер. Что приведет, максимум, к краху этого прокси-сервера и, быть может, к краху ОС в виртуальной машине. Но, не более того.
Проблемы у хоста могут возникнуть, разве что, если прокси-сервер вернет ему полученный из интернета корректный, с точки зрения транспортного уровня (ТСР), но вредоносный трафик уровня НТТР/HTTPS. Который способен сделать проблему, разве что, для браузера. Что вылечится его перезапуском.
2. Для реализации удаленных функций. По аналогии, скажем, с механизмом RPC. Это когда Ваше приложение (работающее в основной ОС, т.е. на хосте) направляет системные запросы к функциям, библиотекам, расположенных где-то в другом месте – в данном случае, в виртуальной машине, в гостевой ОС. Хотя, вполне можно использовать здесь и непосредственно саму технологию RPC.
Удобство здесь проявляется в том, что эти библиотеки можно отключить, точнее, сделать полностью недоступными лишь одним движением – достаточно отключить виртуальную машину, либо сервер, управляющий взаимодействием с этими библиотеками. Подключение тоже, соответственно, весьма простое. При этом важно, что только Ваш хост будет иметь возможность доступа к ним – так как IP-адрес гостевой ОС, в которой они будут работать, является частным (приватным), имея маску 192.168.0.0. А это означает, что политика NAT хоста запретит к ним доступ извне.
Такая технология может быть актуальной, например, если Ваш хост является публичным сервером, но Вы хотите на этом же физическом компьютере хранить также и некоторые секретные данные, библиотеки. При этом Вы будете иметь к ним доступ, а пользователи, обращающиеся на Ваш хост извне – нет.
И последнее про проброс портов на TCP-сервер
Настроив правило проброса портов БЕЗ УКАЗАНИЯ IP-адресов, для которых действует такое правило (а, следовательно, оно будет действовать для ВСЕХ IP-адресов), надо быть точно уверенным, что ни порт 3000 на хосте, ни порт 3001 в гостевой ОС не используется никакими другими программами. Иначе так можно помешать их работе. Поэтому, для целей безопасности, в правилах проброса портов лучше бы использовать, наряду с номерами портов, и конкретные IP-адреса, для которых только и будет работать правило проброса.