Случается в работе каждого админа такая потребность, как - ходить в удаленную сетку с целью оную удаленно поадминить. Казалось бы тривиальная задача на сегодняшний день. Но в любом деле есть нюансы: разные ОС локальной и гейтовой машин, отсутствие времени, невозможность установить специфический софт, невозможность подружить специфический софт на разных ОС и т.д. Эта статья о том, как поднять вполне себе защищенный полноценный тунель в удаленную сеть из подручных средств…
Задача:
И так дано: удаленная сетка в офисе, у которой гейт на FreeBSD 8.0(7.2 не суть), удаленная машина на Gentoo дома, за натом, и очень надо тунель внутрь рабочей сети
Проблемы:
Вроде бы нет проблем: у фряхи есть кошерный демон MPD (Multi Protocol Daemon), который умеет много, работает с мощной сетевой подсистемой netgraph, которая живет в ядре, в дереве portage есть pptp-client, который юзает нативный демон pppd и все ему причитающееся, говорим emerge поставить, настраиваем, поднимается тунель, все прекрасно, пытаемся зайти по RDP на удаленную винду, пять минут радости и… коннект рвется Долго трясем бубном и понимаем, что проблемма в pptp клиенте, и что качественно запихнуть в кадр оно может только пинги, ssh трафик и всего по мелочи, но когда нужно пропихнуть что-то более существенное (защифрованое и непонятное) при этом используя mppe, mppc: клиент и сервер не могут договориться и рвут коннект. Обидно. Особенно ввиду того, что виндовые ppp клиенты работают наура.
Решение:
Предупреждаю: все ip и адреса вымышлены
Но работать то надо… Мало того: не хочется сильно ни чего такого делать в чем можно зарыться по уши, но при этом очень хочется зашифрованый тунель , а время жаль… И тут, открываем *man ssh и понеслась…
Многие знают о достоинствах openssh, что в легкую можно прокинуть к себе на локальную машину любой порт удаленной машины, которая находиться за гейтом, на котором висит демон ssh… для этого надо выполнить что-то вроде:
ssh -f -N -L 127.0.0.10:3389:10.4.4.10:3389 user@remote_gate.com
а можно и проще:
rem_openport user@remote_gate.com 10.4.4.10 3389
Этой функции по умолчанию нет, она описана ниже в “плюшках”
И совершенно “бесплатно” (то есть без усилий) - мы получаем на 3389 порту, по адресу 127.0.0.10, на loopback интерфейсе локальной машины - RDP порт(3389) машинки с адресом 10.4.4.10, которая живет в своей сети, за гейтом remote_gate.com, и логонимся мы при этом юзером user. Ключами -f -N мы говорим ssh “уйти в бэкграунд” и ничего не выводить в консоль, а ключик -L собственно для редиректа
Волшебный ключик -w
Но это решение не оригинальное и неудобно как-то по каждому чиху открывать тунель для каждого порта и тут мы находим ключик w:
*??
-w tunnel:tunnel
Requests a tun(4) device on the client (first tunnel arg) and server (second tunnel arg). The devices may be specified by numerical ID or the keyword ‘‘any’’, which uses the next available tunnel device. See also the Tunnel directive in ssh_config.
??*
Ага! Вот оно то нам и надо… дальше лезем в гугл, и он нам рассказывает, что мы не первые с такой проблемой Мы пробуем “как там написано” и ничего не получается, или получается, но не так как хотелось бы
И как всегда, мы собираем все в кучу и делаем свое решение, не забывая ссылаться на тех, кто нам помогал (ссылки внизу статьи).
Поднимаем VPN:
Сначала реквизируем “что мы имеем” на обоих концах:
Локальная машина с Gentoo:
modprobe tun
Если не ругнулось - значит модуль есть! Если ругнулось - собираем ядро с опцией --menuconfig, не забывая включить TUN/TAP модуль:
Device Drivers--->
Network device support--->
<M> Universal TUN/TAP device driver support
Затем приводим /etc/conf.d/net к такому виду:
### up your stuff %))
config_tun0=( "10.4.4.200/24" )
preup() {
case ${IFACE} in
tun0)
modprobe tun
ssh -i /root/.ssh/netvpn -S /var/run/tun0-ssh -M -f -w 0:0 remote_gate.com true
sleep 5
;;
esac
return 0
}
postup() {
case ${IFACE} in
tun0)
route add -net 10.4.4.0/24 tun0
;;
esac
return 0
}
postdown() {
case ${IFACE} in
tun0)
ssh -S /var/run/tun0-ssh -O exit remote_gate.com
sleep 2
;;
esac
return 0
}
Знающие люди, тут же зададут вопрос: “и чего - под рутом на удаленку ходим?” ответ: “да”, но не совсем Но об этом позже…
Затем делаем симлинк в init.d директории:
ln -s /etc/init.d/net.lo /etc/init.d/net.tun0
Затем делаем правки в /etc/ssh/sshd_config:
#...
PermitTunnel point-to-point
#...
С локальной машиной практически все. Осталось сгенерить ключи - так как мы люди ленивые и пароль постоянно набивать не хотим, да и портит это картинку вывода runscript-а Но и в этом вопросе мы все равно ленивые, поэтому предлагаю, ставших уже традиционными, немного своих плюшек…
Открываем допустим /root/.bashrc , и рисуем туда малость полезных функций:
### up your stuff %))
[[ -f /etc/init.d/functions.sh ]] && . /etc/init.d/functions.sh
function rem_openport(){
/etc/init.d/sshd stop &>/dev/null
#
_gw="$1"; _tg=$2; _p=$3
node_octets=( `echo -e $_tg | sed -e "s/\./ /g"` )
octet=${node_octets[3]}
forw_str="127.0.0.$octet:$_p:$_tg:$_p"
#
#netstat -ln | grep -o "127.0.0.6:22"
#
ssh -f -N -L $forw_str $_gw
}
#
function rem_makekey(){
kf_name=${2:-"id_dsa"}
#
cur_user=`whoami`
if [ $cur_user = "root" ]; then
_remdir="/root"
else
_remdir="/home/$cur_user"
fi
kf="${_remdir}/.ssh/${kf_name}.pub"
#
if ask "Do you want generate a new key?..."; then
ssh-keygen -N "" -t dsa -f ${_remdir}/.ssh/${kf_name}
chmod 0600 ${_remdir}/.ssh/${kf_name}
fi
#
full_key="$3 `cat ${kf}`"
echo -e ${full_key} | ssh $1 "cat >> ${_remdir}/.ssh/authorized_keys"
if ask "Do you want to delete a .pub key?..."; then
rm -f ${kf}
fi
}
#
function ask(){
einfon "$@ (y/n): " ; read ans
udyesno $ans
}
#
function udyesno(){
[ -z "$1" ] && return 1
case "$1" in
[Yy]|[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) return 0;;
[Nn]|[Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|[Oo][Ff][Ff]|0) return 1;;
esac
}
Смотрим, чтобы локальный .bashrc у нас подтягивался при логоне в любом виде(графическую виртуальную или физическую консоль) делаем
env-update && source/etc/profile
и… генерим в легкую ключик:
rem_makekey remote_gate.com netvpn 'tunnel="0",command="ifconfig tun0 10.4.4.1 10.4.4.200; arp -s 10.4.4.200 auto pub"'
Сами функции я разжевывать не буду, а использование поясню:
Мы говорим функции rem_makekey создать ключики с именем netvpn в каталоге пользователя ~/.ssh/, и прописать публичный ключик на удаленном хосте. При этом удаленным ssh при использовании этого ключика будет подниматься интерфейс tun0, настраиваться так как нам нужно, а также добавлять для него поддержку proxy arp (что ой как немаловажно, иначе можно долго удивляться почему при наличии правильного роутинга машины внутри сети не знают кому все-таки отдать пакет :))
И на этом с локальной машинкой все… Теперь можно сбегать перекурить(попить чаю, поцеловать жену и ребенка - ненужное зачеркнуть) а потом сделаем пару телодвижений на удаленном гейте
Удаленный гейт:
Неважно что используется на удаленном гейте, в моем случае это выше озвученная FreeBSD, действия для всех unix одинаковы. Итак.
Момент раз… - правим /etc/ssh/sshd_config:
#...
PermitRootLogin no
#...
AllowTcpForwarding yes
GatewayPorts yes
#...
PermitTunnel yes
#...
# For Tuneling
Match Host aaa.bbb.ccc.ddd,127.0.0.1
PermitRootLogin yes
Где aaa.bbb.ccc.ddd - это ваш удаленный внешний ip, либо того гейта за которым вы сидите… Оговорка: если такового(ip) нет - то я бы не рисковал открывать возможность такого логона, но и это поправимо (то есть можно описать в конфиге, что рут может коннектится, и только по ключам, и при этом ничего более как написаная в строке ключа комманда выполняться им не может - тогда можно не опасаться за безопасность такого “открытия”). Какие опции можно задавать - можете прочитать в мане самого ssh, ссылка на который выше.
Момент два…
Производим манипуляции с пакетным фильтром на удаленной системе… Так как у меня фряха - я рассказал pf, что во внутренней сети можно гонять пакеты с интерфейса tun0.
Еще оговорка: опять-таки на фряхе по дефолту tun-девайс в ядре, если у Вас на том конце linux и не собран модуль оного - то проводим с ядром манипуляции такие же как и на локальной системе…
Проверяем…
Ну вот и все. Оба конца настроены, пробуем? На локальной машине говорим:
/etc/init.d/net.tun0 start
и наблюдаем примерно следующее:
/etc/init.d/net.tun0 start
* Bringing up interface tun0
* Running preup ...
using interface xx0 for proxy with address 00:b1:8d:e1:10:a2 [ ok ]
* 10.4.4.200/24 ...
* Running postup ...
проверяем:
ifconfig tun0
tun0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
inet addr:10.4.4.200 P-t-P:10.4.4.200 Mask:255.255.255.0
UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 Metric:1
RX packets:10 errors:0 dropped:0 overruns:0 frame:0
TX packets:13 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:500
RX bytes:1329 (1.2 KiB) TX bytes:1232 (1.2 KiB)
ping -c 3 10.4.4.6
PING 10.4.4.6 (10.4.4.6) 56(84) bytes of data.
64 bytes from 10.4.4.6: icmp_seq=1 ttl=63 time=4.39 ms
64 bytes from 10.4.4.6: icmp_seq=2 ttl=63 time=6.13 ms
64 bytes from 10.4.4.6: icmp_seq=3 ttl=63 time=5.98 ms
--- 10.4.4.6 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 4.395/5.506/6.136/0.792 ms
Ура! свершилось
В заключении…
Итого: мы имеем полноценный шифрованый тунель в удаленную сеть, который ходит поверх обычного кошерного ssh, при этом требования к машинам на обоих концах минимальные
Автор гоняет свои “админские пакеты” по тунелю и проблем с оным пока не выявил, канал не падает, работать можно.
В качестве рабочего “промышленного решения” (т. е.) для объединения сетей таким образом, я бы это решение не рекомендовал, ибо такой канал не потянет серьезную нагрузку… Но для удаленного администрирования своего хозяйства - вполне сойдет.
Использованные материалы:
http://ru.gentoo-wiki.com/wiki/HOWTO_Создание_VPN_средствами_OpenSSH
http://www.openbsd.ru/docs/steps/ssh-vpn.html
Удачи и успехов Вам в нашем не легком деле, коллеги!