Этот материал создан коллективными усилиями преподавателя и студента. Первый и четвертый этапы были разработаны студентом, второй и третий — преподавателем, а пятый этап — результат совместной работы.
Этап первый – событие или инцидент
Попав на второй курс, я начал полноценное обучение по своей специальности техника связи. И одним из важнейших направлений была 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/
