DHCPRELEASE -- Такое широковещательное сообщение отправляется клиентом если он прекращает использования сетевого адреса.
DHCPNAK -- Этот ответ будет отправлен клиенту в случае, если невозможно удовлетворить параметры DHCPREQUEST.
DHCPDECLINE -- Широковещательный ответ серверу в том случае, когда клиент обнаруживает, что присвоенный ему IP-адрес уже используется.
DHCPINFORM -- Сообщение серверу в том случае, если у клиента DHCP прописан статический IP-адрес и он не нуждается в динамическом распределении.
Сообщения протокола DCHP имеют следующие поля:
|
Поле |
Длина (байты) |
Описание |
|
|
op |
1 |
Тип сообщения |
|
|
htype |
1 |
Тип адреса аппаратной части |
|
|
hlen |
1 |
Длина адреса аппаратной части |
|
|
hops |
1 |
Используемое количество агентов ретрансляции. Клиенты устанавливают значение на 0. |
|
|
xid |
4 |
ID (уникальный идентификационный номер) транзакции используемой клиентом и серверов во время сессии |
|
|
secs |
2 |
Прошедшее время (в секундах) с момента запроса клиентом начала процесса |
|
|
flags |
2 |
Значение флагов |
|
|
ciaddr |
4 |
IP-адрес клиента (если имелся ранее). |
|
|
yiaddr |
4 |
IP-адрес, предложенный сервером клиенту |
|
|
siaddr |
4 |
IP-адрес сервера |
|
|
giaddr |
4 |
IP-адрес relay-агента (агента ретрансляции) |
|
|
chaddr |
16 |
Адрес аппаратной части клиента (в основном MAC). |
|
|
sname |
64 |
Имя сервера. |
|
|
file |
128 |
Название загрузочного файла. |
|
|
options |
изменяемая |
Дополнительные опции |
Как включить DHCP на сетевом адаптере
В операционной системе Windows 10 DHCP-клиент включен по умолчанию как служба, а на сетевом адаптере необходимо выставить автоматическое получение IP. Для этого нажимаем комбинацию клавиш Win+R чтобы открыть окно «Выполнить» и вводим команду ncpa.cpl.
Нажимаем на кнопку «ОК». Появится окно с сетевыми подключениями Виндовс 10.
На том адаптере, где хотим включить DHCP, кликаем правой кнопкой чтобы появилось контекстное меню. В меню -- выбираем пункт «Свойства».
В следующем окне надо выбрать строчку «IP версии 4(TCP/IPv4)» и нажимаем на кнопку «Свойства» чтобы открыть параметры протокола:
Здесь необходимо поставить галочки на автоматическое получение адресов и нажать на кнопку «ОК».
В операционных системах семейства Linux все настройки прописаны в конфигурационных файлах. Например, в популярной Ubuntu это /etc/network/interfaces. Вот пример конфига, который позволяет включить DHCP на сетевом адаптере eth0:
Здесь:
auto eth0 -- автоматическое включение сетевой карты eth0 при загрузке системы.
iface eth0 inet static -- этой строчкой мы указываем системе, что интерфейс сетевой карты eth0 находится в диапазоне адресов с динамическим получением ip.
Если в системе работает менеджер соединение Network Manager, то можно включить DHCP на сетевом адаптере и в графическом интерфейсе:
DHCP (протокол динамической конфигурации хоста) - это протокол управления сетью, используемый для динамического назначения IP-адреса на любом устройстве или узле в сети, чтобы они могли связываться с использованием IP. DHCP автоматизирует и централизованно управляет этими конфигурациями, а не требует, чтобы сетевые администраторы вручную назначали IP-адреса всем сетевым устройствам. DHCP может быть реализован в небольших локальных сетях, а также в крупных корпоративных сетях.
DHCP назначит новые IP-адреса в каждом местоположении, когда устройства будут перемещены с места на место, что означает, что сетевым администраторам не нужно вручную сначала настраивать каждое устройство с допустимым IP-адресом или перенастраивать устройство с новым IP-адресом, если он перемещается на новое место в сети. Версии DHCP доступны для использования в интернет-протоколе версии 4 (IPv4) и в Internet Protocol версии 6 (IPv6).
Как работает DHCP
DHCP работает на прикладном уровне стека протокола протокола управления передачей / протокола IP (TCP / IP) для динамического назначения IP-адресов DHCP-клиентам и для распределения данных конфигурации TCP / IP клиентам DHCP. Сюда входит информация о маске подсети, IP-адреса шлюза по умолчанию и адреса системы доменных имен (DNS).
DHCP - это протокол клиент-сервер, в котором серверы управляют пулом уникальных IP-адресов, а также информацию о параметрах конфигурации клиента и назначают адреса из этих пулов адресов. Клиенты с поддержкой DHCP отправляют запрос на сервер DHCP всякий раз, когда они подключаются к сети.
Клиенты, настроенные DHCP, передают запрос на сервер DHCP и запрашивают информацию о конфигурации сети для локальной сети, к которой они присоединены. Клиент обычно транслирует запрос для этой информации сразу после загрузки. DHCP-сервер отвечает на запрос клиента, предоставляя информацию о конфигурации IP, ранее указанную сетевым администратором. Это включает в себя определенный IP-адрес, а также период времени, также называемый арендой, для которой распределение действительно. При обновлении задания DHCP-клиент запрашивает одни и те же параметры, но DHCP-сервер может назначить новый IP-адрес на основе политик, установленных администраторами.
DHCP-сервер управляет записью всех IP-адресов, которые он назначает сетевым узлам. Если узел перемещается в сети, сервер идентифицирует его, используя его адрес управления доступом к среде передачи (MAC), что предотвращает случайную настройку нескольких устройств с одним и тем же IP-адресом.
DHCP не является маршрутизируемым протоколом и не является безопасным. DHCP ограничен конкретной локальной сетью (LAN), что означает, что один DHCP-сервер для каждой локальной сети является достаточным или два сервера для использования в случае отказа. Более крупные сети могут иметь глобальную сеть (WAN), содержащую несколько отдельных мест. В зависимости от соединений между этими точками и количеством клиентов в каждом месте можно настроить несколько DHCP-серверов для обработки адресов. Если сетевые администраторы хотят, чтобы DHCP-сервер предоставлял адресацию нескольким подсетям в данной сети, они должны настроить службы ретрансляции DHCP, расположенные на соединительных маршрутизаторах, что запросы DHCP должны пересекаться. Эти агенты ретранслируют сообщения между клиентами DHCP и серверами, расположенными в разных подсетях.
DHCP не имеет встроенного механизма, позволяющего клиентам и серверам аутентифицировать друг друга. Оба уязвимы для обмана (один компьютер притворяется другим) и атаковать, когда клиенты-изгои могут исчерпать пул IP-адресов DHCP-сервера.
Статические и динамические аренды DHCP
При динамическом DHCP клиент не имеет назначенного ему IP-адреса, а вместо этого «арендует» его в течение определенного периода времени. При каждом включении устройства с динамическим IP-адресом он должен связываться с сервером DHCP для аренды другого IP-адреса. Беспроводные устройства - это примеры клиентов, которым назначены динамические IP-адреса при их подключении к сети.
Устройства, назначенные статическим IP-адресам, имеют постоянные IP-адреса и используются для таких устройств, как веб-серверы или коммутаторы.
При динамической настройке DHCP клиенту также может потребоваться выполнить определенные действия, которые приведут к завершению его IP-адреса, а затем снова подключиться к сети с использованием другого IP-адреса. Время аренды DHCP может варьироваться в зависимости от того, как долго пользователю будет необходимо подключение к Интернету в определенном месте. Устройства выпускают свои IP-адреса, когда истекает срок их аренды DHCP, а затем запрашивают обновление с сервера DHCP, если они находятся в сети. DHCP-сервер может назначать новый адрес, а не обновлять старый.
Типичный динамический цикл аренды DHCP выглядит следующим образом:
Клиент получает аренду IP-адреса через процесс распределения запроса с сервера DHCP.
Если клиент уже имеет IP-адрес из существующего лизинга, он должен будет обновить свой IP-адрес при его перезагрузке после его завершения и обратиться к DHCP-серверу, чтобы перераспределить IP-адрес.
Как только аренда активна, клиент, как говорят, связан с арендой и адресом.
По истечении срока аренды клиент свяжется с сервером, который изначально предоставил наименьшее количество обновлений, чтобы он мог продолжать использовать свой IP-адрес.
Если клиент перемещается в другую сеть, его динамический IP-адрес будет прекращен и он запросит новый IP-адрес с DHCP-сервера новой сети.
package net.floodlightcontroller.dhcpserver;
import net.floodlightcontroller.core.*;
import net.floodlightcontroller.core.internal.IOFSwitchService;
import net.floodlightcontroller.core.module.FloodlightModuleContext;
import net.floodlightcontroller.core.module.FloodlightModuleException;
import net.floodlightcontroller.core.module.IFloodlightModule;
import net.floodlightcontroller.core.module.IFloodlightService;
import net.floodlightcontroller.core.types.NodePortTuple;
import net.floodlightcontroller.dhcpserver.web.DHCPServerWebRoutable;
import net.floodlightcontroller.packet.DHCP;
import net.floodlightcontroller.packet.Ethernet;
import net.floodlightcontroller.packet.IPv4;
import net.floodlightcontroller.restserver.IRestApiService;
import net.floodlightcontroller.staticentry.IStaticEntryPusherService;
import net.floodlightcontroller.core.IOFSwitchListener;
import net.floodlightcontroller.topology.ITopologyService;
import net.floodlightcontroller.util.OFMessageUtils;
import org.projectfloodlight.openflow.protocol.*;
import org.projectfloodlight.openflow.types.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* SDN DHCP Server
* @author Ryan Izard, rizard@g.clemson.edu, ryan.izard@bigswitch.com
* @edited Qing Wang, qw@g.clemson.edu on 1/3/2018
*
* This module implementing a DHCP DHCPServer. The module can be configured with the REST API.
*
*/
public class DHCPServer implements IOFMessageListener, IOFSwitchListener, IFloodlightModule, IDHCPService {
protected static final Logger log = LoggerFactory.getLogger(DHCPServer.class);
protected IFloodlightProviderService floodlightProviderService;
protected IOFSwitchService switchService;
protected IRestApiService restApiService;
protected ITopologyService topologyService;
protected IStaticEntryPusherService staticEntryPusherService;
private static Map<String, DHCPInstance> dhcpInstanceMap;
private static volatile boolean enableDHCPService = false;
private static volatile boolean enableDHCPDynamicService = false;
private static ScheduledThreadPoolExecutor leasePoliceDispatcher;
private static long DHCP_SERVER_CHECK_EXPIRED_LEASE_PERIOD_SECONDS = 10; // 10 secs as default
@Override
public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
Ethernet eth = IFloodlightProviderService.bcStore.get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
OFPort inPort = OFMessageUtils.getInPort((OFPacketIn) msg);
if (!isDHCPEnabled()) return Command.CONTINUE;
if (!DHCPServerUtils.isDHCPPacketIn(eth)) return Command.CONTINUE;
NodePortTuple npt = DHCPServerUtils.getNodePortTuple(sw, inPort);
VlanVid vid = DHCPServerUtils.getVlanVid((OFPacketIn) msg, eth);
if (!getInstance(npt).isPresent() && !getInstance(sw.getId()).isPresent() && !getInstance(vid).isPresent()) {
log.warn("Could not locate DHCP instance for DPID {}, port {} or VLAN {}", new Object[] {sw.getId(), inPort, vid});
return Command.CONTINUE;
}
DHCPInstance instance = null;
if (getInstance(sw.getId()).isPresent()) {
instance = getInstance(sw.getId()).get();
}
else if (getInstance(npt).isPresent()) {
instance = getInstance(npt).get();
}
else {
instance = getInstance(vid).get();
}
synchronized (instance.getDHCPPool()) {
if (!instance.getDHCPPool().isPoolAvailable()) {
log.info("DHCP Pool is full, trying to allocate more space");
return Command.CONTINUE;
}
}
DHCP dhcPayload = DHCPServerUtils.getDHCPayload(eth);
IPv4Address srcAddr = ((IPv4) eth.getPayload()).getSourceAddress();
IPv4Address dstAddr = ((IPv4) eth.getPayload()).getDestinationAddress();
MacAddress srcMac = eth.getSourceMACAddress();
switch (DHCPServerUtils.getOpcodeType(dhcPayload)) {
case REQUEST:
processDhcpRequest(dhcPayload, sw, inPort, instance, srcAddr, dstAddr, srcMac);
return Command.STOP;
default:
break;
}
return Command.CONTINUE;
}
private void processDhcpRequest(DHCP dhcpPayload, IOFSwitch sw, OFPort inPort, DHCPInstance instance,
IPv4Address srcAddr, IPv4Address dstAddr, MacAddress srcMac) {
DHCPMessageHandler handler = new DHCPMessageHandler();
switch (DHCPServerUtils.getMessageType(dhcpPayload)) {
case DISCOVER:
OFPacketOut dhcpOffer = handler.handleDHCPDiscover(sw, inPort, instance, srcAddr, dhcpPayload, enableDHCPDynamicService);
log.info("DHCP DISCOVER message received from switch {} for client interface {}, handled by dhcp instance {} ... ",
new Object[]{sw.getId().toString(), srcMac.toString(), instance.getName()});
sw.write(dhcpOffer);
break;
case REQUEST:
OFPacketOut dhcpReply = handler.handleDHCPRequest(sw, inPort, instance, dstAddr, dhcpPayload);
log.info("DHCP REQUEST message received from switch {} for client interface {}, handled by dhcp instance {} ... ",
new Object[]{sw.getId().toString(), srcMac.toString(), instance.getName()});
sw.write(dhcpReply); // either ACK or NAK
break;
case RELEASE: // clear client IP (e.g. client shut down, etc)
log.debug("DHCP RELEASE message received from switch {}, start handling... ", sw.getId().toString());
handler.handleDHCPRelease(instance, dhcpPayload.getClientHardwareAddress());
break;
case DECLINE: // client found assigned IP invalid
log.debug("DHCP DECLINE message received from switch {}, start handling... ", sw.getId().toString());
handler.handleDHCPDecline(instance, dhcpPayload.getClientHardwareAddress());
break;
case INFORM: // client request some information
log.debug("DHCP INFORM message received from switch {}, start handling... ", sw.getId().toString());
OFPacketOut dhcpAck = handler.handleDHCPInform(sw, inPort, instance, dstAddr, dhcpPayload);
sw.write(dhcpAck);
break;
default:
break;
}
}
@Override
public String getName() {
return "dhcpserver";
}
@Override
public boolean isCallbackOrderingPrereq(OFType type, String name) {
return false;
}
@Override
public boolean isCallbackOrderingPostreq(OFType type, String name) {
return (type.equals(OFType.PACKET_IN) && name.equals("forwarding"));
}
@Override
public Collection<Class<? extends IFloodlightService>> getModuleServices() {
Collection<Class<? extends IFloodlightService>> s =
new HashSet<Class<? extends IFloodlightService>>();
s.add(IDHCPService.class);
return s;
}
@Override
public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
Map<Class<? extends IFloodlightService>, IFloodlightService> m =
new HashMap<Class<? extends IFloodlightService>, IFloodlightService>();
m.put(IDHCPService.class, this);
return m;
}
@Override
public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {