Страница 1 из 1

Канал между linux и cisco (GRE) - всё руками

Добавлено: 07 окт 2014, 11:35
RomA
Предпосылки:
- Однажды мой домашний провайдер решил, что пользователей надо защищать, и закрыл 25 порт...
- Часто, в целях безопасности, доступ дают на конкретный IP, а у меня дома динамический адрес...

Задача:
Необходимо связать домашнюю сеть с сервером во вне.

Дано:
- Сервер в интернете под управлением Linux Ubuntu 3.13.0-24
- Домашняя сеть с выходом в интернет через Cisco 1841

Теория:
Самый простой свособ - это создать GRE туннель между 2мя устройствами.
Технология весьма проста, но имеет ряд минусов, а именно:
1) некоторые провайдеры режут GRE, а значит не везде заработает
2) трафик между точка не шифруется, а значит есть вероятность в вашу домашнюю сеть кто нить влезет

Итак, что же мы сделаем? Мы через интернет между 2мя интернетовскими IP
ДОМ (ХХХ.ХХХ.ХХХ.ХХХ)
и
LINUX (YYY.YYY.YYY.YYY)
поднимем туннель
ДОМ (192.168.0.2)
и
LINUX (192.168.0.1)
GRE-tunnel.png
Реализация:

На стороне cisco:

Код: Выделить всё

interface Tunnel0
 ip address 192.168.0.2 255.255.255.0
 ip mtu 1420
 tunnel source FastEthernet0/0
 tunnel destination YYY.YYY.YYY.YYY
Где FastEthernet0/0 - это интерфейс который смотрит в интернет - то есть тот, что с интернетовским IP адресом.

На стороне linux:

Код: Выделить всё

root@vps:~# ip tunnel del gre1
root@vps:~# ip tunnel add gre1 mode gre local YYY.YYY.YYY.YYY remote ХХХ.ХХХ.ХХХ.ХХХ ttl 255 
root@vps:~# ip link set gre1 up 
root@vps:~# ip address add 192.168.0.1/24 dev gre1
В итоге на линуксе мы имеем
gre1 Link encap:UNSPEC HWaddr BC-E2-8A-BB-00-00-00-00-00-00-00-00-00-00-00-00
inet addr:192.168.0.1 P-t-P:192.168.0.1 Mask:255.255.255.0
inet6 addr: fe80::200:5efe:bce2:8abb/64 Scope:Link
UP POINTOPOINT RUNNING NOARP MTU:1476 Metric:1
RX packets:9 errors:0 dropped:0 overruns:0 frame:0
TX packets:12 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:836 (836.0 B) TX bytes:1052 (1.0 KB)
Попробуем работоспособность тунеля
root@vps:~# ping 192.168.0.2
PING 192.168.0.2 (192.168.0.2) 56(84) bytes of data.
64 bytes from 192.168.0.2: icmp_seq=1 ttl=255 time=59.2 ms
64 bytes from 192.168.0.2: icmp_seq=2 ttl=255 time=58.5 ms
Работает :-) теперь надо прописать маршруты, поднять наты и всё такое :-)

Начнём с малого - сделаем так, что бы сервер видел нашу домашнюю сеть. Циска сама умная, а вот сервер прийдётся пнуть - для того что бы он знал о нашей сети ему надо явно прописать маршрут до неё

Код: Выделить всё

root@vps:~# /sbin/route add -net 192.168.10.0 netmask 255.255.255.0 gre1
Подведём итог этой части - мы сделали тунель между двумя подсетями и теперь можем обмениваться данными с сервером, как в своей локальной сети.

Канал между linux и cisco (GRE) - автоматизация

Добавлено: 29 окт 2014, 08:25
RomA
В первой части мы настроили тунель, проверили что он работает - так сказать, заложили фундамент. Но, если циска (а в нашем случаем именно она не имеет статического IP) изменит адрес, то тунель пропадёт. Надо это предусмотреть и автоматизировать.

Что же нам надо:
1) Знать новый IP адрес
2) Убрать старый тунель
3) построить тунель с новым IP адресом

Из этого вытекает схема работы:
1) Cisco рассказывает свой адрес серверу
2) Сервер переодически проверяет не сообщили ли ему новый адрес
2.1) Если новый адрес сообщён - удаляем старый и делаем новый тунель

Ну раз есть план - его надо реализовать. Начнём с Cisco. Заставим её раз в 10ь минут ломиться к нам на сервер с целью спалить её IP адрес :-)

Код: Выделить всё

cisco#conf t
cisco(config)#ip sla monitor 1
cisco(config-sla-monitor)#type http operation get url http://YYY.YYY.YYY.YYY/myip.php?key=password
cisco(config-sla-monitor-http)#frequency 600
cisco(config)#ip sla monitor schedule 1 life forever start-time now
Для того, что бы написать строчку адреса вы должны:
1) написать часть до знака вопроса
2) нажать Ctrl+v
3) написать знак вопроса
4) написать оставшуюся часть
В противном случае знак вопроса будет показывать вам справку )

Проверить что циска вас правильно поняла можно командой

Код: Выделить всё

show ip sla monitor configuration
Посмотрите - верно ли она преобразовала, и преобразовала ли вообще ваше имя ресурса в IP адрес, ну если вы указывали имя в ссылке, а не IP.
Увидеть статус текущей работы можно командой

Код: Выделить всё

show ip sla monitor statistics
Так же не помешает посмотреть и с логи веб-сервера на другой стороне, что бы убедиться что запрос идёт туда, куда надо, особенно если у вас на этом сервер много разных имён. Так я заметил что в конфете циски я указал одно имя, но запрос пришёл на другой виртуахост, где скрипта не было, и который был совсем не связан с тем, что я прописал в конфиге. Хотя статистика показывала что циска правильно резольвит то имя, что было прописано

Ну вот с циской и всё. Пошли на сервер. Первым делом сделаем достоверную ссылку. Для этого на нашем вебсервере сделаем файлик, который указали в ссылке.

Код: Выделить всё

touch myip.php?
следующего содержания (ну там со своими путями и модификациями, конечно)

Код: Выделить всё

<?php

$fileIp = '/var/www/php/ip.txt';
$fileMyIp = '/tmp/ip.txt';

$myIp = $_SERVER['REMOTE_ADDR'];

if($_GET['key']=='password'){
    if($myIp==file_get_contents($fileIp)) {
        echo $myIp;
    } else {
        $fp = fopen($fileIp, 'w');
        fwrite($fp, $myIp);
        fclose($fp);
        $fp = fopen($fileMyIp, 'w');
        fwrite($fp, $myIp);
        fclose($fp);
    }

} else { 
    echo $myIp;
    }

?>
Что делает файл:
1) Если новый IP совпадает со старым - ничего
2) Если новый IP и правда новый - создаст файлик в который запишет новый IP (вот с этим файликом мы и будем потом работать)
3) Для защиты используется ключ - некий аналог пароля

В качестве ещё одной ограничительной меры применяется ограничение по IP адресам. Сделано это так - на страничке
http://bgp.he.net было введено имя моего провайдера и получен список подсетей, которые ему принадлежат и которые отправились в коняги моего вебсервера, в качестве которого у меня применяется nginx - в коняги соответствующего виртауалхоста было добавлено следующее ограничение (вам необходимо подставить диапазон, выделенный вашему провайдеру)

Код: Выделить всё

    location /ip/ {
	allow	1.1.1.0/20;
	allow	2.2.2.0/21;
	allow	3.3.3.0/20;
	deny	all;
    
	location ~ \.php$ {
	    fastcgi_pass unix:/var/run/php5-fpm.sock;
	    fastcgi_index index.php;
	    fastcgi_param SCRIPT_FILENAME  $document_root$fastcgi_script_name;
	    include        fastcgi_params;
	}

    }    
Хочу обратить ваше внимание, что тут я делаю права на определённую директорию - я приведу этот пример, потому что столкнулся с несколько неочевидно вещью. Так вы можете ограничить доступ к директории, но если ваш скрипт написан на, скажем, php, как в нашем случае, то доступ к нему ограничиваться не будет. что бы ограничить доступ к нему надо в описании этой же директории, где вы ставите ограничение добавить строки для php, как это показано в данном примере. Описание получилось путанное, но вы поймёте, когда столкнётесь)))

В общем размещаем, проверяем, смотрим, убеждаемся что эта часть работает и идём дальше.
Ну а дальше размещаем ещё один файлик, назовём его gre.sh

Код: Выделить всё

touch gre.sh
chmode +x gre.sh
Следующего содержания

Код: Выделить всё

#!/bin/sh
start(){ 

remoteip=`/bin/cat /tmp/ip.txt`
echo "remote IP:" $remoteip

echo "Starting GRE...                 " 
ip tunnel del gre1 
ip tunnel add gre1 mode gre local YYY.YYY.YYY.YYY remote $remoteip ttl 255 
ip link set gre1 up 
ip address add 192.168.0.1/30 dev gre1 
 
echo "Tunnel OK" 
/sbin/route add -net 192.168.10.0 netmask 255.255.255.0 gre1

rm /tmp/ip.txt
 
} 

onestart(){ 

remoteip=`/bin/cat /var/www/php/ip.txt`
echo "remote IP:" $remoteip

echo "Starting GRE...                 " 
ip tunnel del gre1 
ip tunnel add gre1 mode gre local 188.226.138.187 remote $remoteip ttl 255 
ip link set gre1 up 
ip address add 192.168.0.1/30 dev gre1 
 
echo "Tunnel OK" 
/sbin/route add -net 192.168.10.0 netmask 255.255.255.0 gre1

} 

stop(){ 
ip tunnel del gre1 
} 

check(){ 
if [ -f /tmp/ip.txt ]; then
    start
#else
#    echo 'No file, no new tunnel'
fi
} 
 
