Hola
Hace unos días asistí en el colegio de mi hija a una charla donde debía explicar a qué me dedicaba a los chavales de su clase. Como no sabía por donde meterle mano pensé en explicarles las bases de un algoritmo típico en juegos de mesa contra un openente, el minimax. El algoritmo está suficientemente explicado en muchas páginas como: http://es.wikipedia.org/wiki/Minimax
Por ello, recordando viejos tiempos de facultad me puse a programar el minimax para el juego de las tres en raya. Dejo aquí las distintas clases generadas.
Cada clase y método están suficientemente comentados como para no necesitar añadir nada mas.
1.- Lanzador del aplicativo
package org.dune.juegos;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.UIManager;
import java.awt.SystemColor;
public class TresR {
private JFrame frame;
/**
* Lanzador de la aplicación tres en raya
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
final TresR tr = new TresR();
tr.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Constructor
*/
public TresR() {
//Inicializamos entorno grafico
inicializaPantalla();
}
private void inicializaPantalla() {
//Definimos la pantalla del juego
frame = new JFrame();
frame.setBackground(SystemColor.control);
frame.getContentPane().setBackground(SystemColor.control);
frame.setBounds(100, 100, 800, 600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
//Definimos el contenedor del tablero
final JPanel cajaTablero = new JPanel();
cajaTablero.setBounds(12, 71, 756, 471);
cajaTablero.setBackground(SystemColor.control);
frame.getContentPane().add(cajaTablero);
cajaTablero.setLayout(new BorderLayout(0, 0));
//Definimos la barra de menú
final JMenuBar menuBar = new JMenuBar();
menuBar.setBackground(SystemColor.control);
menuBar.setBounds(0, 0, 780, 21);
frame.getContentPane().add(menuBar);
//Definimos el menú Juego
final JMenu mJuego = new JMenu("Juego");
final JMenuItem smEmpezar = new JMenuItem("Empezar");
final JMenuItem smSalir = new JMenuItem("Salir");
mJuego.add(smEmpezar);
mJuego.add(smSalir);
menuBar.add(mJuego);
//Definimos el menú ayuda
final JMenu mAyuda = new JMenu("Ayuda");
final JMenuItem smInfo = new JMenuItem("Info");
mAyuda.add(smInfo);
menuBar.add(mAyuda);
//Definimos la acción de la opción de menú Empezar
smEmpezar.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
//Pintamos el tablero
final Tablero pTablero = new Tablero();
cajaTablero.removeAll();
cajaTablero.add(pTablero);
frame.setVisible(true);
}
});
//Definimos la acción de la opción de menú Salir
smSalir.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
//Salimos del juego
System.exit(0);
}
});
//Definimos la acción de la opción de menú info
smInfo.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
//Pintamos la pantalla de ayuda
final Info pInfo = new Info();
cajaTablero.removeAll();
cajaTablero.add(pInfo);
frame.setVisible(true);
}
});
}
}
2.- Tablero
package org.dune.juegos;
import java.awt.Button;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.SystemColor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.UIManager;
public class Tablero extends JPanel implements ActionListener {
private static final long serialVersionUID = -6025639950351265124L;
//Botonera que representa el tablero
final Button botonesCasillas[][] = new Button[3][3];
//Estructura de memoria con las casillas del juego
int matrizTablero[][] = new int[3][3];
//Implementación del algoritmo minimax
final MiniMax minimax;
//Indicador de turno de jugador
boolean turnoHumano;
/**
* Constructor del panel
*/
public Tablero() {
//Define el contenido del panel
setBackground(UIManager.getColor("info"));
setLayout(new GridLayout(3, 3, 0, 0));
for (int i=0; i<3; i++) {
for (int j=0; j <3; j++) {
botonesCasillas[i][j] = new Button();
botonesCasillas[i][j].setBackground(SystemColor.control);
botonesCasillas[i][j].setFont(new Font("Arial",Font.BOLD,60));
botonesCasillas[i][j].addActionListener(this);
this.add(botonesCasillas[i][j]);
}
}
//Inicializamos variables de la partida
turnoHumano = true;
//Limpia los botones del tablero
limpiaBotones();
//Iniciamos el minimax
minimax = new MiniMax(3,3);
}
/**
* Interprete de las acciones del usuario.
*/
public void actionPerformed(ActionEvent e){
//Movimiento decidido por el ordenador
Movimiento mov;
//Si el turno era del humano
if(turnoHumano==true){
//Quitamos el turno al humano
turnoHumano = false;
//Revisa qué casilla ha pulsado
for (int i=0;i<3;i++) {
for (int j=0;j<3;j++) {
//Mira si la casilla pulsada por el humaon estaba libre
if ((e.getSource()==botonesCasillas[i][j]) && (botonesCasillas[i][j].getLabel().equals(""))){
//Pone en la casilla una P
botonesCasillas[i][j].setLabel("P");
matrizTablero[i][j] = MiniMax.CASILLA_PERSONA;
//Lanza el algoritmo minimax y recoge el movimiento elegido
mov = minimax.minimax(matrizTablero);
if (mov.getPosX()!=-1 && mov.getPosY()!=-1) {
//Introducimos un retardo
retarda(500);
//Dibujamos el movimiento del ordenador
botonesCasillas[mov.getPosX()][mov.getPosY()].setLabel("O");
matrizTablero[mov.getPosX()][mov.getPosY()]=MiniMax.CASILLA_ORDENADOR;
//Si hay ganador quito el turno al humano para que no pueda mover mas
if(minimax.haGanadoJugador(MiniMax.CASILLA_PERSONA)) {
turnoHumano=false;
JOptionPane.showMessageDialog(null, "ME HAS GANADO");
} else if (minimax.haGanadoJugador(MiniMax.CASILLA_ORDENADOR)) {
turnoHumano = false;
JOptionPane.showMessageDialog(null, "JE JE JE, SIEMPRE GANO YO...");
} else {
turnoHumano = true;
}
} else {
turnoHumano = false;
JOptionPane.showMessageDialog(null, "HEMOS VUELTO A EMPATAR");
}
}
}
}
}
}
private void retarda(int milis){
try {
Thread.sleep(milis);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
/**
* Limpia los botones del tablero
*/
private void limpiaBotones(){
for (int i=0; i<3; i++) {
for (int j=0; j <3; j++) {
botonesCasillas[i][j].setLabel("");
}
}
}
}
3.- Implementación del minimax
package org.dune.juegos;
public class MiniMax {
public static final int CASILLA_VACIA = 0;
public static final int CASILLA_PERSONA = 1;
public static final int CASILLA_ORDENADOR = 2;
private int tableroActual[][];
private int numCols;
private int numFils;
/**
* Recibe los datos del tablero de juego.
*
* @param anchura Dimensión horizontal del tablero.
* @param altura Dimensión vertical del tablero.
*/
public MiniMax(int anchura, int altura) {
super();
this.numCols = anchura;
this.numFils = altura;
this.tableroActual = new int[numCols][numFils];
}
/**
* Es el turno del ordenador y en base al tablero actual decidimos el movimiento a realizar.
*/
public Movimiento minimax(int[][] tableroParam){
this.tableroActual = tableroParam;
int posX=-1;
int posY=-1;
int aux=-9999;
int mejor=-9999;
for (int x=0;x<this.numCols;x++){
for (int y=0;y<this.numFils;y++){
if (isCasillaVacia(x,y)){
marcarCasilla(x,y,CASILLA_ORDENADOR);
aux = min();
if (aux>mejor) {
mejor=aux;
posX=x;
posY=y;
}
marcarCasilla(x,y,CASILLA_VACIA);
}
}
}
return new Movimiento(posX,posY);
}
/**
* El último jugador que marcó alguna casilla fue el ordenador, por lo que analizamos los posibles
* movimientos de la persona.
*
* Si estamos en un nodo hoja devolvemos la valoración del tablero, puede que haya ganado el ordenador
* o puede que sigamos empatados, así que hay dos posibles valores: 1 (gana el ordenador)
* y 0 (seguimos empatados).
*
* Si no es nodo hoja recorremos las casillas vacías simulando ser el jugador humano, y llamando
* a continuación al método MAX. Llamamos a MAX porque en el siguiente turno le tocará jugar a la CPU
* y nos interesa maximizar su resultado.
*/
private int min(){
if (haGanadoJugador(CASILLA_ORDENADOR)){
//Si ha ganado el ordenador devolvemos el valor del tablero
return 1;
} else if (isTableroLleno()){
//Si el tablero está lleno y no ha ganado el ordenador hemos empatado
return 0;
} else {
//Si el tablero no está lleno y no ha ganado el ordenador, recorremos todos
//los posibles movimientos restantes y los valoramos llamando a max()
int aux=9999;
int mejor=9999;
for (int x=0;x<this.numCols;x++){
for (int y=0;y<this.numFils;y++){
if (isCasillaVacia(x,y)){
marcarCasilla(x,y,CASILLA_PERSONA);
aux = max();
if (aux<mejor) {
mejor=aux;
}
marcarCasilla(x,y,CASILLA_VACIA);
}
}
}
return mejor;
}
}
/**
* El último jugador que marcó alguna casilla fue la persona, por lo que analizamos los posibles
* movimientos del ordenador.
*
* Si estamos en un nodo hoja devolvemos la valoración del tablero, puede que haya ganado la persona
* o puede que sigamos empatados, así que hay dos posibles valores: -1 (gana la persona)
* y 0 (seguimos empatados).
*
* Si no es nodo hoja recorremos las casillas vacías simulando ser el ordenador, y llamando
* a continuación al método MIN. Llamamos a MIN porque en el siguiente turno le tocará jugar al humano
* y nos interesa minimizar su resultado.
*/
private int max(){
if (haGanadoJugador(CASILLA_PERSONA)){
//Si ha ganado la persona devolvemos el valor del tablero
return -1;
} else if (isTableroLleno()){
//Si el tablero está lleno y no ha ganado la persona hemos empatado
return 0;
} else {
///Si el tablero no está lleno y no ha ganado la persona, recorremos todos
//los posibles movimientos restantes y los valoramos llamando a min()
int aux=-9999;
int mejor=-9999;
for (int x=0;x<this.numCols;x++){
for (int y=0;y<this.numFils;y++){
if (isCasillaVacia(x,y)){
marcarCasilla(x,y,CASILLA_ORDENADOR);
aux = min();
if (aux>mejor) {
mejor=aux;
}
marcarCasilla(x,y,CASILLA_VACIA);
}
}
}
return mejor;
}
}
/**
* Determina si una determinada posición del tablero está
* o no vacía.
*
* @param x. Fila de la casilla a analizar.
* @param y. Columna de la casilla a analizar.
*
* @return True cuando la casilla está vacía
*/
private boolean isCasillaVacia(int x, int y){
return tableroActual[x][y]==CASILLA_VACIA;
}
/**
* Ocupa la casilla indicada con la ficha recibida.
*
* @param x. Fila de la casilla a marcar.
* @param y. Columna de la casilla a marcar.
* @param ficha. Ficha a colocar.
*/
private void marcarCasilla(int x, int y, int ficha){
tableroActual[x][y]=ficha;
}
/**
* Determina si el tablero tiene casillas libres.
*
* @return True si hay casillas no ocupadas.
*/
private boolean isTableroLleno(){
for (int x=0;x<3;x++){
for (int y=0;y<3;y++){
if (isCasillaVacia(x,y)){
return false;
}
}
}
return true;
}
/**
* Determina si el jugador que maneja la ficha recibida
* por parámetro ha ganado la partida.
*
* @param ficha Ficha que podría haber ganado
*
* @return True cuando el jugador con la ficha recibida ha ganado.
*/
public boolean haGanadoJugador(int ficha){
//Verifica si el jugador ha ganado en las diagonales
if((tableroActual[0][0]==ficha && tableroActual[1][1]==ficha && tableroActual[2][2]==ficha)||
(tableroActual[0][2]==ficha && tableroActual[1][1]==ficha && tableroActual[2][0]==ficha)) {
return true;
} else {
//Verifica si el jugador ha ganado en una fila
for(int i=0;i<3;i++) {
if(tableroActual[i][0]==ficha && tableroActual[i][1]==ficha && tableroActual[i][2]==ficha) {
return true;
}
}
//Verifica si el jugador ha ganado en una columna
for(int i=0;i<3;i++) {
if(tableroActual[0][i]==ficha && tableroActual[1][i]==ficha && tableroActual[2][i]==ficha) {
return true;
}
}
}
return false;
}
}
4.- Clase auxiliar para manejar los movimientos
package org.dune.juegos;
public class Movimiento {
private int posX;
private int posY;
public Movimiento(int posX, int posY) {
super();
this.posX = posX;
this.posY = posY;
}
public int getPosX() {
return posX;
}
public void setPosX(int posX) {
this.posX = posX;
}
public int getPosY() {
return posY;
}
public void setPosY(int posY) {
this.posY = posY;
}
}
Páginas
sábado, 26 de abril de 2014
jueves, 24 de abril de 2014
Gnome 3 (gnome-shell) gestión varios monitores
Hola
Si tenemos nuestro PC conectado a varios monitores y queremos configurar tanto el monitor principal (donde se ubica el lanzador) como la posición del monitor secundario con respecto al primario podemos seguir los siguientes pasos:
1) Lanzar el comando
$ xrandr
2) Ésto generará una salida similar a la siguiente:
Screen 0: minimum 320 x 200, current 3286 x 1080, maximum 32767 x 32767
LVDS1 connected 1366x768+1920+0 (normal left inverted right x axis y axis) 344mm x 193mm
1366x768 60.0*+ 40.0
1360x768 59.8 60.0
1024x768 60.0
800x600 60.3 56.2
640x480 59.9
VGA1 disconnected (normal left inverted right x axis y axis)
HDMI1 connected primary 1920x1080+0+0 (normal left inverted right x axis y axis) 480mm x 270mm
1920x1080 60.0*+ 60.0 50.0 59.9
1680x1050 59.9
1600x900 60.0
1280x1024 60.0
1440x900 59.9
1280x720 60.0 50.0 59.9
1024x768 60.0
800x600 60.3
720x576 50.0
720x480 60.0 59.9
640x480 60.0 59.9
720x400 70.1
DP1 disconnected (normal left inverted right x axis y axis)
VIRTUAL1 disconnected (normal left inverted right x axis y axis)
VGA-1-1 disconnected
3) Nos fijamos en que tenemos varios monitores activos, en el ejemplo anterior tenemos dos: LVDS1 y HDMI1
4) Para hacer que el monitor principal sea HDMI1, que el monitor secundario sea LVDS1 y que el monitor secundario esté a la derecha del primario podemos lanzar el siguiente comando:
$ xrandr --output HDMI1 --primary --mode 1920x1080 --output LVDS1 --mode 1366x768 --right-of HDMI1
5) Ésto efectuará el cambio inmediatamente, con lo que podemos seguir jugando indefinidamente con las opciones de xrandr hasta dar con la configuración deseada. Hay muchas páginas documentando éstos parámetros, como por ejemplo: http://pkg-xorg.alioth.debian.org/howto/use-xrandr.html
6) Una vez definido el ajuste ideal, tenemos que almacenarlo en alguna parte, dado que en el siguiente inicio de sesión se habrá perdido. Seguro que hay una forma mejor de hacerlo, pero mientras investivamos podemos añadir el comando anterior al final del fichero .profile de nuestro $HOME.
P.D. En mi caso todo ésto tiene una pega y es que cuando use el portatil sin el monitor secundario la pantalla del portatil no mostrará el lanzador, en esas ocasiones deberé comentar ésta línea del .profile, seguiremos curioseando para solucionar éste tema.
Un saludo
Si tenemos nuestro PC conectado a varios monitores y queremos configurar tanto el monitor principal (donde se ubica el lanzador) como la posición del monitor secundario con respecto al primario podemos seguir los siguientes pasos:
1) Lanzar el comando
$ xrandr
2) Ésto generará una salida similar a la siguiente:
Screen 0: minimum 320 x 200, current 3286 x 1080, maximum 32767 x 32767
LVDS1 connected 1366x768+1920+0 (normal left inverted right x axis y axis) 344mm x 193mm
1366x768 60.0*+ 40.0
1360x768 59.8 60.0
1024x768 60.0
800x600 60.3 56.2
640x480 59.9
VGA1 disconnected (normal left inverted right x axis y axis)
HDMI1 connected primary 1920x1080+0+0 (normal left inverted right x axis y axis) 480mm x 270mm
1920x1080 60.0*+ 60.0 50.0 59.9
1680x1050 59.9
1600x900 60.0
1280x1024 60.0
1440x900 59.9
1280x720 60.0 50.0 59.9
1024x768 60.0
800x600 60.3
720x576 50.0
720x480 60.0 59.9
640x480 60.0 59.9
720x400 70.1
DP1 disconnected (normal left inverted right x axis y axis)
VIRTUAL1 disconnected (normal left inverted right x axis y axis)
VGA-1-1 disconnected
3) Nos fijamos en que tenemos varios monitores activos, en el ejemplo anterior tenemos dos: LVDS1 y HDMI1
4) Para hacer que el monitor principal sea HDMI1, que el monitor secundario sea LVDS1 y que el monitor secundario esté a la derecha del primario podemos lanzar el siguiente comando:
$ xrandr --output HDMI1 --primary --mode 1920x1080 --output LVDS1 --mode 1366x768 --right-of HDMI1
5) Ésto efectuará el cambio inmediatamente, con lo que podemos seguir jugando indefinidamente con las opciones de xrandr hasta dar con la configuración deseada. Hay muchas páginas documentando éstos parámetros, como por ejemplo: http://pkg-xorg.alioth.debian.org/howto/use-xrandr.html
6) Una vez definido el ajuste ideal, tenemos que almacenarlo en alguna parte, dado que en el siguiente inicio de sesión se habrá perdido. Seguro que hay una forma mejor de hacerlo, pero mientras investivamos podemos añadir el comando anterior al final del fichero .profile de nuestro $HOME.
P.D. En mi caso todo ésto tiene una pega y es que cuando use el portatil sin el monitor secundario la pantalla del portatil no mostrará el lanzador, en esas ocasiones deberé comentar ésta línea del .profile, seguiremos curioseando para solucionar éste tema.
Un saludo
domingo, 26 de enero de 2014
Aprobar exámenes ITIL V3
Hola
Con los siguientes resúmenes de ITIL y los exámanes referenciados, todos los miembros del equipo hemos obtenido la certificación con más de un 80% de acierto.
Resúmenes
1. Estrategia para los Servicios TI.odt
2. Diseño de los Servicios TI.odt
3. Transición de los Servicios TI.odt
4. Operación de los Servicios TI.odt
5. Proceso de Mejora Continua de los Servicios TI.odt
Exámenes
http://www.proprofs.com/quiz-school/story.php?title=itil-foundation-v3-examen-2
http://www.proprofs.com/quiz-school/story.php?title=itil-foundation-v3-examen-3
http://www.proprofs.com/quiz-school/story.php?title=test-itil-foundation-v3
Referencias
http://itilv3.osiatis.es/
Con los siguientes resúmenes de ITIL y los exámanes referenciados, todos los miembros del equipo hemos obtenido la certificación con más de un 80% de acierto.
Resúmenes
1. Estrategia para los Servicios TI.odt
2. Diseño de los Servicios TI.odt
3. Transición de los Servicios TI.odt
4. Operación de los Servicios TI.odt
5. Proceso de Mejora Continua de los Servicios TI.odt
Exámenes
http://www.proprofs.com/quiz-school/story.php?title=itil-foundation-v3-examen-2
http://www.proprofs.com/quiz-school/story.php?title=itil-foundation-v3-examen-3
http://www.proprofs.com/quiz-school/story.php?title=test-itil-foundation-v3
Referencias
http://itilv3.osiatis.es/
jueves, 16 de enero de 2014
Montar una petición PKCS#10 RSA de 2048 bits
PKCS#10 es un estándar para solicitar certificados (definido en la RFC 2986) que define el formato del mensaje a enviar a una CA (por ejemplo la FNMT).
Para generar una de éstas solicitudes podemos usar la herramienta java keytool (estoy usando JDK 1.7.0_51).
Los pasos serían los siguientes:
1) Nos creamos nuestro certificado.
keytool -genkey -alias firma.dune.org -keyalg RSA –keysize 2048 -keystore /home/usuario/dune-keystore.jks
2) Creamos el CSR (Certificate Signing Request) y que en el ejemplo he llamado cert-req.txt
keytool -certreq -keyalg RSA -alias firma.dune.org -file cert-req.txt -keystore /home/usuario/dune-keystore.jks
3) Enviamos a la CA el fichero cert-req.txt
Un saludo
Para generar una de éstas solicitudes podemos usar la herramienta java keytool (estoy usando JDK 1.7.0_51).
Los pasos serían los siguientes:
1) Nos creamos nuestro certificado.
keytool -genkey -alias firma.dune.org -keyalg RSA –keysize 2048 -keystore /home/usuario/dune-keystore.jks
2) Creamos el CSR (Certificate Signing Request) y que en el ejemplo he llamado cert-req.txt
keytool -certreq -keyalg RSA -alias firma.dune.org -file cert-req.txt -keystore /home/usuario/dune-keystore.jks
3) Enviamos a la CA el fichero cert-req.txt
Un saludo
miércoles, 15 de enero de 2014
Alfresco ContentStore sobre NFS
Vamos a montar el contentstore de nuestro server Alfresco en otra máquina accesible mediante NFS.
Para ello necesitaremos montar el servidor NFS en nuestra máquina Ubuntu servidora de disco y el cliente NFS en nuestra la Ubuntu donde corre el Alfresco.
Montar server NFS y dar permisos
1) Descargamos server NFS con el comando:
sudo apt-get install nfs-kernel-server
2) Decidimos qué carpeta vamos a compartir, por ejemplo /home/compartido
3) Editamos el fichero /etc/exports con el comando:
sudo gedit /etc/exports
4) Añadimos la siguiente línea:
/home/compartido ccc.ccc.ccc.ccc(rw,async,no_subtree_check,insecure,all_squash,anonuid=65534,anongid=65534)
Nota 1. Todos los parámetros aparecen perfectamente descritos en la ayuda: man exports
Nota 2. Para sacar los ID de usuario/grupo de la cuenta anónima nobody/nogroup hemos lanzado:
sudo id nobody
5) Publicamos los cambios en la configuración de carpetas compartidas ejecutando el comando:
sudo /usr/sbin/exportfs
6) Levantamos el servidor con el comando:
sudo /etc/init.d/nfs-kernel-server start
Montar el cliente NFS
1) Descargamos el cliente NFS con el comando:
sudo apt-get isntall nfs-common
2) Decidimos en qué carpeta vamos a montar la unidad de red compartida, por ejemplo /home/red/compartido1
3) Montamos la unidad de red compartida vía NFS con el comando:
sudo mount -t nfs sss.sss.sss.sss:/home/compartido /home/red/compartido1
Referencias
- Algunas páginas interesantes son:
http://ubuntuforums.org/showthread.php?t=1356807
https://www.digitalocean.com/community/articles/how-to-set-up-an-nfs-mount-on-ubuntu-12-04
http://www.idevelopment.info/data/Unix/Linux/LINUX_ExportingaFileSystemforNFS.shtml
https://help.ubuntu.com/12.04/serverguide/network-file-system.html
Para ello necesitaremos montar el servidor NFS en nuestra máquina Ubuntu servidora de disco y el cliente NFS en nuestra la Ubuntu donde corre el Alfresco.
Montar server NFS y dar permisos
1) Descargamos server NFS con el comando:
sudo apt-get install nfs-kernel-server
2) Decidimos qué carpeta vamos a compartir, por ejemplo /home/compartido
3) Editamos el fichero /etc/exports con el comando:
sudo gedit /etc/exports
4) Añadimos la siguiente línea:
/home/compartido ccc.ccc.ccc.ccc(rw,async,no_subtree_check,insecure,all_squash,anonuid=65534,anongid=65534)
Nota 1. Todos los parámetros aparecen perfectamente descritos en la ayuda: man exports
Nota 2. Para sacar los ID de usuario/grupo de la cuenta anónima nobody/nogroup hemos lanzado:
sudo id nobody
5) Publicamos los cambios en la configuración de carpetas compartidas ejecutando el comando:
sudo /usr/sbin/exportfs
6) Levantamos el servidor con el comando:
sudo /etc/init.d/nfs-kernel-server start
Montar el cliente NFS
1) Descargamos el cliente NFS con el comando:
sudo apt-get isntall nfs-common
2) Decidimos en qué carpeta vamos a montar la unidad de red compartida, por ejemplo /home/red/compartido1
3) Montamos la unidad de red compartida vía NFS con el comando:
sudo mount -t nfs sss.sss.sss.sss:/home/compartido /home/red/compartido1
Referencias
- Algunas páginas interesantes son:
http://ubuntuforums.org/showthread.php?t=1356807
https://www.digitalocean.com/community/articles/how-to-set-up-an-nfs-mount-on-ubuntu-12-04
http://www.idevelopment.info/data/Unix/Linux/LINUX_ExportingaFileSystemforNFS.shtml
https://help.ubuntu.com/12.04/serverguide/network-file-system.html
miércoles, 9 de octubre de 2013
Ubuntu. Configurar una VPN y el enrutado para separar flujos de tráfico
Al conectar a una VPN solo tenemos conexión a los equipos que se encuentran dentro de la red corporativa. Para tener acceso a internet debemos ajustar el proxy corporativo en N sitios y tenemos herramientas capadas como Skype por lo que perdemos éste acceso.
La solución es simple:
1) Primero vamos a la configuración de VPN, vamos a la pestaña "Ajustes de IPv4", pulsamos el botón "Rutas" y ahi marcamos la opción "Usar esta conexión sólo para los recursos en su red".
2) Conectamos a la VPN y probamos que Skype y el navegador funcionan "sin proxy". Pero ahora resulta que no conectamos al escritorio remoto ni a ningún otro sitio de la red corporativa, por lo que faltan ciertos ajustes.
3) Si queremos acceder a una o varias máquinas de la red corporativa por el tunel VPN sin perder la navegación "externa" deberemos conocer ciertos datos. Lanzamos el comando ifconfig para ver nuestra IP tunel, en mi caso 10.59.200.87:
usuario@maquina:~$ ifconfig
eth4 Link encap:Ethernet direcciónHW xx:xx:xx:xx:xx:xx
Direc. inet:xxx.xxx.xxx.xxx Difus.:xxx.xxx.xxx.xxx Másc:xxx.xxx.xxx.xxx
Dirección inet6: xxxx::xxxx:xxxx:xxxx:xxxx/64 Alcance:Enlace
ACTIVO DIFUSIÓN FUNCIONANDO MULTICAST MTU:1500 Métrica:1
Paquetes RX:108554 errores:0 perdidos:0 overruns:0 frame:0
Paquetes TX:119590 errores:0 perdidos:0 overruns:0 carrier:0
colisiones:0 long.colaTX:1000
Bytes RX:60091563 (60.0 MB) TX bytes:17759382 (17.7 MB)
lo Link encap:Bucle local
Direc. inet:127.0.0.1 Másc:255.0.0.0
Dirección inet6: ::1/128 Alcance:Anfitrión
ACTIVO BUCLE FUNCIONANDO MTU:16436 Métrica:1
Paquetes RX:30496 errores:0 perdidos:0 overruns:0 frame:0
Paquetes TX:30496 errores:0 perdidos:0 overruns:0 carrier:0
colisiones:0 long.colaTX:0
Bytes RX:1496970 (1.4 MB) TX bytes:1496970 (1.4 MB)
tun0 Link encap:UNSPEC direcciónHW 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
Direc. inet:10.59.200.87 P-t-P:10.59.200.87 Másc:255.255.255.255
ACTIVO PUNTO A PUNTO FUNCIONANDO NOARP MULTICAST MTU:1412 Métrica:1
Paquetes RX:1076 errores:0 perdidos:0 overruns:0 frame:0
Paquetes TX:900 errores:0 perdidos:0 overruns:0 carrier:0
colisiones:0 long.colaTX:500
Bytes RX:134470 (134.4 KB) TX bytes:86186 (86.1 KB)
4) Para poder conectar por VPN a cualquier equipo de la red corporativa sin perder la conexión directa a internet en el navegador, skype y demás utilidades, deberemos ajustar las tablas de enrutamiento de nuesto Ubuntu:
sudo route add -net 10.0.0.0 netmask 255.0.0.0 gw 10.59.200.87 dev tun0
Donde 10.0.0.0 son las direcciones IP de la red corporativa a las que necesitaríamos acceder (todas).
Donde 255.0.0.0 es la máscara para la red corporativa.
Donde 10.59.200.87 es la IP que nos han asignado al conectar a la VPN.
Donde tun0 es el interfaz del tunneling.
5) Para poder conectar por VPN únicamente a nuestro PC de la red corporativa sin perder la conexión directa a internet en el navegador, skype y demás utilidades, deberíamos teclear:
sudo route add -net 192.168.0.38 netmask 255.255.255.255 gw 10.59.200.87 dev ppp0
Donde 192.168.0.38 es la dirección IP de la máquina a la que queremos acceder.
Donde 255.255.255.255 es la máscara de red para una única máquina.
Donde 10.59.200.87 es la IP que nos han asignado al conectar a la VPN.
Donde tun0 es el interfaz del tunneling.
Referencias:
http://www.taringa.net/posts/linux/17183350/Configurar-VPN-sin-perder-Internet.html
La solución es simple:
1) Primero vamos a la configuración de VPN, vamos a la pestaña "Ajustes de IPv4", pulsamos el botón "Rutas" y ahi marcamos la opción "Usar esta conexión sólo para los recursos en su red".
2) Conectamos a la VPN y probamos que Skype y el navegador funcionan "sin proxy". Pero ahora resulta que no conectamos al escritorio remoto ni a ningún otro sitio de la red corporativa, por lo que faltan ciertos ajustes.
3) Si queremos acceder a una o varias máquinas de la red corporativa por el tunel VPN sin perder la navegación "externa" deberemos conocer ciertos datos. Lanzamos el comando ifconfig para ver nuestra IP tunel, en mi caso 10.59.200.87:
usuario@maquina:~$ ifconfig
eth4 Link encap:Ethernet direcciónHW xx:xx:xx:xx:xx:xx
Direc. inet:xxx.xxx.xxx.xxx Difus.:xxx.xxx.xxx.xxx Másc:xxx.xxx.xxx.xxx
Dirección inet6: xxxx::xxxx:xxxx:xxxx:xxxx/64 Alcance:Enlace
ACTIVO DIFUSIÓN FUNCIONANDO MULTICAST MTU:1500 Métrica:1
Paquetes RX:108554 errores:0 perdidos:0 overruns:0 frame:0
Paquetes TX:119590 errores:0 perdidos:0 overruns:0 carrier:0
colisiones:0 long.colaTX:1000
Bytes RX:60091563 (60.0 MB) TX bytes:17759382 (17.7 MB)
lo Link encap:Bucle local
Direc. inet:127.0.0.1 Másc:255.0.0.0
Dirección inet6: ::1/128 Alcance:Anfitrión
ACTIVO BUCLE FUNCIONANDO MTU:16436 Métrica:1
Paquetes RX:30496 errores:0 perdidos:0 overruns:0 frame:0
Paquetes TX:30496 errores:0 perdidos:0 overruns:0 carrier:0
colisiones:0 long.colaTX:0
Bytes RX:1496970 (1.4 MB) TX bytes:1496970 (1.4 MB)
tun0 Link encap:UNSPEC direcciónHW 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
Direc. inet:10.59.200.87 P-t-P:10.59.200.87 Másc:255.255.255.255
ACTIVO PUNTO A PUNTO FUNCIONANDO NOARP MULTICAST MTU:1412 Métrica:1
Paquetes RX:1076 errores:0 perdidos:0 overruns:0 frame:0
Paquetes TX:900 errores:0 perdidos:0 overruns:0 carrier:0
colisiones:0 long.colaTX:500
Bytes RX:134470 (134.4 KB) TX bytes:86186 (86.1 KB)
4) Para poder conectar por VPN a cualquier equipo de la red corporativa sin perder la conexión directa a internet en el navegador, skype y demás utilidades, deberemos ajustar las tablas de enrutamiento de nuesto Ubuntu:
sudo route add -net 10.0.0.0 netmask 255.0.0.0 gw 10.59.200.87 dev tun0
Donde 10.0.0.0 son las direcciones IP de la red corporativa a las que necesitaríamos acceder (todas).
Donde 255.0.0.0 es la máscara para la red corporativa.
Donde 10.59.200.87 es la IP que nos han asignado al conectar a la VPN.
Donde tun0 es el interfaz del tunneling.
5) Para poder conectar por VPN únicamente a nuestro PC de la red corporativa sin perder la conexión directa a internet en el navegador, skype y demás utilidades, deberíamos teclear:
sudo route add -net 192.168.0.38 netmask 255.255.255.255 gw 10.59.200.87 dev ppp0
Donde 192.168.0.38 es la dirección IP de la máquina a la que queremos acceder.
Donde 255.255.255.255 es la máscara de red para una única máquina.
Donde 10.59.200.87 es la IP que nos han asignado al conectar a la VPN.
Donde tun0 es el interfaz del tunneling.
Referencias:
http://www.taringa.net/posts/linux/17183350/Configurar-VPN-sin-perder-Internet.html
martes, 8 de octubre de 2013
Salida por el proxy corporativo autenticando en un dominio Windows
En redes Widows se usa NTLM (NT Lan Manager) que es un conjunto de protocolos de Microsoft que proporcionan autenticación, integridad y confidencialidad a los usuarios.
NTLMv2, introducido con Windows NT 4.0 SP4 y soportado por Windows 2000, amplía las capacidades de NTLM al soportar métodos criptográficos más modernos.
Mientras Kerberos ha reemplazado a NTLM como protocolo de autenticación por defecto del Directorio Activo (AD), NTML es aún muy usado.
CNTLM es una implementación libre de NTLM/NTLMv2 que podemos usar en Ubuntu a la hora de autenticarnos a la hora de conectar a través de un proxy que utilice NTLM.
CNTLM se sitúa entre las aplicaciones y los proxy corporativos.
Instalación:
sudo apt-get install cntlm
Configuración:
Editamos el fichero de configuración:
sudo gedit /etc/cntlm.conf
Ajustamos las líneas siguientes:
Username xxxxxxxxxx
Domain yyyyyyyyyy
Password ppppppp
Proxy xxx.xxx.xxx.xxx:pppp
Listen rrrr
Donde xxxxxxxxxx es el nombre de usuario en el dominino.
Donde yyyyyyyyyy es el nombre del dominio.
Donde ppppppp es la password del usuario en el dominio.
Donde xxx.xxx.xxx.xxx es la dirección IP del proxy corporativo
Donde pppp es el puerto del proxy corporativo
Donde rrrr es el puerto del proxy cntlm que deberemos configurar en las aplicaciones de nuestro sistema
Ajuste de aplicativos:
Ya sólo queda ajustar el proxy del sistema apuntanto a localhost:rrrr y el proxy de todos aquellos aplicativos que no dependan de la configuración del proxy a nivel de sistema, por ejemplo wget, apt-get, etc.
Por último reiniciamos la máquina y listo
Parar y arrancar cntlm:
Si necesitamos para el servicio lanzamos:
sudo service cntlm stop
Si necesitamos reiniciar el servicio lanzamos:
sudo service cntlm start
Referencias:
http://cntlm.sourceforge.net/
http://en.wikipedia.org/wiki/NTLM
NTLMv2, introducido con Windows NT 4.0 SP4 y soportado por Windows 2000, amplía las capacidades de NTLM al soportar métodos criptográficos más modernos.
Mientras Kerberos ha reemplazado a NTLM como protocolo de autenticación por defecto del Directorio Activo (AD), NTML es aún muy usado.
CNTLM es una implementación libre de NTLM/NTLMv2 que podemos usar en Ubuntu a la hora de autenticarnos a la hora de conectar a través de un proxy que utilice NTLM.
CNTLM se sitúa entre las aplicaciones y los proxy corporativos.
Instalación:
sudo apt-get install cntlm
Configuración:
Editamos el fichero de configuración:
sudo gedit /etc/cntlm.conf
Ajustamos las líneas siguientes:
Username xxxxxxxxxx
Domain yyyyyyyyyy
Password ppppppp
Proxy xxx.xxx.xxx.xxx:pppp
Listen rrrr
Donde xxxxxxxxxx es el nombre de usuario en el dominino.
Donde yyyyyyyyyy es el nombre del dominio.
Donde ppppppp es la password del usuario en el dominio.
Donde xxx.xxx.xxx.xxx es la dirección IP del proxy corporativo
Donde pppp es el puerto del proxy corporativo
Donde rrrr es el puerto del proxy cntlm que deberemos configurar en las aplicaciones de nuestro sistema
Ajuste de aplicativos:
Ya sólo queda ajustar el proxy del sistema apuntanto a localhost:rrrr y el proxy de todos aquellos aplicativos que no dependan de la configuración del proxy a nivel de sistema, por ejemplo wget, apt-get, etc.
Por último reiniciamos la máquina y listo
Parar y arrancar cntlm:
Si necesitamos para el servicio lanzamos:
sudo service cntlm stop
Si necesitamos reiniciar el servicio lanzamos:
sudo service cntlm start
Referencias:
http://cntlm.sourceforge.net/
http://en.wikipedia.org/wiki/NTLM
Suscribirse a:
Entradas (Atom)