Этот материал создан коллективными усилиями преподавателя и студента. Первый и четвертый этапы были разработаны студентом, второй и третий — преподавателем, а пятый этап — результат совместной работы.
Этап первый – событие или инцидент
Попав на второй курс, я начал полноценное обучение по своей специальности техника связи. И одним из важнейших направлений была IP адресация. Но к моему огромному сожалению, 95% времени мы обучались работе с протоколом IPv4, создавая сети, разбивая их на подсети и изучая специфику этого протокола. Меня это беспокоило, ибо такой фокус на устаревающей технологии пагубно влияет на будущих специалистов.
На 3 курсе я ушёл заниматься кибербезопасностью в Skills Battles, где ещё больше узнал про IP адресацию и наконец то полноценно поработал с IPv6. После этого я загорелся идеей сделать что-то по протоколу IPv6, чтобы обычные обучающиеся узнавали про IPv6 и становились более подкованными в нём.
Этап второй - зачем это надо?
Я, как преподаватель дисциплины Компьютерные сети, понимала необходимость изучения протокола IPv6. Протокол IPv6 больше соответствует современным реалиям. Формат IPv6-адреса составляет 128 бит, которые представлены восемью шестнадцатибитными шестнадцатеричными блоками и разделены двоеточиями.
Если сравнивать с IPv4, то IPv6 имеет следующие достоинства:
маршрутизация становится более эффективной, поскольку пакеты передаются без необходимости фрагментации;
встроена технология QoS, для обеспечения эффективной передачи данных в условиях ограниченных возможностей сети;
устранён механизм преобразования сетевых адресов NAT;
упрощается администрирование сети благодаря автоконфигурации адресов;
уменьшаются затраты на обработку за счёт улучшенной структуры заголовков.
Всем понятно, что будущее за протоколом 6 версии. Но в учебных программах, большее количество часов отведено для изучения 4 версии.
Студентам скучно читать просто теоретический материал, да и скорость усвоения материала у всех разная. Поэтому было решено в рамках дипломного проектирования создать программу по изучению протокола IPv6.
Этап третий - постановка задачи
Мною, как руководителем дипломного проектирования, было разработано и выдано задание разработать приложение, в котором содержится лекционный материал, тесты и практические задания по теме «Протокол IPv6».
Приложение должно иметь функционал регистрации и авторизации пользователей, возможность сохранения результатов и прогресса учащихся, а также страницу для администратора. Администратор должен иметь возможность управлять учетными записями пользователей, просматривать их результаты и удалять пользователей при необходимости.
Этап четвертый - реализация
Так как я имел достаточно опыта в работе с фреймворком для разработки веб приложений – Django, я выбрал его для реализации своей задачи.
В качестве базы данных я выбрал PostgreSQL. Django позволяет легко и быстро создавать приложения и мне отдельно нравится в нём его система маршрутизации и реализация шаблона MVP (Model-View-Presenter). Изначально у меня не было предпочтений в выборе базы данных, но после изучения рынка я пришёл к PostgreSQL. Она была выбрана для получения опыта с релевантной на данный момент базой данных.
Итоговая база данных выглядит так
Было разработано 5 тем, каждая из которых затрагивает ключевые аспекты протокола IPv6.
Для усложнения жизни учащихся и повышения безопасности мной была создана защищённая маршрутизация. Доступ к лекциям, тестам и заданиям возможен только по POST запросам и система адресации Django и csrf токены позволяют так сделать.
Например система генерации и вывода заданий выглядит вот так.
def exercise(request):
if request.POST.get('number') is None:
return redirect('/')
if request.session.get('auth') and request.method == 'POST':
form = dict(request.POST)
num = int(form.get('number')[0])
if num == 3:
addresses = RecordingAddresses.objects.order_by('?')[:12]
id_addresses = []
f_addresses = []
a_addresses = []
i = 0
for address in addresses:
id_addresses.append(address.id)
if i < len(addresses) / 2:
f_addresses.append(address.full_record)
else:
a_addresses.append(address.abbreviation)
i += 1
request.session["id_addresses"] = id_addresses
return render(request, 'tasks/task3.html',
{'auth': request.session.get('auth'), "f_addresses": f_addresses,
"a_addresses": a_addresses})
if num == 4:
task_4_data = []
task_texts = []
for i in range(3):
type_task = random.choice([True, False]) # True - 4 бита False - 5 битов
if type_task:
type_task_text = "подсети "
else:
type_task_text = "интерфейса "
addresses_names =
['a136', 'b062', '7f8c', '974c', 'ff0d', 'cb8b', '8e51', 'afbc',
'11ae', '153f', 'a39f', 'fc97', '0445', '1d4c', '6209', 'ab7a',
'5dc3', '9692', 'd4f1', 'af91', '3c97', '4a0f', '5b60', 'b72b',
'ed0c', '149c', '15dc', '1e69', '687d', 'ba80', '99b9', 'cc8a',
'6358', 'f32e', 'aa29', '4c49', 'b88d', '970e', '3a78', 'f88c',
'b89c', 'da45', '73b6', '180a', '9df3', '85e6', '7f34', '1608',
'd8dd', '719c', '5138', '3f2c', 'a6e8', '22a9', '4eed', '2993',
'f3f8', '5710', '4acc', '2a75', '50a6', '7d28', '8a33', 'fe9a',
'e424', '7d97', '252b', '89f7', '5bd6', '1e4a', '734d', '6bd3',
'1870', 'a633', 'b6b4', '15bf', '7494', '0c7d', '8d98', '2def',
'0ee5', '378b', '8f7d', '6835', 'b0c1', 'f451', 'cc42', '2f39',
'8d51', 'b269', '9729', 'eedc', 'ee80', 'bc4b', 'ce67', 'af69',
'0054', '2329', '7361', '4cbb', 'c368', '7f27', 'a042', 'c5d0',
'3057', 'ee51', 'f62c', '6b13', '1fd0', 'ca8a', '1d23', '3e33',
'1030', '7d04', '61de', '3ae1', '960b', '229f', 'caab', '0000',
'ca32', 'f177', '09f1', '5242', '2883', 'ca35', '2df6', 'bd86']
random.shuffle(addresses_names)
address_name = addresses_names[0] + ':' + addresses_names[1] + ':' + addresses_names[1]
number_of_subnets = random.randint(17, 4080)
task_text = "Произведите разбиение сети " + address_name + ":: на подсети с использованием идентификатора " + type_task_text + "и укажите " + str(
number_of_subnets) + " подсеть."
task_texts.append(task_text)
task_4_data.append([type_task, address_name, number_of_subnets])
request.session["task_4_data"] = task_4_data
return render(request, 'tasks/task4.html',
{'auth': request.session.get('auth'), "tasks": task_texts})
return render(request, 'tasks/task' + str(num) + '.html', {'auth': request.session.get('auth')})
else:
return redirect('/login')
Теперь перейдём к заданиям. Они присутствуют только в 2, 3 и 4 темах.
В задании 2 темы нужно заполнить поля заголовка и указать размеры.
Вот так проходит обработка формы
task = Task.objects.filter(task_number=str(num)).first()
answers = json.loads(task.task_answer)
for i in range(8):
if str(form.get('formChoice' + str(i + 1))[0]) == str(answers['naming'][i]):
result_task += 1
if str(form.get('size' + str(i + 1))[0]) == str(answers['len'][i]):
result_task += 1
grade = calculation_result(16, result_task)if num == 3: for i in range(12):
address = RecordingAddresses.objects.filter(id=request.session["id_addresses"][i]).first()
if i < 6 and str.strip(form['address'][i].lower()) == str.strip(address.abbreviation):
result_task += 1
if i >= 6 and str.strip(form['address'][i].lower()) == str.strip(address.full_record):
result_task += 1
grade = calculation_result(12, result_task)
task_answer = TaskAnswer(task_result=grade, task_id_id=Task.objects.filter(task_number=num).first().id,
user_id_id=request.session['id'])task_answer.save()if grade > "2":
user = User.objects.get(id=request.session['id'])
user.theme_status = user.theme_status[:num - 1] + '1' + user.theme_status[num:]
user.save(update_fields=["theme_status"])return render(request, 'result_task_page.html',
{'result': grade, 'number': num})
В задании 3 темы необходимо сократить и восстановить по 6 адресов.
Для генерации адресов используется вот этот код
addresses = RecordingAddresses.objects.order_by('?')[:12]
id_addresses = []
f_addresses = []
a_addresses = []
i = 0for address in addresses:
id_addresses.append(address.id)
if i < len(addresses) / 2:
f_addresses.append(address.full_record)
else:
a_addresses.append(address.abbreviation)
i += 1request.session["id_addresses"] = id_addressesreturn render(request, 'tasks/task3.html',
{'auth': request.session.get('auth'), "f_addresses": f_addresses, "a_addresses": a_addresses})
А для проверки корректности используется этот код
for i in range(12):
address = RecordingAddresses.objects.filter(id=request.session["id_addresses"][i]).first()
if i < 6 and str.strip(form['address'][i].lower()) == str.strip(address.abbreviation):
result_task += 1
if i >= 6 and str.strip(form['address'][i].lower()) == str.strip(address.full_record):
result_task += 1grade = calculation_result(12, result_task)
Задание 4 темы требует разбиение сети на подсети и указание последней
Данный код генерирует сети и необходимое количество подсетей
task_4_data = []task_texts = []for i in range(3):
type_task = random.choice([True, False]) # True - 4 бита False - 5 битов
if type_task:
type_task_text = "подсети "
else:
type_task_text = "интерфейса "
addresses_names = ['a136', 'b062'] # Их больше
random.shuffle(addresses_names)
address_name = addresses_names[0] + ':' + addresses_names[1] + ':' + addresses_names[1]
number_of_subnets = random.randint(17, 4080)
task_text = "Произведите разбиение сети " + address_name + ":: на подсети с использованием идентификатора " + type_task_text + "и укажите " + str( number_of_subnets) + " подсеть."
task_texts.append(task_text)
task_4_data.append([type_task, address_name, number_of_subnets])request.session["task_4_data"] = task_4_datareturn render(request, 'tasks/task4.html',
{'auth': request.session.get('auth'), "tasks": task_texts})
А данный код проверяет выполненную работу
i = 0for task_data in request.session["task_4_data"]:
number_of_subnets_hex = hex(int(task_data[2]))[2:] # True - 4 бита False - 5 битов
subnet = ":0000:0"
len_num_sub = len(number_of_subnets_hex)
if task_data[0]:
subnet = subnet[:len(subnet) - len_num_sub - 2] + str(number_of_subnets_hex) + ":0"
else:
subnet = (subnet[:len(subnet) - len_num_sub - 1] +
str(number_of_subnets_hex[:len_num_sub - 1]) +
":" + number_of_subnets_hex[len_num_sub - 1:len_num_sub])
ans_address = task_data[1] + subnet + "000:0000:0000:0000"
try:
if ipaddress.IPv6Address(ans_address) == ipaddress.IPv6Address(form.get('address')[i]):
result_task += 1
except:
print("Nop")
i += 1grade = 2 + result_task
Этап пятый - тестирование
Когда Веб приложение было готово, мы протестировали его с помощью студентов-добровольцев. Студенты критичных проблем не выявили. По их отзывам программа интересная, материал дан в доступной форме, а также есть возможность проверить свои знания и умения с помощью тестов и практических заданий.
Веб приложение доступно в открытом репозитории Github https://github.com/GoshArt/DiplomIPv6/
Комментарии (6)
Mamonthful
08.05.2024 12:54NAT имеет и другой функционал, помимо экономии адресов. Это важный элемент безопасности, скрывающий внутреннюю структуру сети. Так что он будет применяться и дальше
omgiafs
08.05.2024 12:54+2Тут сейчас правильные сетевики придут и объяснят, что NAT - это не про безопасность и что думать в таком ключе вредно. И что в IPv6 эта структура тоже вполне себе скрывается. И что у устройства есть локальный и глобальный IPv6 адреса и ещё много интересных штук.
jackcrane
08.05.2024 12:541) сколько % заданий решается через ip калькулятор ?
2) сколько % заданий решается через сниффер ?
3) знают ли соавторы, как называется заучивание этого наизусть ?
но вы продолжайте в том же направлении. и чтобы модель OSI от зубов отлетала.
slonopotamus
08.05.2024 12:54У вас отступы в листингах кода сломались. И подсветку синтаксиса неплохо бы включить.
Vindicar
Как преподаватель скажу: программка ничего так. Абсолютно стандартная база для тестов с парой типов вопросов. На курсовой сойдёт, но не более того. На диплом - даже четвёрка будет с большой натяжкой, разве что специальность студента не связана напрямую с разработкой ПО. Косвенно подтверждается тем, что на гитхабе коммиты идут с середины января по середину февраля. Ну не бывает так, чтобы серьёзный диплом написали так быстро. =)
Во-первых, вся функциональность прекрасно реализуется тем же Moodle. В том числе генерация случайных заданий по формуле. Мудлом сейчас довольно активно пользуются для организации дистанционного обучения, так что вопрос про конкурентный анализ был бы задан одним из первых. А поскольку это опенсорсный движок, обычная отмазка про зависимость от сервис-провайдера не сработала бы.
Во-вторых, хардкод. Его много. Код проверки заданий на подсети содержит захардкоженные строки. Т.е. число нулей в адресе всегда одинаково? Тогда несколько страдает вариативность задания. Захардкожено то, что число заданий по сокращению и развёртыванию IPv6 адресов всегда равное. Захардкожено преобразование процентов в шкалу оценок 2-3-4-5. Захардкожены части адреса для генерации. Хотя тут я вижу почему - это гарантирует, что не проявится ноль, где не нужно, и не изменит ответ.
Ну и до кучи, очень небрежно оформлен пост, просто "на, отвали". Код нечитаем: команды в кучу по нескольку строк, отступы уехали, ссылка в конце кривая и ведёт не куда нужно. Да и на кой код в посте, если есть ссылка на гитхаб?
В общем, удивлён, откуда +5 у поста.
zvzd Автор
Здравствуйте. Спасибо большое, за замечания.