Casto je potreba znat verejnou IP adresu, za kterou se PC schovava. Hodne znamy je web http://www.mojeip.cz/ ktery vsak jde pouzit jenom pres webovy prohlizec. Pokud potrebujeme zjistit IP v terminalu, nebo ve skriptu, museli bychom si napsat parser webove stranky. Z lenosti jsem si napsal vlastni skript na zjistovani adresy. Zde je jednoduchy skript na zjistovani IP v Pythonu:
import socket import thread import sys # -------------------- port = 1234 host = '0.0.0.0' # -------------------- print("Using TCP port %s." % (port)) buf = 1024 addr = (host, port) NL = '\r\n' serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) serversocket.bind(addr) serversocket.listen(500) clients = [serversocket] def handler(clientsocket, clientaddr): print("Accepted connection from: ", clientaddr) clientsocket.settimeout(2) try: data = clientsocket.recv(buf) if "GET" in data or "Host:" in data or "User-Agent" in data: # HTTP request clientsocket.send("HTTP/1.0 200 OK" + NL) clientsocket.send("Content-type: text/plain; charset=us-ascii" + NL) clientsocket.send("Connection: close" + NL) clientsocket.send(NL) clientsocket.send(str(clientaddr[0]) + NL) except socket.timeout: # Telnet request clientsocket.send(str(clientaddr[0]) + NL) except socket.error: # error print("Send to %s error: " % clientaddr) finally: clients.remove(clientsocket) clientsocket.close() while True: try: #print("Server is listening for connections\n") clientsocket, clientaddr = serversocket.accept() clients.append(clientsocket) thread.start_new_thread(handler, (clientsocket, clientaddr)) except KeyboardInterrupt: # Ctrl+C # FIXME print("Closing server socket...") serversocket.close()
Ktery nasledne muzeme zkompilovat pomoci cythonu a spustit:
$ cython --embed getip.py $ gcc getip.c -I/usr/include/python2.7 -lpython2.7 -o getip $ strip getip $ du -sh getip 59K getip $ file getip getip: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=12166ba5208e49ff66eb73820025b860baedc78b, stripped $ $ ./getip Using TCP port 1234.
Automaticke spusteni
Na automaticke spusteni po startu systemu pouzivam /usr/local/bin/getip_start
#!/bin/bash while true; do /usr/local/bin/getip sleep 2 done
a ten se spousti z /etc/rc.local :
root@server:/home/martin# cat /etc/rc.local #!/bin/sh -e # # rc.local # # This script is executed at the end of each multiuser runlevel. # Make sure that the script will "exit 0" on success or any other # value on error. # # In order to enable or disable this script just change the execution # bits. # # By default this script does nothing. # ... nohup su - XXX -c "/usr/local/bin/getip_start" & # XXX je jmeno nejakeho ne-root uzivatele, pod kterym to pobezi # ... exit 0
Pouziti je nasledujici
nc (netcat)
martin@martin:~$ nc ip.vancl.eu 1234 77.78.90.200 martin@martin:~$
Busybox telnet client (OpenWrt, Ubiquity)
martin@martin:~$ /bin/busybox telnet ip.vancl.eu 1234 77.78.90.200 Connection closed by foreign host martin@martin:~$
wget
martin@martin:~$ wget http://ip.vancl.eu:1234/ -qO - 77.78.90.200 martin@martin:~$ martin@martin:~$ wget ip.vancl.eu:1234 -qO - 77.78.90.200 martin@martin:~$
Ubuntu telnet client
martin@martin:~$ telnet ip.vancl.eu 1234 Trying ip.vancl.eu... Connected to ip.vancl.eu. Escape character is '^]'. 77.78.90.200 Connection closed by foreign host. martin@martin:~$
Jak je videt, klasicky telnet klient je nepouzitelne ukecany. Wget funguje dobre, ale kdo si ma pamatovat vsechny jeho parametry? Idealni je netcat (nc), ten vsak zvlast v embedded systemech neni.
Jak to funguje
Po spusteni zacne skript poslouchat na TCP 0.0.0.0:1234. Kdyz se nekdo pripoji, vrati mu IP a ukonci spojeni. U telnetu to tak funguje, webove prohlizece Firefox/Chrome take nemaji problem.
Pokud se vsak zkusime pripojit wgetem, wget vypise hromadu chybovych hlasek o chybejicih HTTP hlavickach. Proto jsem udelal maly hack. Skript po navazani spojeni ceka 2s. Pokud behem teto doby prijme nejake HTTP hlavicky, posle odpoved jako validni HTTP odpoved. Kdyz hlavicky neprijdou, posle jenom plain text adresu a zalomeni radku.
Odkaz na Gist, kde bude vzdy aktualni verze.