Я следил за инструкциями Использование переадресации протоколов на Виртуальной платформе Google. Итак, теперь у меня есть что-то вроде этого:
$ gcloud compute forwarding-rules list
NAME REGION IP_ADDRESS IP_PROTOCOL TARGET
x-fr-1 us-west1 104.198.?.?? TCP us-west1-a/targetInstances/x-target-instance
x-fr-2 us-west1 104.198.?.?? TCP us-west1-a/targetInstances/x-target-instance
x-fr-3 us-west1 104.198.??.??? TCP us-west1-a/targetInstances/x-target-instance
x-fr-4 us-west1 104.198.??.??? TCP us-west1-a/targetInstances/x-target-instance
x-fr-5 us-west1 104.198.?.??? TCP us-west1-a/targetInstances/x-target-instance
(Примечание: имена были изменены, а вопросительные знаки были заменены. Я не уверен, что важно сохранить эти личные, но лучше безопасные, чем извините.)
Мой экземпляр "x" находится в "x-target-instance" и имеет пять правил пересылки "x-fr-1" через "x-fr-5". Я запускаю nginx на "x", и я могу получить к нему доступ с любого из 6 внешних IP-адресов (1 для экземпляра + 5 правил пересылки). Пока что так хорошо.
Мне сейчас интересно привязать сервер к этим внешним IP-адресам. Для изучения я попытался использовать Python:
import socket
import time
def serve(ip_address, port=80):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((ip_address, port))
try:
sock.listen(5)
while True:
con, _ = sock.accept()
print con.getpeername(), con.getsockname()
con.send(time.ctime())
con.close()
finally:
sock.close()
Теперь я могу привязать "0.0.0.0", и я получаю интересные результаты:
>>> serve("0.0.0.0")
('173.228.???.??', 57288) ('10.240.?.?', 80)
('173.228.???.??', 57286) ('104.198.?.??', 80)
Когда я общаюсь с сервером на его внешнем IP-адресе, метод getsockname возвращает внутренний IP-адрес экземпляра. Но когда я связываюсь с сервером по внешнему IP-адресу, используемому правилом пересылки, методы "getsockname" возвращают внешний IP-адрес.
Хорошо, теперь я связываю внутренний IP-адрес экземпляра:
>>> serve("10.240.?.?")
('173.228.???.??', 57295) ('10.240.?.?', 80)
Снова я могу общаться с сервером по его внешнему IP-адресу, а метод getsockname возвращает внутренний IP-адрес экземпляра. Это кажется немного странным.
Кроме того, если я пытаюсь связать внешний IP-адрес экземпляра:
>>> serve("104.198.?.??")
error: [Errno 99] Cannot assign requested address
Затем я получаю сообщение об ошибке.
Но если я попытаюсь связать внешние IP-адреса, используемые правилами пересылки, а затем сделать запрос:
>>> serve("104.198.??.???")
('173.228.???.??', 57313) ('104.198.??.???', 80)
Он работает.
Наконец, я смотрю "ifconfig":
ens4 Link encap:Ethernet HWaddr 42:01:0a:??:??:??
inet addr:10.240.?.? Bcast:10.240.?.? Mask:255.255.255.255
inet6 addr: fe80::4001:???:????:2/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1460 Metric:1
RX packets:37554 errors:0 dropped:0 overruns:0 frame:0
TX packets:32286 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:41201244 (41.2 MB) TX bytes:3339072 (3.3 MB)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:9403 errors:0 dropped:0 overruns:0 frame:0
TX packets:9403 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1
RX bytes:3155046 (3.1 MB) TX bytes:3155046 (3.1 MB)
И я вижу только два интерфейса. Очевидно, что возможности Google Cloud Platform Networking превысили то, что я помню, из моего класса Computer Networking в колледже. Подводя итог моим наблюдениям:
- Если я хочу привязываться к внешнему IP-адресу экземпляра, я связываю его внутренний IP-адрес.
- Процесс, связанный с внутренним IP-адресом экземпляра, не может различать IP-адрес назначения между внутренними или внешними IP-адресами экземпляра.
- Один сетевой адаптер "ens4" принимает пакеты, привязанные к любому из внешних IP-адресов экземпляра 6.
И вот мои вопросы:
- Почему я не могу связать внешний IP-адрес экземпляра?
- Как я могу привязывать внешние IP-адреса, используемые правилами пересылки, когда у меня нет связанных сетевых адаптеров?
- Если я хочу ограничить доступ SSH к внешнему IP-адресу экземпляра, должен ли я настроить SSH для привязки внутреннего IP-адреса?
- Если я настрою прокси-сервер HTTP на одном из внешних IP-адресов, используемых правилом пересылки, каким будет исходный IP-адрес прокси-запроса?
- Наконец, и это может быть ошибка, почему список правил пересылки пуст в веб-интерфейсе в https://console.cloud.google.com/networking/loadbalancing/advanced/forwardingRules/list?project=xxx, когда я вижу их с "gcloud compute forwarding-rules list"?