case "$1" in 
start) 
    start 
    ;; 
onestart) 
    onestart 
    ;; 
stop) 
    stop 
    ;; 
check) 
    check 
    ;; 
*) 
echo "Usage: $0 start|stop|onestart|check " 
    ;; 
esac 
Ну тут всё стандартно - запускаем в ключиками
stop - убрать тунель
start - поднять тунель
check - проверка не изменился ли IP, и если да, то перестроить тунель
onestart - поднятие тунель при перезагрузки сервера

Забиваем его в крон - у меня это раз в 10ь минут

Код: Выделить всё

*/10 *	* * *	root	/tmp/gre.sh check
Не забудьте, что вы должны поставить свои пути к файлам.

Для того, что бы тунель заработал при перезагрузки добавим в файл /etc/rc.local следующую строку

Код: Выделить всё

/tmp/gre.sh onestart &
подведём итог - к итогу первой части у нас добавилось некое управление туннелем, а так же автоматическая его перестройка при изменении IP адреса cisco

Канал между linux и cisco (GRE) - DNS и прочие радости жизни

Добавлено: 20 ноя 2014, 23:21
RomA
Вступление:
Итак, канал между нами поднимается, но есть вещи, которые требуют знания домашнего IP как такового. Из первого что приходит в голову:
1) файрвол рубит все соединения, но открыт для домашнего ИП адреса на случай чего
2) мониторинг осуществляется через инет, а не по каналу, на всякий случай
3) в конце концов на домашнем IP висят нужные вещи, так, скажем, вторичный ДНС или просто удалённый рабочий стол
Таким образом следующим шагом является уход от изменчивого IP адреса домашней сети в пользу ДНС имени - то есть будем творить свой собственный DDNS.

Дано:
Данный текст подразумевает что на сервере уже стоит ДНС сервер bind на котором крутится некая зона cz6.ru - все действия будут выполняться только на нём

Решение:
За основу была взята схожая статья http://help.ubuntu.ru/wiki/динамический ... ими_руками где люди уже изобрели велосипед и нам оставалось только повторить его - потому описание будет беглое - в оригинале всё рассказано.
В директории /etc/bind были созданы ключики

Код: Выделить всё

sudo dnssec-keygen -b 512 -a HMAC-MD5 -v 2 -n HOST myip.cz6.ru
там же правим файлик keys.conf в который дописываем нашу белиберду, которую получили от предыдущей команды - информация будет находиться в файле с расширение key после цифры 157

Код: Выделить всё

key myip.cz6.ru. {
algorithm "HMAC-MD5";
secret "rID+Cu8PXrDa9Gk1DwzgdgsabteHGVKjhgvv4jkvggj3bhkhgE+YqmtWk3JWdDKA==";
};
Подключаем получившийся файл к основной конфигурации ДНС /etc/bind/named.conf

Код: Выделить всё

include "/etc/bind/keys.conf";
Теперь надо разрешить править саму зону cz6.ru (на этом сервере должен быть type master; у зоны) - добавляем в описание зоны следующее

Код: Выделить всё

    allow-update{
      key myip.cz6.ru;
    };
Таким образом описание зоны будет выглядеть так

Код: Выделить всё

zone "cz6.ru" {
    type master;
    check-names fail;
    forwarders { /* empty! */ };
    allow-transfer { zone_transfer; };
    allow-query { any; };
    file "/etc/bind/master/cz6.ru";
    allow-update{
      key myip.cz6.ru;
    };
};
С ДНС покончили - сохраняем, перезагружаем.


В Ubuntu мне пришлось ещё подправить файлик /etc/apparmor.d/usr.sbin.named на предмет записи в директорию /etc/bind - таким образом строка в файле выглядит так

Код: Выделить всё

/etc/bind/** rw,
после чего демон надо перезапустить

Код: Выделить всё

/etc/init.d/apparmor reload
иначе эта штука не даст писать в директорию апдейты зоны - подробнее описано тут http://notessysadmin.com/oshibki-named-bind
[/color][/i]

Теперь в любом удобном месте создаёте скрипит, который будет работать с ДНС зоной

Код: Выделить всё

touch dnsupdate.sh
chmod +x dnsupdate.sh
следующего содержания

Код: Выделить всё

#!/bin/bash
TTL=3600
SERVER=localhost
HOSTNAME=myip.cz6.ru
ZONE=cz6.ru
KEYFILE=/etc/bind/Kmyip.cz6.ru.+157+32885.private

new_ip_address=`cat /tmp/ip.txt`

nsupdate -v -k $KEYFILE << EOF
server $SERVER
zone $ZONE
update delete $HOSTNAME A
update add $HOSTNAME $TTL A $new_ip_address
send
EOF

Тут вы домен cz6.ru не поленитесь уж заменить на свой.

Данный скрипт был сопряжён со скриптом из предыдущей статьи - то есть после того, как скрипт обнаружил новый ИП и построил тунель запускается этот скрипт и правит ДНС.